Friday, June 8, 2012

Book an Appointment in Microsoft Dynamics CRM 2011 Using C# or Jscript

This illustration shows how to book an appointment in Microsoft Dynamics CRM 2011 with BookRequest.  This example will be given in Jscript (SOAP) and in C# (.NET).
    Ok, here is what the code looks like!
    First in C#:

    WhoAmIRequest userRequest = new WhoAmIRequest();
    WhoAmIResponse userResponse = (WhoAmIResponse)_serviceProxy.Execute(userRequest);
    
    // Create the ActivityParty instance.
    ActivityParty party = new ActivityParty
    {
        PartyId = new EntityReference(SystemUser.EntityLogicalName, userResponse.UserId)
    };
    
    // Create the appointment instance.
    Appointment appointment = new Appointment
    {
        Subject = "Test Appointment",
        Description = "Test Appointment created using the BookRequest Message.",
        ScheduledStart = DateTime.Now.AddHours(1),
        ScheduledEnd = DateTime.Now.AddHours(2),
        Location = "Office",
        RequiredAttendees = new ActivityParty[] { party },
        Organizer = new ActivityParty[] { party }
    };
    
    // Use the Book request message.
    BookRequest req = new BookRequest
    {
        Target = appointment
    };
    BookResponse resp = (BookResponse)service.Execute(req);
    Guid _appointmentId = resp.ValidationResult.ActivityId;
    
    
    This C# code was adapted from MSDN examples located at http://msdn.microsoft.com/en-us/library/microsoft.crm.sdk.messages.bookrequest.aspx

    If you need help instantiating a service object in .NET within a plugin check out this post:
    http://mileyja.blogspot.com/2011/04/instantiating-service-object-within.html

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

    Now in Jscript


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

    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 ServicePath = "/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 + ServicePath;
                   }, 
               BookRequest: 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=\"b:BookRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\" xmlns:b=\"http://schemas.microsoft.com/crm/2011/Contracts\">";
                   requestMain += "        <a:Parameters xmlns:c=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
                   requestMain += "          <a:KeyValuePairOfstringanyType>";
                   requestMain += "            <c:key>Target</c:key>";
                   requestMain += "            <c:value i:type=\"a:Entity\">";
                   requestMain += "              <a:Attributes>";
                   requestMain += "                <a:KeyValuePairOfstringanyType>";
                   requestMain += "                  <c:key>subject</c:key>";
                   requestMain += "                  <c:value i:type=\"d:string\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">Test Appointment</c:value>";
                   requestMain += "                </a:KeyValuePairOfstringanyType>";
                   requestMain += "                <a:KeyValuePairOfstringanyType>";
                   requestMain += "                  <c:key>description</c:key>";
                   requestMain += "                  <c:value i:type=\"d:string\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">Test Appointment created using the BookRequest Message.</c:value>";
                   requestMain += "                </a:KeyValuePairOfstringanyType>";
                   requestMain += "                <a:KeyValuePairOfstringanyType>";
                   requestMain += "                  <c:key>scheduledstart</c:key>";
                   requestMain += "                  <c:value i:type=\"d:dateTime\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">2012-06-08T09:42:45.8655676-05:00</c:value>";
                   requestMain += "                </a:KeyValuePairOfstringanyType>";
                   requestMain += "                <a:KeyValuePairOfstringanyType>";
                   requestMain += "                  <c:key>scheduledend</c:key>";
                   requestMain += "                  <c:value i:type=\"d:dateTime\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">2012-06-08T10:42:45.8655676-05:00</c:value>";
                   requestMain += "                </a:KeyValuePairOfstringanyType>";
                   requestMain += "                <a:KeyValuePairOfstringanyType>";
                   requestMain += "                  <c:key>location</c:key>";
                   requestMain += "                  <c:value i:type=\"d:string\" xmlns:d=\"http://www.w3.org/2001/XMLSchema\">Office</c:value>";
                   requestMain += "                </a:KeyValuePairOfstringanyType>";
                   requestMain += "                <a:KeyValuePairOfstringanyType>";
                   requestMain += "                  <c:key>requiredattendees</c:key>";
                   requestMain += "                  <c:value i:type=\"a:EntityCollection\">";
                   requestMain += "                    <a:Entities>";
                   requestMain += "                      <a:Entity>";
                   requestMain += "                        <a:Attributes>";
                   requestMain += "                          <a:KeyValuePairOfstringanyType>";
                   requestMain += "                            <c:key>partyid</c:key>";
                   requestMain += "                            <c:value i:type=\"a:EntityReference\">";
                   requestMain += "                              <a:Id>6e219f51-0310-4c4d-8c60-1c524e2ba7b3</a:Id>";
                   requestMain += "                              <a:LogicalName>systemuser</a:LogicalName>";
                   requestMain += "                              <a:Name i:nil=\"true\" />";
                   requestMain += "                            </c: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>activityparty</a:LogicalName>";
                   requestMain += "                        <a:RelatedEntities />";
                   requestMain += "                      </a:Entity>";
                   requestMain += "                    </a:Entities>";
                   requestMain += "                    <a:EntityName i:nil=\"true\" />";
                   requestMain += "                    <a:MinActiveRowVersion i:nil=\"true\" />";
                   requestMain += "                    <a:MoreRecords>false</a:MoreRecords>";
                   requestMain += "                    <a:PagingCookie i:nil=\"true\" />";
                   requestMain += "                    <a:TotalRecordCount>0</a:TotalRecordCount>";
                   requestMain += "                    <a:TotalRecordCountLimitExceeded>false</a:TotalRecordCountLimitExceeded>";
                   requestMain += "                  </c:value>";
                   requestMain += "                </a:KeyValuePairOfstringanyType>";
                   requestMain += "                <a:KeyValuePairOfstringanyType>";
                   requestMain += "                  <c:key>organizer</c:key>";
                   requestMain += "                  <c:value i:type=\"a:EntityCollection\">";
                   requestMain += "                    <a:Entities>";
                   requestMain += "                      <a:Entity>";
                   requestMain += "                        <a:Attributes>";
                   requestMain += "                          <a:KeyValuePairOfstringanyType>";
                   requestMain += "                            <c:key>partyid</c:key>";
                   requestMain += "                            <c:value i:type=\"a:EntityReference\">";
                   requestMain += "                              <a:Id>6e219f51-0310-4c4d-8c60-1c524e2ba7b3</a:Id>";
                   requestMain += "                              <a:LogicalName>systemuser</a:LogicalName>";
                   requestMain += "                              <a:Name i:nil=\"true\" />";
                   requestMain += "                            </c: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>activityparty</a:LogicalName>";
                   requestMain += "                        <a:RelatedEntities />";
                   requestMain += "                      </a:Entity>";
                   requestMain += "                    </a:Entities>";
                   requestMain += "                    <a:EntityName i:nil=\"true\" />";
                   requestMain += "                    <a:MinActiveRowVersion i:nil=\"true\" />";
                   requestMain += "                    <a:MoreRecords>false</a:MoreRecords>";
                   requestMain += "                    <a:PagingCookie i:nil=\"true\" />";
                   requestMain += "                    <a:TotalRecordCount>0</a:TotalRecordCount>";
                   requestMain += "                    <a:TotalRecordCountLimitExceeded>false</a:TotalRecordCountLimitExceeded>";
                   requestMain += "                  </c: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>appointment</a:LogicalName>";
                   requestMain += "              <a:RelatedEntities />";
                   requestMain += "            </c:value>";
                   requestMain += "          </a:KeyValuePairOfstringanyType>";
                   requestMain += "        </a:Parameters>";
                   requestMain += "        <a:RequestId i:nil=\"true\" />";
                   requestMain += "        <a:RequestName>Book</a:RequestName>";
                   requestMain += "      </request>";
                   requestMain += "    </Execute>";
                   requestMain += "  </s:Body>";
                   requestMain += "</s:Envelope>";
                   var req = new XMLHttpRequest();
                   req.open("POST", SDK.SAMPLES._getServerUrl(), true)
                   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.BookResponse(req, successCallback, errorCallback); };
                   req.send(requestMain);
               },
           BookResponse: 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
    };
    
    


    To understand how to parse the response please review my post on using the DOM parser.
    Now you can call the SDK.SAMPLES.BookRequest function from your form jscript handler.


    Thats all there is to it!
    -

    Thursday, June 7, 2012

    My Favorite Pasta Sauce Recipe

    Sorry, no CRM today,  only the best pasta sauce recipe EVER!!!   I used to use it to impress the ladies on dates.  Now that I am married I use it to impress our friends when I invite them over.   This recipe was given to me by a old friend from high school named Devon Gifford.

    Bowties w/ Sausage & Vodka Sauce

    Servings           4
    Prep Time        10 min
    Cook Time        40 min

    Ingredients

    6          ounces Bowties Pasta (can substitute with any spiral/tubed pasta)

    6          ounces uncooked, loose ground spicy Italian sausage (SuperTarget is the best – not in casing.  Be sure your guests can handle the heat, otherwise get mild sausage)

    2          Tablespoons fresh garlic, finely chopped

    ½         Cup onion, finely diced

    1          14 oz Can diced tomatoes (ensure can only contains tomatoes and no other herbs, vegetables or seasonings other than salt)

    3          Tablespoons vodka

    1          Cup whipping cream

    ¼         Cup peas (defrosted if frozen)

    6 – 8    Leaves of fresh basil, finely chopped (there is no substitute for this!  It is a majority of the flavor.)

    Grated hard Italian cheese (Parmesan, Romano or Asiago)

    Instructions

    In a medium pot, cook pasta, drain and set aside.

    Heat a large sauce pan over medium-high heat for several minutes.  Add Italian sausage and break apart into small pieces with wooden spoon while frying.  Cook for 10 minutes or until sausage is cooked through and fat has been rendered out of it.  Ideally, the sausage will be almost dry and very dark brown but not burnt.  Reduce heat to low. 

    With a slotted spoon, remove the cooked sausage while leaving the rendered fat in the pan.  Place the cooked sausage in a bowl and set aside.  In same sauce pan and using the rendered fat, sauté garlic and onion on low heat until onion is limp and translucent, about 5 minutes.  Be caution not to burn the onion and garlic.

    Add entire can of tomatoes and increase heat to medium-high.  Using wooden spoon, chop and stir tomatoes.  Cook on medium-high heat until virtually all liquid from the tomatoes has been evaporated, about 10 minutes.

    While pan is still hot, add the 3 Tablespoons of vodka.  Ignite the fumes and swirl mixture while burning off alcohol. (For best results – the pan should be hot enough that the vodka turns to steam once it hit the pan.  Be sure not to catch anything on fire.)

    Once fire burns out, add the cream, peas and chopped basil followed by the cooked sausage and pasta.  Reduce heat to medium and stir to coat pasta.  Cook until flavors have combined and cream is slightly reduced – about 5 to 10 minutes.

    Serve immediately with grated cheese on top.  Accompanied well with a good Italian bread and olive oil with balsamic vinegar and parmesan for dipping.


    Happy Thursday!

    Monday, June 4, 2012

    Richard Knudson's New Book is Out!

    Another CRM MVP, Richard Knudson, just released his new book "Building Business With CRM".  It's a great book because it mixes how to apply Microsoft Dynamics CRM to business while still incorporating a lot of the technical knowledge you would expect from a more technically focused book.

    I am not receiving any monetary proceeds from this book but my name is buried in it somewhere because I assisted in the editing process.

    Check it out at the link below:

    http://www.crmbizbook.com/

    Tuesday, May 22, 2012

    How to Fix: Invalid Parameter Error When Viewing Dashboards or Sitemap in Microsoft Dynamics CRM 2011

    At a client the other day we had a late Friday issue right when everyone wanted to go home for the weekend.  It seemed that some of the user's were getting an error when they were viewing their dashboards that read something like:

      "Invalid parameter ‘formid=xxxxxxxx-xxxx-xxxxx-′ in Request.QueryString on page .../workplace/home_dashboards.aspx"

    The main thing I noticed about the error message was that the guid in the parameter was being truncated, this meant that the guid was incomplete that was used in the query string.  There had been no changes to the system recently and it seemed to start happening without any warning.

    I had never seen this particular one before, but we were able to resolve it and even find out how to prevent it in the future.  Some searching revealed that other people have had this problem before and that the parameter that causes the problem is not always the same.  In the example given here it seemed that the OTC (Object Type Code) was being truncated in the same fashion.

    The fix for this issue was ultimately performing an IIS Reset.  This quickly resolved the problem for the client.  Some further searching seemed to suggest that staying current on your update rollups may prevent this from happening to you because there has been fixes implemented for issues of this type in both Rollup 5 and Rollup 7.

    I hope this helps.

    -

    Friday, May 18, 2012

    Install Sample Data In a Microsoft Dynamics CRM 2011 Organization Using VB.NET

    This illustration shows how to install the sample data that comes with Microsoft Dynamics CRM 2011 with InstallSampleDataRequest.   This example will be given in VB.NET.

    Ok, here is what the code looks like!
    In VB.NET#:

    Dim req As New InstallSampleDataRequest()
    Dim resp As InstallSampleDataResponse = DirectCast(service.Execute(req), InstallSampleDataResponse)
    

    I hope this helps!

    -

    Thursday, May 17, 2012

    Retrieve Metadata for a Relationship in Microsoft Dynamics CRM 2011 Using VB.NET

    This illustration shows how to retrieve metadata for a relationship in Microsoft Dynamics CRM 2011 in code using VB.NET.   This example will be given in SOAP (JScript) and in C# (.NET).

    Ok, here is what the code look like!
    In VB.NET:

    Dim req As New RetrieveRelationshipRequest()
    req.Name = "new_contact_account_partner_relationship"
    Dim resp As RetrieveRelationshipResponse = DirectCast(service.Execute(req), RetrieveRelationshipResponse)
    
    

    Thats all there is to it!

    I hope this helps!

    Wednesday, May 16, 2012

    Retrieve Option Set Metadata in Microsoft Dynamics CRM 2011 Using VB.NET

    This illustration shows how to retrieve an option set in Microsoft Dynamics CRM 2011 using the RetrieveOptionSetRequest.   This example will be given in VB.NET.

    Ok, here is what the code look like!

    First in C#:

    Dim req As New RetrieveOptionSetRequest()
    req.Name = "new_contactmethod"
    Dim resp As RetrieveOptionSetResponse = DirectCast(service.Execute(req), RetrieveOptionSetResponse)
    
    'Access the metadata this way
    Dim osm As OptionSetMetadata = resp.OptionSetMetadata
    


    I hope this helps!

    -