Community project to make MSCRM easier to customize

ShenpenShenpen Member Posts: 386
edited 2006-01-23 in Dynamics CRM
When I've been to Denmark, I often saw people saying "Navision turns amateurs into professionals." And it is so true, actually, it happened to me, it turned me from a business analyst into a programmer.

MSCRM is different: although customization became easier in 3.0, it is still hard for a consultant with a non-technical background to learn Visual Studio a C# to do very simple customizations.

For example, if users request that when they open an Opportunity form, they should get a message box if any contacts associated will have a birthday in two weeks, you need to 1) write a web service in Visual Studio, compile and configure it, that reads the data from the database 2) write JScript code to the form to show the message box. It is kind of hard.

So, I think we should start thinking together how to make it easier.

1) Having to use two languages instead of one (Jscript and C#/VB.NET) is hard. We could investigate that whether we could write the compiled part in Jscript.NET. It would bring things closer. In a next post, I will copy a little Jscript.NET tutorial here.

2) Borrowing the idea of the Object Table from Navision, we could investigate the idea of creating custom entities to hold the code. Maybe two entities, Project and Code Object, could be the name, and the code itself in a text field. Then, we could write a service that calls the command-line compiler and maybe even copies the files where they belong. Is it a good idea?

Remember, Visual Studio is great, but you don't need it for 95% of typical CRM/ERP customization requests, usually they are very simple, just reading and writing some data.

Any ideas are welcome.

And Merry Xmas!

Do It Yourself is they key. Standard code might work - your code surely works.

Comments

  • ShenpenShenpen Member Posts: 386
    And here is the Jscript.NET tutorial from this page:
    http://www.c-sharpcorner.com/JScript/In ... Script.asp

    We have been hearing the announcement from Microsoft right from PDC2000 that they have realsed new languages viz. C#, VB.NET and JScript.NET
    This artice of mine is going to introduce to u JScript.NET
    Jscript's association with the ECMAScript standard has helped its success considerably, this has led to a close compatibality with JavaScript. The most dramatic impact on performance in JScript.NET is that it is a true compiled language, which makes it possible to achieve performance comparable to that of C# and Visual Basic.NET. As JScript is a part of .NET it automatically benefits from all the goodies .NET offers.

    .NET ships with a compiler for JScript.NET called jsc
    Jscript can be compiled as a .exe or a .dll (default), Jscript can also be used in ASP.NET pages and create web services by specifying "Language=JScript".

    Creating a Simple .exe using JScript Hello.js
    //Copy this line in a file Hello.js
    //Compile it as jsc /exe Hello.js to produce Hello.exe

    print("Hello From Jscript Exe");


    Creating a Simple Class in Jscript : Class.js
    //Copy in a file Class.js
    //Compile it as jsc /exe class.js to produce class.exe

    class Class1
    {
    function sayHi()
    {
    return "Hi from JScript Class";
    }
    }
    var o : Class1 = new Class1;
    print(o.sayHi());


    A Bit of OOPS in JScript.NET : class1.js
    //Copy in a file Class1.js
    //Compile it as jsc /exe Class1.js to produce class1.exe

    class Class1
    {
    function sayHi()
    {
    return "Hi from JScript Class";
    }
    }


    class c2 extends Class1
    {
    protected var name : String; //variable of type string

    function get fname() : String //property get (acessor)
    {
    return this.name;
    }

    function set fname(newName : String) //property let (mutator)
    {
    this.name = newName;
    }

    }

    var o : c2 = new c2;
    print(o.sayHi());
    o.fname = "Manish";
    print(o.fname);



    Creating a Simple WebService in JScript.NET : JSweb.asmx
    <%@ WebService Language ="JScript" Class="MyJS" % >
    import System.Web.Services;
    class MyJS extends WebService
    {
    WebMethodAttribute function sayHi() : String
    {
    return "Hi from a JScript.NET web service";
    }
    }

    JScript.NET blends seemlessly in the .NET framwework and so will other languages like SmallTalk, FujitsuCOBOL and other .NET compatible languages.

    Do It Yourself is they key. Standard code might work - your code surely works.
  • ShenpenShenpen Member Posts: 386
    Finally I managed to install an example customization from the SDK for CRM

    3.0! It is the one called Duplicate Detection - this is a good example of
    typical implementation customizations.

    It consists of two parts:

    1) A web service in ASP.NET/C# that queries the database for Accounts with a same name as the one you are trying to enter.

    2) JScript code in OnSave for calling this service and throwing a nice big
    error if it returns true.

    It was REALLY hard installing it - clearly, MS CRM is much harder than
    Navision for a consultant with a non-technical background. What I managed to find out is ugly and unsafe, but it at leasts works and the later we can harden and refine it.

    First, go to sdk samples/fullsamples/duplicatedetection and read the readme.

    The important stuff is you DO NOT NEED Visual Studio! The readme just tries to tempt you into buying VS, but you don't actually need it.

    What you need is

    a) CSC.EXE which you can find on your CRM Server at

    C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322

    b) wsdl.exe, part of .NET Framework Tools which is a command-line tool, either it is install automatically or f.e. one cand find it at:

    http://www.epcc.ed.ac.uk/~ogsanet/cours ... ial0_2.htm

    Copy the ASPX, the JS file, and wsdl.exe to you CRM server if it's not already there.

    From now on, we are working on the server.

    c) command line: wsdl.exe /out:Microsoft.Crm.Sdk.Wsdl.cs /namespace:CrmSdk [url=http://]http://[/url]<yourserver>/mscrmservices/2006/crmservice.asmx

    Note that it has NOTHING to do with this specific customization: all
    webservices you write which want to acces the CRM database through the CRM web service must use this. In other words, you need to do it only once.

    In my case, <yourserver> was localhost:5555. (It's a testing system.) You can find out what yours is by Start menu, Run, inetmgr and checking the properties of the web sites there.

    D) command line: "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\csc.exe" /t:library Microsoft.Crm.Sdk.Wsdl.cs

    You should have a Microsoft.Crm.Sdk.Wsdl.dll now.

    E) Copy it to Program Files\Microsoft CRM\CRMWeb\bin

    F) Copy the aspx file somewhere, I copied it to

    c:\custom\ISV_DuplicateDetection

    G) Start menu, Run, inetmgr, go to the CRM website, New, Virtual Directory. Now, the SDK suggests ISV_DuplicateDetection as a virtualdir name but I was afraid that underscore might be dangerous so I just named it dupdec. I suggest to try this way first. Then selected that it refers to c:\custom\ISV_DuplicateDetection, and granted all rights except for write. Yes, it is unsafe, but get it to work first and harden it later.

    H) Restart IIS - go up in the inetmgr to the server, right click, all tasks,
    Restart IIS

    I) I tried this stuff by typing
    localhost:5555/dupdec/checkforduplicateaccount.aspx?name=Test. It did not work. After much guessing and scratchin' head what I finally did is that I went to Program Files\Microsoft CRM\CRMWeb\bin and copied all bloody DLL-s to c:\custom\ISV_DuplicateDetection\bin of
    course it is not the right solution, but I dunno how to configure ASP.NET properly. Later we need to find it out I think.

    For testing it works and we can refine it later on. After that it worked from the browser, so I went to the Jscript part.

    J) Start CRM, copy the JScript code to the OnSave event, save, Publish,
    exit, start CRM again, try out and lo and behold! :)

    #TODO:

    - find out the minimum required rights for the virtual directory
    - find out how to avoid copying DLL-s

    The important thing is that you could do it all without Visual Studio.

    For developing such stuff, I suggest to download the free ASP.NET Web
    Matrix. It contaings syntax coloring and a built-in webserver so you can
    test things on-the-fly. You will either need to install it on the server or
    on a box with access to the web services provided by the server.

    I will now play around with the code of these apps and tell you what I find.

    Do It Yourself is they key. Standard code might work - your code surely works.
  • ShenpenShenpen Member Posts: 386
    I played around with customizations - I wanted to write code that makes a
    field mandatory for a business unit only on an Account form.

    General impressions

    - ad-hoc customizations, especially for one without much technical
    background, can be quite hard, however

    - code reusability and structurisation are quite good and once one
    creates a decent library, things can get easier, it looks like a curve where
    the start is hard but if we cleverly generalize developments and build a
    good library, it can turn quite easy in the long run. It will be a hard and
    slow start and I would expect working much more than was planned in the
    first 2-3 projects but afterwards I expect it to become easy.

    The important point is that MSCRM, contrary to Navision, can't be
    implemented alone - a full-time consultant needs a full-time developer to
    build the necessary libraries and services. No other way around.
    This example - make a field mandatory for a business unit - I started to
    write, I am not finished yet but I can tell the general concepts:

    1) The database part: we need a general web service that tells what business stream you are in. I think it's best using the Division Name field for a simple business unit code: f.e. in our company I am in the 273 business stream.

    This web service can be more or less copy-pasted from SDK examples: the WhoAmI from the customroles example and the duplicatedetection example which tells how to generally write ASPX pages that query the database and return data.

    It is a little bit complicated - I am not sure overriding the Render method
    is the simplest way to return data, but it's just a copy-paste and it
    works so no problem.

    The duplicatedetection SDK example offers an elegant way of communication between the database-querying ASPX pages and the Jscript in the CRM client: returning data in XML. Although I like plain text data better (too much Unix blood running in my veins :D ) it is easy to see the advantages of this approach: for example, one can return a node like <result>273</result> if the query is successful and return a node like <error>Division Name field is empty in you Business Unit, please contact the system administrator!</error> if there is an error. It's a nice way to handle errors: then the client-side code can check whether there is an error node and if there is, show the
    error message and die, and if there is no such node, then process the
    results.

    It is not very easy, however, when it's finished, we have a general service
    that tells what business unit we are in - I think we can use it a lot of
    times in the future.

    The question is that should one not generalize it? For example, a service
    that returns any field from any kind of entity?

    2) The client part: we need JScript code to look at this business unit information and check whether the field is populated. If we just try to write this code into the client, it will be a suffering, because it's long and error-prone and have
    to republish and restart the client for evey single change, and writing any
    code in the form event editor is really hard (TAB does'nt work for
    indentation etc.). What we really need is an external JScript library in
    a file, something.js and import it - and this is not covered in the SDK!
    Basically, what this library would provide is a function, that, if we just type
    something like import something.js;
    CheckFieldForBusinessUnit("273","accountnumber");
    Then if we are in the 273 business stream it would check if the account
    number is populated and throw an error message if not. I think this is
    possible, but I am not quite sure how to import libraries and how to turn a string into an object property - I will tinker with it and tell what I
    find.

    Note: the most elegant solution would be to create a new entity, where there is a relation to a Business Unit, and dynamic picklists (such as in the
    dynamic picklist SDK example, by querying the metadatabase) to choose entity and field, I think it is possible, and then it would be completely
    configurable. I think this is possible, but takes some time - one needs to find out how to cycle through XML nodes in JScript to build the picklist and also needs to find out how to cast a string to a method in C#.

    Do It Yourself is they key. Standard code might work - your code surely works.
Sign In or Register to comment.