Friday, April 8, 2011

How To: Use Create Requests in .NET and Jscript in Microsoft Dynamics CRM 2011

I didn't find much useful code in the MSDN SDK for the Organization service create message.  So I will give a quick demo on how to utilize this message in both C# and Jscript.

First in C# (I am using SOAPLogger solution included with the SDK:

  // Connect to the Organization service. 
    // The using statement assures that the service proxy will be properly disposed.
    using (_serviceProxy = new OrganizationServiceProxy(serverConfig.OrganizationUri,
                                                        serverConfig.HomeRealmUri,
                                                        serverConfig.Credentials,
                                                        serverConfig.DeviceCredentials))
    {
     // This statement is required to enable early-bound type support.
     _serviceProxy.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior());

     IOrganizationService service = (IOrganizationService)_serviceProxy;


     using (StreamWriter output = new StreamWriter("output.txt"))
     {

      SoapLoggerOrganizationService slos = new SoapLoggerOrganizationService(serverConfig.OrganizationUri, service, output);

      //Add the code you want to test here:
      // You must use the SoapLoggerOrganizationService 'slos' proxy rather than the IOrganizationService proxy you would normally use.


      CreateRequest create = new CreateRequest();
      Account tstAccount = new Account();
      
     //set attributes here
      tstAccount.Name = "test account in code";
      tstAccount.Address1_City = "Richfield";

      create.Target = tstAccount;
      slos.Execute(create);

Now here is the Jscript nicely formatted by the CRM 2011 SOAP formatter. Available at: http://crm2011soap.codeplex.com/

This example is asynchronous, if you want to learn how to make JScript SOAP calls synchronously please visit this posthttp://mileyja.blogspot.com/2011/07/using-jscript-to-access-soap-web.html


function runme() {
    
    SDK.SAMPLES.CreateAccountRequest();
}

if (typeof (SDK) == "undefined")
   { SDK = { __namespace: true }; }
       //This will establish a more unique namespace for functions in this library. This will reduce the 
       // potential for functions to be overwritten due to a duplicate name when the library is loaded.
       SDK.SAMPLES = {
           _getServerUrl: function () {
               ///<summary>
               /// Returns the URL for the SOAP endpoint using the context information available in the form
               /// or HTML Web resource.
               ///</summary>
               var OrgServicePath = "/XRMServices/2011/Organization.svc/web";
               var serverUrl = "";
               if (typeof GetGlobalContext == "function") {
                   var context = GetGlobalContext();
                   serverUrl = context.getServerUrl();
               }
               else {
                   if (typeof Xrm.Page.context == "object") {
                         serverUrl = Xrm.Page.context.getServerUrl();
                   }
                   else
                   { throw new Error("Unable to access the server URL"); }
                   }
                  if (serverUrl.match(/\/$/)) {
                       serverUrl = serverUrl.substring(0, serverUrl.length - 1);
                   } 
                   return serverUrl + OrgServicePath;
               }, 
           CreateAccountRequest: function () {
               var requestMain = ""
               requestMain += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
               requestMain += "  <s:Body>";
               requestMain += "    <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
               requestMain += "      <request i:type=\"a:CreateRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
               requestMain += "        <a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
               requestMain += "          <a:KeyValuePairOfstringanyType>";
               requestMain += "            <b:key>Target</b:key>";
               requestMain += "            <b:value i:type=\"a:Entity\">";
               requestMain += "              <a:Attributes>";
               requestMain += "                <a:KeyValuePairOfstringanyType>";
               requestMain += "                  <b:key>name</b:key>";
               requestMain += "                  <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">New Account Code</b:value>";
               requestMain += "                </a:KeyValuePairOfstringanyType>";
               requestMain += "                <a:KeyValuePairOfstringanyType>";
               requestMain += "                  <b:key>address1_city</b:key>";
               requestMain += "                  <b:value i:type=\"c:string\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">Minneapolis</b:value>";
               requestMain += "                </a:KeyValuePairOfstringanyType>";
               requestMain += "              </a:Attributes>";
               requestMain += "              <a:EntityState i:nil=\"true\" />";
               requestMain += "              <a:FormattedValues />";
               requestMain += "              <a:Id>00000000-0000-0000-0000-000000000000</a:Id>";
               requestMain += "              <a:LogicalName>account</a:LogicalName>";
               requestMain += "              <a:RelatedEntities />";
               requestMain += "            </b:value>";
               requestMain += "          </a:KeyValuePairOfstringanyType>";
               requestMain += "        </a:Parameters>";
               requestMain += "        <a:RequestId i:nil=\"true\" />";
               requestMain += "        <a:RequestName>Create</a:RequestName>";
               requestMain += "      </request>";
               requestMain += "    </Execute>";
               requestMain += "  </s:Body>";
               requestMain += "</s:Envelope>";
               var req = new XMLHttpRequest();
               req.open("POST", SDK.SAMPLES._getServerUrl(), true)
               // Responses will return XML. It isn't possible to return JSON.
               req.setRequestHeader("Accept", "application/xml, text/xml, */*");
               req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
               req.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute");
               var successCallback = null;
               var errorCallback = null;
               req.onreadystatechange = function () { SDK.SAMPLES.CreateAccountResponse(req, successCallback, errorCallback); };
               req.send(requestMain);
           },
       CreateAccountResponse: function (req, successCallback, errorCallback) {
               ///<summary>
               /// Recieves the assign response
               ///</summary>
               ///<param name="req" Type="XMLHttpRequest">
               /// The XMLHttpRequest response
               ///</param>
               ///<param name="successCallback" Type="Function">
               /// The function to perform when an successfult response is returned.
               /// For this message no data is returned so a success callback is not really necessary.
               ///</param>
               ///<param name="errorCallback" Type="Function">
               /// The function to perform when an error is returned.
               /// This function accepts a JScript error returned by the _getError function
               ///</param>
               if (req.readyState == 4) {
               if (req.status == 200) {
               if (successCallback != null)
               { successCallback(); }
               }
               else {
                   errorCallback(SDK.SAMPLES._getError(req.responseXML));
               }
           }
       },
       _getError: function (faultXml) {
           ///<summary>
           /// Parses the WCF fault returned in the event of an error.
           ///</summary>
           ///<param name="faultXml" Type="XML">
           /// The responseXML property of the XMLHttpRequest response.
           ///</param>
           var errorMessage = "Unknown Error (Unable to parse the fault)";
           if (typeof faultXml == "object") {
               try {
                   var bodyNode = faultXml.firstChild.firstChild;
                   //Retrieve the fault node
                   for (var i = 0; i < bodyNode.childNodes.length; i++) {
                       var node = bodyNode.childNodes[i];
                       //NOTE: This comparison does not handle the case where the XML namespace changes
                       if ("s:Fault" == node.nodeName) {
                       for (var j = 0; j < node.childNodes.length; j++) {
                           var faultStringNode = node.childNodes[j];
                           if ("faultstring" == faultStringNode.nodeName) {
                               errorMessage = faultStringNode.text;
                               break;
                           }
                       }
                       break;
                   }
               }
           }
           catch (e) { };
        }
        return new Error(errorMessage);
     },
 __namespace: true
};

Now you can call the runme() function from your form jscript handler.
Thats all there is to it!

I hope this helps!

23 comments:

  1. Thanks for posting this Jamie. It's been incredibly useful for me as I've been trying to write a SOAP client in Java for Dynamics CRM 2011.

    ReplyDelete
  2. Great Jamie

    Please can you tell how i should call or reference the function runme() in Javascrit?

    And this c# code , how do i import it in my organisation so that i shoul be able to acces to that function from Javascript

    Thanks

    ReplyDelete
    Replies
    1. To run the jscript function you would have to upload the jscript as a jscript file into your web resource library for your organization. Then you can go into the forms designer (settings-customizations-customize the system-entities-pick an entity-forms and you can double click on the properties of the form after opening the form designer for a specific form. You can then add jscript functions to be called in the on-load and on-save events of the form. You can also examine the properties of the for fields and add jscript in the on-change event of fields in the form designer also.

      The .NET code would have to be used as part of a separate application that calls into the CRM web service or it could be a plugin or custom workflow assembly. For all of these things I would recommend starting with the CRM SDK and take a look at the examples there.

      Delete
  3. it's look like good but what if you get an error in your plugin?

    ReplyDelete
    Replies
    1. The easiest way to debug a plugin is to attach to the w3wp.exe process using remote debugger. This requires you to have the .pdb file deployed to the server\bin\assembly directory of your server.

      Delete
    2. You can also write out error messages using InvalidPluginExecutionException. It allows you to easily put the exception.tostring in the message before throwing it. The error text will then be presented to the UI in CRM.

      Delete
  4. Hi, Great.. Tutorial is just awesome..It is really helpful for a newbie like me.. I am a regular follower of your blog. Really very informative post you shared here. Kindly keep blogging. If anyone wants to become a .Net developer learn from Dot Net Training in Chennai. or learn thru Dot Net Training in Chennai. Nowadays Dot Net has tons of job opportunities on various vertical industry.
    or Javascript Training in Chennai. Nowadays JavaScript has tons of job opportunities on various vertical industry.

    ReplyDelete
  5. This is quite educational arrange. It has famous breeding about what I rarity to vouch. Colossal proverb.
    This trumpet is a famous tone to nab to troths. Congratulations on a career well achieved. This arrange is synchronous s informative impolites festivity to pity. I appreciated what you ok extremely here 


    Selenium training in bangalore
    Selenium training in Chennai
    Selenium training in Bangalore
    Selenium training in Pune
    Selenium Online training

    ReplyDelete
  6. Thank you for taking time to provide us some of the useful and exclusive information with us.
    Regards,
    selenium course in chennai

    ReplyDelete
  7. Thank you for allowing me to read it, welcome to the next in a recent article. And thanks for sharing the nice article, keep posting or updating news article.
    lenovo mobile service center near me
    lenovo mobile service centre in chennai
    lenovo service center in velachery

    ReplyDelete
  8. This comment has been removed by the author.

    ReplyDelete
  9. Hey, very nice site. I came across this on Google, and I am stoked that I did. I will definitely be coming back here more often. Wish I could add to the conversation and bring a bit more to the table, but am just taking in as much info as I can at the moment. Thanks .

    DedicatedHosting4u.com


    ReplyDelete

  10. I am overwhelmed by your post with such a nice topic. Usually, I visit your blogs and get updated with the information you include but today’s blog would be the most appreciable...

    Thanks
    Cpa offers

    ReplyDelete