Code

When you update records using Silverlight and the REST Endpoint for Web resources, unless you have worked around this issue you are updating every field even if the data hasn’t changed. This can lead to the following problems:

  • Potential for data loss
  • Auditing data does not correctly reflect actual changes
  • Event driven features such as Workflows (Processes) and Plug-ins execute when they are not needed

This post will describe the issue and provide a technique to avoid the problems.

Issue Description

The Microsoft Dynamics CRM SDK documents the following in the topic: Perform Basic Data Operations in Microsoft Dynamics CRM Using the REST Endpoint.

clip_image002

This behavior is a result of the way that a Silverlight application project generates proxies to work with an OData service. By default all properties defined for an entity are sent in an update request when you use the DataServiceContext.BeginSaveChanges Method. If you are working with an entity instance that was retrieved from a query it will contain all the current values and saving changes will update all the properties of the entity instance with those values even if they have not changed. If you instantiate a new entity instance and only update a few properties the update will overwrite other properties using the default null value for properties you haven’t set.

Technique to Avoid this Problem

To address this problem you need to provide some capability in your Silverlight application to track which properties have changed and only submit those properties when you save changes. Michael created the following solution that extends the Data Service Context to include change tracking for entity properties. I’ve found that it is relatively easy to apply this to an existing Silverlight application. Use the following steps to add and edit a new class file to your project:

Apply Data Service Context Extensions to A Silverlight Application Project:

1. Add a reference to System.Xml.Linq to your Silverlight application project if it doesn’t already exist

2. Create a new class file for your Silverlight application project. You might call it DataServiceContextExtensions.cs.

3. Paste the following code into the new file:

using System;
using System.Linq;
using System.Data.Services.Client;
using System.Reflection;
using System.Collections.Generic;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Xml.Linq;
namespace [[The Namespace of your Data Service Context]]
{
 partial class [[The name of your DataServiceContext Class]]
 {
  #region Methods
  partial void OnContextCreated()
  {
   this.ReadingEntity += this.OnReadingEntity;
   this.WritingEntity += this.OnWritingEntity;
  }
  #endregion
  #region Event Handlers
  private void OnReadingEntity(object sender, ReadingWritingEntityEventArgs e)
  {
   ODataEntity entity = e.Entity as ODataEntity;
   if (null == entity)
   {
    return;
   }
   entity.ClearChangedProperties();
  }
  private void OnWritingEntity(object sender, ReadingWritingEntityEventArgs e)
  {
   ODataEntity entity = e.Entity as ODataEntity;
   if (null == entity)
   {
    return;
   }
   entity.RemoveUnchangedProperties(e.Data);
  }
  #endregion
 }
 public abstract class ODataEntity
 {
  private readonly Collection<string> ChangedProperties = new Collection<string>();
  public ODataEntity()
  {
   EventInfo info = this.GetType().GetEvent("PropertyChanged");
   if (null != info)
   {

PropertyChangedEventHandler method = new PropertyChangedEventHandler

(this.OnEntityPropertyChanged);

    //Ensure that the method is not attached and reattach it
    info.RemoveEventHandler(this, method);
    info.AddEventHandler(this, method);
   }
  }
  #region Methods
  public void ClearChangedProperties()
  {
   this.ChangedProperties.Clear();
  }
  internal void RemoveUnchangedProperties(XElement element)
  {
   const string AtomNamespace = "http://www.w3.org/2005/Atom";
   const string DataServicesNamespace = "http://schemas.microsoft.com/ado/2007/08/dataservices";
   const string DataServicesMetadataNamespace = DataServicesNamespace + "/metadata";
   if (null == element)
   {
    throw new ArgumentNullException("element");
   }
   List<XElement> properties = (from c in element.Elements(XName.Get("content", AtomNamespace)
               ).Elements(XName.Get("properties", DataServicesMetadataNamespace)).Elements()
                                select c).ToList();
   foreach (XElement property in properties)
   {
    if (!this.ChangedProperties.Contains(property.Name.LocalName))
    {
     property.Remove();
    }
   }
  }

private void OnEntityPropertyChanged(object sender,

System.ComponentModel.PropertyChangedEventArgs e)

  {
   if (!this.ChangedProperties.Contains(e.PropertyName))
   {
    this.ChangedProperties.Add(e.PropertyName);
   }
  }
  #endregion
 }
}

4. In the file you created replace the following placeholders with the correct references for your project:

image

5. Update the Reference.cs file

a. In Visual Studio 2010, click the icon with the tooltip Show All Files at the top of the Solution Explorer window.

b. In Solution Explorer, expand the service reference you created and the Reference.datasvcmap file to view the Reference.cs file.

c. Use Find/Replace to change:

: global::System.ComponentModel.INotifyPropertyChanged

to

: ODataEntity, global::System.ComponentModel.INotifyPropertyChanged

Note: There should be one instance for each entity.

6. Recompile your project, update your Silverlight Web resource with the new .xap file and test it.

SDK Update

In next release of the SDK (version 5.05) the SDK topic Use the REST Endpoint with Silverlight Web Resources will contain steps include this method. Each of the Silverlight samples that update records will also be updated to include these extensions.

Cheers,

Jim Daly, Michael Scott



{ 0 comments }

There’s a CRM training course out now and you can read about it here: Developer Training Course for Microsoft Dynamics CRM 2011! The training course helps .NET developers learn various development features of Microsoft Dynamics CRM 2011 and Microsoft Dynamics CRM Online and build applications on top of these platforms. The article contains the training course download information and a brief description of the presentations, videos, and hands-on labs that are included.

The article highlights the following areas that are covered in the course: 

  • Introduction to the Dynamics CRM 2011 Training Course
  • Solutions in Dynamics CRM 2011
  • User Experience Extensibility
  • Visualizations and Dashboards
  • WCF Web Services
  • LINQ and oData
  • Plug-ins
  • Processes
  • Client Programming
  • Silverlight
  • SharePoint and CRM
  • Azure
  • Upgrading from CRM 4.0 to CRM 2011
  • Dynamics Marketplace

We hope the training course will help you ramp up with building new applications for Microsoft Dynamics CRM 2011 and Microsoft Dynamics CRM Online. 

As always, we’d like to hear from you!

Additional Resources

Cheers,

Inna Agranov



{ 0 comments }

CRM 2011 Charts – Know the Real Potential ~ Part Deux

May 2, 2011

Hello readers, this post is in continuation of my ”Getting to Know Charts” blog series, where we discuss useful features of charts. In the introductory post of this series we learned how to create a 3D chart and a multi series chart. Let’s answer…

Read the full article →

Creating Custom Sample Data for CRM 2011 – Advanced

April 29, 2011

We learned how to create a simple sample data for Microsoft Dynamics CRM 2011 in the blog post titled Creating Custom Sample Data for CRM 2011. In this post, we will take a look at some of the more advanced sample data building techniques. Building a…

Read the full article →

JScript IntelliSense for Form Script Libraries

April 7, 2011

In the latest release of the Microsoft Dynamics SDK (Version 5.0.3) you will find a Microsoft Dynamics CRM Solution and Visual Studio extension that together will provide IntelliSense support for the Xrm.Page object in form scripts. I hope that this so…

Read the full article →

Create Dynamic Ribbon Controls

March 30, 2011

Microsoft Dynamics CRM 2011 uses Ribbons (also known as Fluent UI) to provide a user interface to display the right commands at the right time. Ribbons also provide a very powerful and flexible way of extending the ribbon functionality to meet your req…

Read the full article →

Microsoft Dynamics CRM Online 2011 Web Services SOAP Sample now ready for Europe & Asia

March 28, 2011

The recent code sample I published on Connecting to CRM Online 2011 Web Services using SOAP Requests Only was well received by many people however a few developers from Europe & Asia mentioned that they were getting (500) Internal Server Error when they were trying out the code. I then realized that CRM 2011 Web Service URLs had a different format in Europe & Asia which helped me to find the culprit.

I signed up for a CRMOnline European trial account and putting the SDK sample under Fiddler inspection revealed that it was a minor change within one of the XML fragments. That’s it, seriously!

<a:Address>urn:crm:dynamics.com</a:Address>  to <a:Address>urn:crm4:dynamics.com</a:Address>

Obviously crm4 is used in our European datacenter and crm5 is used in our Asian datacenter so I had to modify the code to use the appropriate URN address.

// Create the URN address of the format urn:crm:dynamics.com. // Replace crm with crm4 for Europe & crm5 for Asia.string URNAddress = "urn:crm:dynamics.com";if (CRMUrl.IndexOf("crm4.dynamics.com") != -1)    URNAddress = "urn:crm4:dynamics.com";if (CRMUrl.IndexOf("crm5.dynamics.com") != -1)    URNAddress = "urn:crm5:dynamics.com";

You can download the updated code sample here:

http://code.msdn.microsoft.com/CRM-Online-2011-WebServices-14913a16

All is well again!

Girish Raja

Read the full article →

Custom Charting Capabilities in Microsoft Dynamics CRM 2011

January 19, 2011

Microsoft Dynamics CRM 2011 comes with in-built visual analytics. You can create charts to view aggregations of your CRM data over various dimensions, providing nice visual and interactive tools to analyze data. But, there is more to it. It also provi…

Read the full article →