Archive for the ‘MS CRM’ Category

CRM 2011 – Hiding a Form’s Header and Footer

While Microsoft provides a button to minimize a form’s header, we had to fulfill a requirement to automatically minimize the header and completely hide the footer for several entities. The reasoning behind this was that most users weren’t going to be making changes to these records, so the client wanted to provide the maximum amount of viewable space. For instance, the Account form normally displays like this, but we wanted to reclaim at least that 90px of height from the ribbon:

Account Form

As it turned out, all it took was a couple simple JavaScript functions called in the form’s OnLoad event to make this happen. When looking into how to hide the ribbon, I came across this article, which lists code to hide different elements on the form and contained discussion regarding the ribbon’s minimize functionality and how to leverage it during the form’s OnLoad event. Hiding the ribbon was just a matter of firing the “onclick” event for the “minimizeribbon” button after it had rendered:

function Hide_Ribbon()
{
  setTimeout(function () { window.top.document.getElementById("minimizeribbon").fireEvent("onclick"); }, 0);
}


And hiding the footer was even easier, since you could just set a “display: none;” for the footer’s parent:

function Hide_Footer()
{
  document.getElementById("crmFormFooter").parentElement.style.display = "none";
}


The result looks something like this:

Account Form - No Header or Footer

The biggest downside to this approach, though, is that the header and footer will momentarily display before the JavaScript kicks in and hides them. Still, if your users don’t need to use the ribbon on a regular basis and are starved for screen space, this is a quick and easy way to give them a little more room.

Tags: , , , ,


Microsoft CRM 2011: Immediately Open a Record That Was Updated Using oData

This is a quick modification to the Microsoft CRM 2011: Update oData Examples article we posted a while ago. In the event that you would prefer to just pop up a record that you’ve updated or created using oData instead of making your user find it on their own, you can use the AJAX “success” attribute to execute whatever code you want when the update/create is complete.

For instance, in the following “updateContact” function from the previous article, I’ve added code to build a URL, then open a window:

function updateContact(id, contactObject) {

  //Parse the entity object into JSON
  var jsonEntity = window.JSON.stringify(contactObject);

  //Asynchronous AJAX function to Update a CRM record using OData
 $.ajax({
    type: "POST",
    contentType: "application/json; charset=utf-8",
    datatype: "json",
    data: jsonEntity,
    url: Xrm.Page.context.getServerUrl() + "/XRMServices/2011/OrganizationData.svc/ContactSet(guid'" + id + "')",
    beforeSend: function (XMLHttpRequest) {
      //Specifying this header ensures that the results will be returned as JSON.
      XMLHttpRequest.setRequestHeader("Accept", "application/json");

      //Specify the HTTP method MERGE to update just the changes you are submitting.
      XMLHttpRequest.setRequestHeader("X-HTTP-Method", "MERGE");
    },
    success: function (data, textStatus, XmlHttpRequest) {
      if(Xrm.Page.getAttribute('new_opencontactonsave').getValue() == true) {
        var linkUrl = Xrm.Page.context.getServerUrl() + "/main.aspx?etc=2&extraqs=formid%3d894cc46a-b0cb-4ab0-8bf6-200544e46a2d&id=%7b" + id + "%7d&pagetype=entityrecord";

        var windowWidth = screen.width * .5;
        var windowLeft = windowWidth * .5;

        var windowHeight = screen.height * .75;
        var windowTop = (screen.height - windowHeight) * .5;

        var options = "left=" + windowLeft + ",width=" + windowWidth + ",top=" + windowTop + ",height=" + windowHeight;

        window.open(linkUrl,"_blank",options);
      }
    }
  });
}

In this case, we’re using the GUID for the Contact we just updated when building the URL, but, if we inserted a Contact record, we could use the result data to find the GUID of the record with something like “data.d.ContactId”. The quickest way to get the values for the other querystring variables, “etc” and “extraqs”, is to open a record of whatever entity you’re interested in, click “Copy a Link”, then pull the values from there. All that’s left is to set the window options that you want and open it up!

Contact Header

The updated CRM 2011 solution file can be downloaded here!

Tags: , , , , ,


Microsoft CRM 2011: Update OData Example

Expanding upon Jeff Ballard’s recent post, Microsoft CRM 2011 oData Examples, the following is an example of how to use OData to update a record. Let’s say that we want to let the user not only see who the Account’s latest Contact is, but also allow them to update the Contact’s Job Title, E-mail, and Phone Number without needing to open up the Contact, itself. Start out by opening up the Account form and unchecking the “Field is read-only” option for the “Most Recent Contact”‘s E-mail, Job Title, and Phone Number fields, then we’ll jump right to the code (which was shamelessly pared down from the example in this fantastic MS TechNet article).

Open up the form properties and add json2.js as a new JavaScript Web Resource (for its handy “stringify” function), then open up the new_oDataExample library. First, modify the “requestComplete” function so that we have a new condition that looks for a queryName of “MostRecent_Save” and add code to populate an object with the four “Recent Contact” fields. We’ll be passing that object to the “updateContact” function, along with the Contact’s Guid.

function requestComplete(request, queryName) {
    /*  A request.readyState of 4 means the request is complete. If
        it's complete and the status is 200 (OK), then we can assign the results
        of the call to our controls on the form.*/
    if (request.readyState == 4 && request.status == 200) {
        var json = $.parseJSON(request.responseText);
        if ( (json != undefined) && (json.d != undefined) && (json.d.results != undefined) && (json.d.results[0] != null) ) {
            json = json.d.results[0];
            // Note that the way things are set up, it's possible to have more
            // than one "Support Contact" returned but I'm hard coding the results
            // to return the first contact only.
            if (queryName == "MostRecent") {
                xp.getAttribute("new_mostrecentfullname").setValue(json.FullName);
                xp.getAttribute("new_mostrecentphone").setValue(json.Telephone1);
                xp.getAttribute("new_mostrecentemail").setValue(json.EMailAddress1);
                xp.getAttribute("new_mostrecenttitle").setValue(json.JobTitle);
                // As an aside (the field below doesn't exist), when placing values
                // into a numeric field, you will need to use the javascript
                // function parseFloat to prevent CRM type errors.
                //xp.getAttribute("new_numericrank").setValue(parseFloat(json.new_NumericRank));
            } else if (queryName == "SupportContact") {
                xp.getAttribute("new_supportfullname").setValue(json.FullName);
                xp.getAttribute("new_supportphone").setValue(json.Telephone1);
                xp.getAttribute("new_supportemail").setValue(json.EMailAddress1);
                xp.getAttribute("new_supporttitle").setValue(json.JobTitle);
            } else if (queryName == "MostRecent_Save") {
                var changes = new Object();
                changes.FullName = xp.getAttribute("new_mostrecentfullname").getValue();
                changes.Telephone1 = xp.getAttribute("new_mostrecentphone").getValue();
                changes.EMailAddress1= xp.getAttribute("new_mostrecentemail").getValue();
                changes.JobTitle= xp.getAttribute("new_mostrecenttitle").getValue();

                updateContact(json.ContactId, changes);
            }
        }
    }
}

Now go ahead and add the “onSave” function to the library. “onSave” will be building a query that’s very similar to the “Most Recent Contact” query that’s used to populate those fields, only we’re just interested in the Guid this time. It calls “getContact” and passes along the “MostRecent_Save” queryName that we added a condition for in “requestComplete”.

function onSave(context) {
    var accountId = xp.data.entity.getId();

    // Since we're not saving the most recent Contact's Guid anywhere on the page, request it.
    var mostRecentQuery = "/XRMServices/2011/organizationData.svc/ContactSet?$select=ContactId&$top=1&$orderby=CreatedOn desc&$filter=ParentCustomerId/Id eq guid'" + accountId + "'";
    getContact(mostRecentQuery, "MostRecent_Save");

}

Finally, add the “updateContact” function. This will be using the Contact Guid to merge the changes in the object we populated in “requestComplete” with the Contact’s record.

function updateContact(id, contactObject) {

  //Parse the entity object into JSON
  var jsonEntity = window.JSON.stringify(contactObject);

  //Asynchronous AJAX function to Update a CRM record using OData
 $.ajax({
    type: "POST",
    contentType: "application/json; charset=utf-8",
    datatype: "json",
    data: jsonEntity,
    url: Xrm.Page.context.getServerUrl() + "/XRMServices/2011/OrganizationData.svc/ContactSet(guid'" + id + "')",
    beforeSend: function (XMLHttpRequest) {
      //Specifying this header ensures that the results will be returned as JSON.
      XMLHttpRequest.setRequestHeader("Accept", "application/json");

      //Specify the HTTP method MERGE to update just the changes you are submitting.
      XMLHttpRequest.setRequestHeader("X-HTTP-Method", "MERGE");
    }
  });
}

Add a reference to the “onSave” function in the Form onSave Event Handler subgrid and you’re ready to go! After publishing the changes, you’ll be able to update the most recent Contact’s information from the related Account entity. Jeff’s original exported solution has been updated with these changes and is available for download here!

Tags: , ,


MS CRM 2011: Date Controls and Column Width

A coworker of mine was recently experimenting with some changes to the Account entity in our MS CRM 2011 test environment and came across an interesting quirk. They had formatted a section to be four columns wide and set the labels to a reasonable width of 100 pixels. To their surprise, every column in every section on the form was suddenly inflated, pushing items off-screen, including the horizontal scrollbar.

As it turns out, the Date control was the culprit. While textboxes can be shrunk considerably, it appears that the MS CRM Date control’s minimum width is 103 pixels. The interesting part is that every column was widened to accommodate the extra space that the Date control needed, not just the column or the section that contained the control.

The workaround was to modify the Formatting properties for the section so that the labels were positioned over the controls, rather then to the left. Another workaround would have been to reduce the label size, but we couldn’t go much lower, in this case. There’s also the option of avoiding the situation entirely and not putting a Date control into a section with too many columns or you could always embrace the behavior and resize the window in the form’s OnLoad event.

With typical web design, I would maybe expect to see a particular column’s width expanded if the contents are too wide or the column’s contents truncated or wrapped. In any case, this issue really helped illustrate to me just how interconnected the formatting is on an MS CRM form. It’s not a huge inconvenience, but it’s definitely something to keep in mind when designing new forms or modifying existing ones.

Tags: ,


Script Compatibility Between MS CRM 4.0 and 2011

During an upgrade from CRM 4.0 to CRM 2011 we discovered an issue in scripting that caused things to break even though scripts are backwards compatible. There is a field/attribute called fullname that is hidden and auto-populated based on first, middle and last names and is saved with the record. The issue was the syntax used in MS CRM 4.0 – while it worked, it wasn’t the “supported” MS CRM method. There are two fixes.

The code that didn’t work was this:

// fullname is a var that is a concatenation of first, last and middle
document.crmForm.new_fullname.value = fullname;

The first way to fix it is to use the CRM 2011 scripting model:

Xrm.Page.getAttribute("new_fullname").setAttribute(fullname);

The second method was to fix it using the proper CRM 4.0 syntax with the “.value” at the end replaced with “.DataValue”:

document.crmForm.new_fullname.DataValue = fullname;

Which is the better way to fix it? If it were me and it’s a small script, I would update the whole script to the CRM 2011 scripting model. If it’s a large script where only a few lines need to be changed, I might be tempted to fix it using the 4.0 method until the whole script can be updated so it’s consistent. Of course, if you have time to update the whole thing and thoroughly test it, then I would do that.

Hopefully this will help someone else during their upgrade process, whether for themselves or on behalf of a customer.

Tags: , , , ,


Random Error Message: Type or namespace name ‘CrmEntityReference’ does not exist in the namespace…

I created a project (call it “Project A”) a while ago using the Advanced Developer Extensions and used crmsvcutil.exe to generate the classes to be used in my .NET project. I recently had a need to create another .NET project (call it “Project B”) using the Advanced Developer Extensions. Instead of using the DLL in the SDK\microsoft.xrm folder that I had recently re-downloaded/updated, I just copied the Microsoft.Xrm.Client DLL from “Project A”. When I went to build the project it failed with the error message:

Error 1 The type or namespace name 'CrmEntityReference' does not exist
in the namespace 'Microsoft.Xrm.Client' (are you
missing an assembly reference?)

After doing some digging around, I discovered that the latest version of crmsvcutil.exe in the SDK generates the code a bit differently. Fields such as an ownerid used to be generated like this:

[global::Microsoft.Xrm.Client.Linq.CrmProperty("ownerid")]
public global::Microsoft.Crm.Sdk.Owner ownerid
	{
		get { return this.GetPropertyValue<global::Microsoft.Crm.Sdk.Owner>("ownerid"); }
		set { this.SetPropertyValue("ownerid", value, typeof(global::Microsoft.Crm.Sdk.Owner)); }
	}

but instead has been changed to this:


[global::Microsoft.Xrm.Client.Linq.CrmProperty("ownerid", "owneridLabel")]
public global::Microsoft.Xrm.Client.CrmEntityReference ownerid
	{
		get { return this.GetPropertyValue<global::Microsoft.Xrm.Client.CrmEntityReference>("ownerid"); }
		set { this.SetPropertyValue("ownerid", value, typeof(global::Microsoft.Crm.Sdk.Owner)); }
	}

The difference is in the actual type – instead of being a type of “Microsoft.Crm.Sdk.Owner” it is ”Microsoft.Xrm.Client.CrmEntityReference”. Since that class exists in the microsoft.xrm.client assembly, I knew something had to be different. At first I thought I had pointed to a CRM 2011 dll instead of 4.0 version because the CrmEntityReference is something that you see in CRM 2011. I double checked and I was correct, it was a 4.0 version assembly. The fix at that point was simply a matter of removing my reference to the older Microsoft.Xrm.Client.dll assembly and adding in the one with the latest version from my recently updated SDK. Everything built just fine after that.

The moral of the story? If you update your SDK, make sure that any assemblies you rely on haven’t changed their types or your code may break!

Tags: , , , , , ,


MS CRM SQL Server Traces – CRM Brings the Noise – and I Filter it!

Every once in a while when doing customization or development for MS CRM I need to run a SQL trace. Anyone who has ever watched a trace of SQL Server for MS CRM (or any enterprise level application, for that matter) knows that a lot of SQL gets generated.

In my case, I usually don’t want to see all the “background noise” SQL that the app generates for it’s internal processing – I’m more interested in what SQL is running to select, insert or update records. SQL Server has the option to add filters to filter out items you don’t want to see in a SQL trace.

Assuming you already know how to create a filter in SQL Server, you can add each of the following statements as a filter to the column “TextData” and filter out a lot of things that you would prefer not to see in the results. I hope it helps, of course, but I warn you that if I am filtering out something that you actually do want to see in the results, don’t blame me:)

NOTE: This is for CRM 4.0 and has not been testing in MSCRM 2011. I would say that it probably will not work very well.

%exec sp_executesql N'With TopSuspendedAsyncOperations(AsyncOperationId)%
%if exists (select * from WorkflowWaitSubscriptionBase (nolock) where IsModified = 1)%
%exec GetDBVersion @DBVersion=@p1 output%
%exec sp_reset_connection%
%exec sp_executesql N'update AsyncOperationBase%
%-- network protocol: LPC%
%exec sp_executesql N'SELECT OrganizationId, EventId, EventData, CreatedOn FROM Notification%
%exec sp_executesql N'select subscription.WorkflowWaitSubscriptionId, subscription.AsyncOperationId, subscription.EntityName,%
%if exists (select * from WorkflowWaitSubscriptionBase (nolock) where IsModified = 1)%
%and DeletionStateCode = 0',N'@lockedState int,@hostId nvarchar(62),@pausingStatus int,@cancelingStatus%
%exec sp_executesql N'SELECT Id FROM DataEncryptionKey  WHERE (((IsConfigurationRow = @IsConfigurationRow0))%
%exec sp_executesql N'SELECT Id, ColumnName, BigIntColumn, IntColumn, SmallIntColumn, TinyIntColumn,%
%exec sp_executesql N'SELECT Id, CreatedOn, Enabled, KeyType, ScaleGroupId FROM CrmKey  WHERE (((Id = @Id0)) ) AND (IsDeleted =
%exec sp_executesql N'SELECT Id, CreatedOn, Enabled, KeyType, ScaleGroupId FROM CrmKey%
%exec sp_executesql N'select sdkmessagefilter0.PrimaryObjectTypeCode as ''primaryobjecttypecode'',%
%exec sp_executesql N'SELECT LocalizedLabelId AS localizedlabelid,%
%exec sp_executesql N'select sdkmessage0.SdkMessageId as ''sdkmessageid'' from SdkMessage%
%exec sp_executesql N'update WorkflowLogBase set <a href="mailto:ModifiedBy=@ModifiedBy0">ModifiedBy=@ModifiedBy0</a>, <a href="mailto:ModifiedOn=@ModifiedOn0">ModifiedOn=@ModifiedOn0</a>, Message=NULL,%
%exec p_GetFullName @organizationid=%
%exec sp_executesql N'select workflow0.UIData as ''uidata'', workflow0.IsCrmUIWorkflow as ''iscrmuiworkflow'',%
%exec sp_executesql N'select systemuser0.AccessMode as ''accessmode'', systemuser0.SystemUserId%
%exec sp_executesql N'select workflowlog0.AsyncOperationId as ''asyncoperationid'',%
%exec sp_executesql N'select workflow0.WorkflowId as ''workflowid'', workflow0.PrimaryEntity as ''primaryentity'',%
%exec sp_executesql N'delete from WorkflowCompletedScopeBase%
%exec sp_executesql N'SELECT Id, KeyType, ActiveKeyId, Enabled%
%exec sp_executesql N'SELECT Id, ScaleGroupId, KeyType,%
%select sdkmessageprocessingstepimage0.CreatedOn as ''createdon''%
%exec sp_executesql N'SELECT Label AS label,%
%SELECT EntityRelationshipId AS entityrelationshipid,%
%SELECT CascadeAssign AS cascadeassign,%
%exec sp_executesql N'SELECT EntityId AS entityid,%
%exec sp_executesql N'SELECT LogicalName AS logicalname,%
%exec sp_executesql N'SELECT T1.LocalizedLabelId AS localizedlabelid,%
%exec sp_executesql N'SELECT RelationshipId AS relationshipid,%
%exec sp_executesql N'IF EXISTS (SELECT 1 FROM dbo.MatchCode%
%SELECT MatchCode FROM dbo.MatchCode%
%exec sp_executesql N'update WorkflowWaitSubscriptionBase%
%exec sp_executesql N'select distinct AsyncOperationId from WorkflowWaitSubscriptionBase%
%exec sp_executesql N'SELECT Id, HelpServerUrl, InstallOn, IsRegistered,%
%exec sp_executesql N'insert into AsyncOperationBase%
%exec sp_executesql N'SELECT T1.AttributeId AS attributeid,%
%exec sp_executesql N'select sdkmessagerequestinput%
%exec sp_executesql N'SELECT Id, KeyType, ScaleGroupId, ActiveKeyId%
%exec sp_executesql N'select sdkmessageprocessingstep0%
%AttributeId AS attributeid FROM AttributeLogicalView%
%FROM AttributePicklistValueLogicalView WHERE AttributeId%
%exec sp_executesql N'SELECT T1.Label AS label,%
%select VersionNumber from EntityView%
%select VersionNumber from AttributePicklistValueView%
%select VersionNumber from EntityRelationshipView%
%select VersionNumber from RelationshipView%
%select VersionNumber from LocalizedLabelView%
%select VersionNumber from AttributeView%
%select VersionNumber from AttributeLookupValueView%
%select VersionNumber from EntityRelationshipRoleView%
%select VersionNumber from EntityRelationshipRelationshipsView%
%select VersionNumber from ViewAttributeView%
%exec sp_executesql N'select transactioncurrency0.ImportSequenceNumber%
%exec sp_executesql N'SELECT EntityId AS entityid FROM EntityLogicalView%
%exec sp_executesql N'SELECT AttributeTypeId AS attributetypeid,%
%exec sp_executesql N'SELECT Id FROM Organization  WHERE (((UniqueName%
%FROM AttributePicklistValueLogicalView WHERE AttributeId%
%exec sp_executesql N'SELECT T1.Label AS label,%
%exec sp_executesql N'exec p_GrantInheritedAccess @referencingId, @referencingOTC,%
%exec sp_executesql N'select contact0.OwningBusinessUnit as ''owningbusinessunit''%
%case when WorkflowState is null then 0 else 1 end%
%exec sp_executesql N'select asyncoperation0.AsyncOperationId as ''asyncoperationid''%
%exec sp_executesql N'SELECT Id, LOWER(SqlServerName) FROM Organization%
%isvalidforadvancedfind FROM EntityLogicalView%
%exec sp_executesql N'SELECT T1.AttributeTypeId AS attributetypeid,%
%exec sp_executesql N'SELECT ReferencedEntityId AS referencedentityid,%
%exec sp_executesql N'select workflowdependency0.CreatedBy as ''createdby'',%
%exec sp_executesql N'select workflow0.WorkflowId as%
%exec sp_executesql N'select asyncoperation0.OwningUser%
%exec sp_executesql N'select workflow0.WorkflowId as%
%create table #CascadeCollect(id INT IDENTITY(1,1)%
%exec sp_executesql N'if (NOT EXISTS(select 0 from PrincipalObjectAccess%
%exec sp_executesql N'select systemuser0.OrganizationId as%
%exec sp_executesql N'select privilege0.PrivilegeId as%
%exec sp_executesql N'SELECT Id, LicenseKey, ProductId, InstallOn FROM ConfigSettings%
%exec sp_executesql N'select asyncoperation0.OwningUser as %
%#CascadeCollect%
%select organization0.SystemUserId as%
%insert into WorkflowLogBase%
%select sdkmessageprocessingstepimage0.SdkMessageProcessingStepImageId%
%exec sp_executesql N'exec p_GetCrmUserId @OrganizationId, @AuthInfo'%
%SELECT Id, DefaultOrganizationId FROM Deployment%
%exec sp_executesql N'SELECT Id, UserId FROM SystemUserOrganizations%
%exec sp_executesql N'SELECT Id, AuthInfo FROM SystemUserAuthentication%
%SELECT M.ObjectId FROM dbo.MatchCode%
%exec sp_executesql N'select subscription.WorkflowWaitSubscriptionId%
%and StatusCode in (@pausingStatus, @cancelingStatus)%
%exec sp_executesql N'select timezonedefinition0.TimeZoneCode%
%exec GetMyRunningJobs%
%exec sp_executesql N'select sdkmessagefilter0%
%exec sp_executesql N'select sdkmessagerequestfield0.Name%
%KeyType, ScaleGroupId FROM CrmKeySetting%
%select report0.Name as ''name'', report0.ReportTypeCode as%
%from TimeZoneRule as timezonerule0%
%exec sp_executesql N'select queue0.QueueId%
%truncate table #SyncEntry%
%create table #SyncEntry%
%exec sp_executesql N'update Subscription set LastSyncStartedOn%
%exec sp_executesql N'select subscriptionclients%
%exec sp_executesql N'select displaystring0.DisplayStringId%
%drop table #SyncEntryIds;%
%select convert(bigint, min_active_rowversion()-1)%
%select ObjectTypeCode, SyncState,%
%insert into SubscriptionSyncInfo%
Enjoy

Tags: , , ,


MS CRM 2011 JavaScript JSON Results Prototyped

I was working in MS CRM 2011 returning some JSON using the oData REST endpoint and while I was looking at what was returned I noticed that the string values that were returned had some prototyped functions attached. Specifically, the following methods were available on a string that was returned:

  • endsWith()
  • startsWith()
  • trim()
  • trimEnd()
  • trimStart()

That’s a nice touch. The functions are actually contained in a library MicrosoftAjax.js, which I’m assuming isn’t strictly a a part of CRM but instead a part of – go figure – the MS AJAX library. :) Below is a screen shot of a string attribute named “new_QualityFocused” that has the methods attached. Handy!

Tags: , , , , , ,


Customizing and Developing for MS CRM 2011

MS CRM 2011 has been officially released. I finally had some time to spend looking at it last week and I really, really like what I see from a customization and development perspective. Some of the pain has been taken out of customizing MS CRM. But, as with any new version of software, good documentation is hard to find. Since I spent a good part of my learning & playing with MS CRM 2011 finding documentation, I thought I would share some of the links I’ve found that serve as good references and resources to help me get up to speed on the new version.

Form Scripting

When it comes to form scripting, the whole model has changed. Things used to be referenced by “crmForm.property”, but that has been deprecated. It still works, but you should begin using the newly provided Xrm.Page object model. This article explains what the Xrm.Page model is, the collections of various items in the page model as well as a good overview.

Web Services

The web services in MS CRM have changed as well. It used to be there were two services: the main data service and the metadata web service. MS CRM 2011 still has two web services, but they are different. The first is a RESTful web service that uses oData. If you’re not familiar with oData, you can check it out here. [Update 2011-06-27: I've added a post on our blog with some examples of oData in CRM 2011.] Blogger TechHike has a post on “How to get started with oData” that explains the fundamentals of oData. If you want to use oData in CRM 2011, you can find out how to use it in CRM here. Be forewarned that the MS CRM oData service doesn’t fully implement all oData functions. The other web service uses SOAP. You can read about the differences and which is preferred for various scenarios here.

JavaScript

CRM 2011 allows you to include JavaScript libraries – usable blocks of code that can be shared amongst multiple forms and events. Before you had to resort to lots of trickeration to get things like this done. Here is an overview.

Plugins

Plugins aren’t new, but there are some new things about plugins. For a great overview of plugins, this page is a great springboard for other links.

Lastly, for some great videos that explain lots of things about MS CRM, Channel 9 at MSDN has a library of videos that covers a wide variety of topics. In my experience you can just jump right in on a given video that interests you and you won’t be lost if you haven’t seen the others.

CRM 2011 brings a lot of new things to the table from a customization and development perspective and learning them all will take time. Hopefully these links will get you started or at least give you a reference point. I suspect I’ll be bringing up this post for my own use in the future!

Tags: , , ,


Random Error Message: Mandatory updates for Microsoft Dynamics CRM could not be applied successfully

I was installing the Microsoft Outlook CRM client and got the error message:

Mandatory updates for Microsoft Dynamics CRM could not be applied successfully.

I didn’t bother reading any instructions before installing and when prompted to enter the server, I entered:

http://crmtest/OrgName

I solved the problem by removing the “/OrgName” from the URL I had entered.  From there, everything was fine.

Tags: ,