locked
Cannot create a record using microsoft.xRM SDK and WCF Data Service RRS feed

  • Question

  • Hi There,

    Can anyone help me with this issue? I'm working with the new xRM SDK, which I've found to be an incredible extension of the SDK. I have a WCF data service built on the xRM data context. Using this data service in a Silverlight project, I can successfully query and return CRM data through the data service.

    However, I cannot create a record. I have tested and I can create a record in my web project, using the xRM SDK directly.

    //This works in synchronous code, directly using the xRM SDK
    dtx.AddObject("account", a);
    dtx.SaveChanges();
    
    //So does this (the EntitySetName seems to accept singular or plural "account(s)"
    dtx.AddObject("accounts", a);
    dtx.SaveChanges();
    
    //In my Silverlight project, where I need to use asynchronous calls, neither of the following work:
    //TRY 1
    svc.AddObject("account", a);
    svc.BeginSaveChanges(SaveChangesOptions.Batch, on_update, svc);
    
    /*RETURNS THE FOLLOWING ERROR:
    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
     <code></code>
     <message xml:lang="en-US">Resource not found for the segment 'account'.</message>
    </error>
    */
    
    //TRY 2 - MADE "ACCOUNTS" PLURAL
    svc.AddObject("accounts", a);
    svc.BeginSaveChanges(SaveChangesOptions.Batch, on_update, svc);
    
    /*RETURNS TEH FOLLOWING ERROR:
    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
     <code></code>
     <message xml:lang="en-US">An error occurred while processing this request.</message>
    </error>
    */
    

    Entire code block and Data Service configuration below. If anyone can guide me, I would really appreciate it - thanks!

     

    private void TextEntry_TextChanged(object sender, TextChangedEventArgs e)
    {
     TextBox textentry = (TextBox)sender;
     account a = new account();
     a.name = "From Code";
    
     svc.AddObject("accounts", a);
     svc.BeginSaveChanges(SaveChangesOptions.Batch, on_update, svc);
    }
    
    public void on_update(IAsyncResult ar)
    {
     Dispatcher.BeginInvoke(() =>
     {
     svc = ar.AsyncState as DataContext;
     //try
     // {
     WriteOperationResponse(svc.EndSaveChanges(ar));
     // }
     // catch (DataServiceRequestException ex)
     // {
     // WriteOperationResponse(ex.Response);
     //}
     //catch (InvalidOperationException ex)
     //{
     // throw ex;
     //}
     }
     );
    }
    
    private void WriteOperationResponse(DataServiceResponse response)
    {
     string messageTextBlock = string.Empty;
     int i = 1;
     if (response.IsBatchResponse)
     {
     messageTextBlock = string.Format("Batch operation response code: {0}\n",
     response.BatchStatusCode);
     }
     foreach (ChangeOperationResponse change in response)
     {
     messageTextBlock +=
     string.Format("\tChange {0} code: {1}\n",
     i.ToString(), change.StatusCode.ToString());
     if (change.Error != null)
     {
     messageTextBlock +=
     string.Format("\tChange {0} error: {1}\n",
     i.ToString(), change.Error.Message);
     }
    
     i++;
     }
    }
    

    Data Service Configuration:

    namespace InvocConvo.Web
    {
     public class convoservice : DataService< DataContext >
     {
     // This method is called only once to initialize service-wide policies.
     public static void InitializeService(DataServiceConfiguration config)
     {
     ClearCache("account");
     config.SetEntitySetAccessRule("*", EntitySetRights.All);
     config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
     config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
     }
    
     public static void ClearCache(string entityName)
     {
     const string format = "adxdependency:crm:entity:{0}";
     var dependency = string.Format(format, entityName).ToLower();
     var cache = Microsoft.Xrm.Client.Caching.CacheManager.GetBaseCache();
     cache.Remove(dependency);
     }
     }
    }
    
    Thursday, July 29, 2010 4:01 PM

Answers

  • I finally got it working -

    Aaron was right, the issue involved the "label" fields not having any set methods in the classes generated by the crmsvcutil tool.

    /// <summary>
    /// Reason for the status of the entity (Label for statuscode)
    /// </summary>
    [global::Microsoft.Xrm.Client.Linq.CrmNamed("statuscode")]
    public global::System.String statuscodeLabel
    {
    	get { return this.GetPropertyLabel("statuscode"); 
    }
    

    You can get around this, as long as you don't have to actually use this property in your data service, by adding it to this piece of code at the top of the class generated for the entity you're working with:

    [global::System.Data.Services.IgnoreProperties("ownerid", "statuscodeLabel")]
    
    Hope this helps someone!
    Web: http://invoc.net Blog: http://invoc.net/CRM_BPOS_Blog
    Sunday, August 15, 2010 1:33 AM

All replies

  • Can you enable verbose errors in your Data Service configuration and reply back with the full stack trace?

     

    // Add this to your convoservice

    config.UseVerboseErrors = true;


    || Aaron Elder - Dynamics CRM MVP || http://xrm.ascentium.com/blog/crm
    Monday, August 2, 2010 6:47 PM
  • Hi Aaron,

    You bet - thanks for the reply! I found the culprit in the message of the inner exception, the "Property set method not found". I was told that this was probably because the xRM sdk is a reflection provider and doesn't implement IUpdatable. So I'm working on that now. This was advice from a Data Service perspective, but if you know anything more concrete for the xRM sdk, I'd love to hear it.

    Thanks!

    Outer Exception:
       at System.Data.Services.Client.SaveResult.HandleBatchResponse()
       at System.Data.Services.Client.SaveResult.EndRequest()
       at System.Data.Services.Client.DataServiceContext.EndSaveChanges(IAsyncResult asyncResult)
       at InvocConvo.MainPage.<>c__DisplayClass7.<on_update>b__6()

    Inner Exception:System.Data.Services.Client.DataServiceClientException
    MESSAGE:
    <?xml version="1.0" encoding="utf-8" standalone="yes"?>
    <error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
      <code></code>
      <message xml:lang="en-US">An error occurred while processing this request.</message>
      <innererror>
        <message>Property set method not found.</message>
        <type>System.ArgumentException</type>
        <stacktrace>   at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)&#xD;
       at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, Object[] index)&#xD;
       at Microsoft.Xrm.Client.Data.Services.CrmDataContext.System.Data.Services.IUpdatable.SetValue(Object targetResource, String propertyName, Object propertyValue)&#xD;
       at System.Data.Services.Serializers.Deserializer.SetPropertyValue(ResourceProperty resourceProperty, Object declaringResource, Object propertyValue, ContentFormat contentFormat, IDataService service)&#xD;
       at System.Data.Services.Serializers.PlainXmlDeserializer.ApplyProperty(XmlReader reader, String propertyName, ResourceType resourceType, Object resource)&#xD;
       at System.Data.Services.Serializers.PlainXmlDeserializer.ApplyContent(XmlReader reader, ResourceType resourceType, Object resource)&#xD;
       at System.Data.Services.Serializers.PlainXmlDeserializer.ApplyContent(Deserializer deserializer, XmlReader reader, ResourceType resourceType, Object resource, EpmAppliedPropertyInfo propertiesApplied, Int32 currentObjectCount)&#xD;
       at System.Data.Services.Serializers.SyndicationDeserializer.ApplyProperties(SyndicationItem item, ResourceType resourceType, EpmAppliedPropertyInfo propertiesApplied, Object resource)&#xD;
       at System.Data.Services.Serializers.SyndicationDeserializer.CreateObject(SegmentInfo segmentInfo, Boolean topLevel, SyndicationItem item)&#xD;
       at System.Data.Services.Serializers.SyndicationDeserializer.CreateSingleObject(SegmentInfo segmentInfo)&#xD;
       at System.Data.Services.Serializers.Deserializer.ReadEntity(RequestDescription requestDescription)&#xD;
       at System.Data.Services.Serializers.Deserializer.HandlePostRequest(RequestDescription requestDescription)&#xD;
       at System.Data.Services.DataService`1.HandlePostOperation(RequestDescription description, IDataService dataService)&#xD;
       at System.Data.Services.DataService`1.ProcessIncomingRequest(RequestDescription description, IDataService dataService)&#xD;
       at System.Data.Services.DataService`1.BatchDataService.HandleBatchContent(Stream responseStream)</stacktrace>
      </innererror>
    </error>

    STACK TRACE
       at System.Data.Services.Client.SaveResult.<HandleBatchResponse>d__10.MoveNext()


    Web: http://invoc.net Blog: http://invoc.net/CRM_BPOS_Blog
    Monday, August 2, 2010 7:08 PM
  • Actually, the documentation at the link below says that the classes generated by the crmsvcutil.exe tool DO implement the IUpdatable interface -

    http://msdn.microsoft.com/en-us/library/ff681561.aspx ("Data Context Classes" section).

    So I'm at a loss to understand why I can't update from the DataService that passes the DataContext as its Data Source, but I can from the DataContext directly.


    Web: http://invoc.net Blog: http://invoc.net/CRM_BPOS_Blog
    Monday, August 2, 2010 9:07 PM
  • Yeah, I am actually having the exact same problem and I a too am confused by the documentation.

    The Microsoft.Xrm.Client actually supports ASP.NET tracing; so if you turn that on you and go to the Trace Viewer; you will see what it is having a problem with.  The issue appears to be that the generated class does not have a "Set" method for the various "Label" fields (like statuscodelabel) and it tries to set it.

    I hacked up my xrm.cs file to have empty Set{}'s and that got past this issue; only to have it complain that OwerId had to be set (which the proxy marks as "ignore") - getting around that; leads to an "Object not set to a reference" error from CRM.

     

    Still looking.


    || Aaron Elder - Dynamics CRM MVP || http://xrm.ascentium.com/blog/crm
    Tuesday, August 3, 2010 3:14 AM
  • Thanks Aaron - I was considering doing something similar, to try to implement the IUpdatable interface on the DataContext class. I was working directly in the DataContext.part.cs file (I had the crmsvcutil generate separate files). I see it implements IQueryable everywhere, but I searched and didn't find IUpdatable anywhere in the entire solution. However, that link I gave above said that the xrm classes ALREADY implement IUpdatable, so I stopped following that route.

    I had been asking this question in the WCF Data Services forum as well, and had some help from a moderator there (http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataservices/thread/855bed3d-6631-4679-97a8-a063f02f63db/?prof=required). I let him know what we were trying (pasted your steps there as well) and asked for any final advice, but it does seem clear that the problem is on our side with the classes generated by crmsvcutil.


    Web: http://invoc.net Blog: http://invoc.net/CRM_BPOS_Blog
    Tuesday, August 3, 2010 1:22 PM
  • Hey Aaron (or others),

    Have you turned up any additional information on this subject? I'm still stuck in the same spot.


    Web: http://invoc.net Blog: http://invoc.net/CRM_BPOS_Blog
    Thursday, August 5, 2010 2:05 PM
  • I am stuck on the same problem... Any help???
    Thursday, August 5, 2010 2:56 PM
  • Trying to keep this on the list - someone has to have an answer. Anyone?
    Web: http://invoc.net Blog: http://invoc.net/CRM_BPOS_Blog
    Monday, August 9, 2010 3:36 PM
  • This may or may not help as you are way above my head.  But i did get the same error using the xRM in a console app.  you have to create the owner object

    new Owner("systemuser",userid) //userid would obviously be a GUID

     

    I would love to see your app if possible, I'm interested in writing my own some day.  Examples of replicating lookups would be huge!!!!


    Withers *Check out my javascript working examples on my blog http://withersblog.withersdavid.com/
    Monday, August 9, 2010 6:26 PM
  • Hi David,

    Thanks for the advice. I tried to assign an owner just to be sure - the calls are a bit different when coding from a WCF data service, but the issue is independent of that value.

    Thanks!


    Web: http://invoc.net Blog: http://invoc.net/CRM_BPOS_Blog
    Monday, August 9, 2010 7:53 PM
  • Anyone? Not finding any forthcoming answers to this...
    Web: http://invoc.net Blog: http://invoc.net/CRM_BPOS_Blog
    Wednesday, August 11, 2010 5:54 PM
  • I finally got it working -

    Aaron was right, the issue involved the "label" fields not having any set methods in the classes generated by the crmsvcutil tool.

    /// <summary>
    /// Reason for the status of the entity (Label for statuscode)
    /// </summary>
    [global::Microsoft.Xrm.Client.Linq.CrmNamed("statuscode")]
    public global::System.String statuscodeLabel
    {
    	get { return this.GetPropertyLabel("statuscode"); 
    }
    

    You can get around this, as long as you don't have to actually use this property in your data service, by adding it to this piece of code at the top of the class generated for the entity you're working with:

    [global::System.Data.Services.IgnoreProperties("ownerid", "statuscodeLabel")]
    
    Hope this helps someone!
    Web: http://invoc.net Blog: http://invoc.net/CRM_BPOS_Blog
    Sunday, August 15, 2010 1:33 AM