OData PostTo Navigation Property - Grid Crashes

5 posts, 0 answers
  1. Greg
    Greg avatar
    35 posts
    Member since:
    Sep 2013

    Posted 17 Oct 2014 Link to this post

    I am using a GridView with a QueryableDataServiceCollectionView data source in a MVVM WPF application.

    Relevant data involved (Entity Framework is in use on the server) are SecurityDomain, SecurityRole and SecurityDomainSecurityRole.

    SecurityDomain and SecurityRole are EntityFramework entities with corresponding database tables.

    SecurityDomainSecurityRole is a navigation property that is represented in the database as a table, but not as an EntityFramework entity. This navigation property represents the many to many relationship between SecurityDomain and SecurityRole.

    I use the "expand" property of the QueryableDataServiceCollectionView to retrieve SecurityDomains along with each of their related SecurityRoles.

    SecurityDomains = new QueryableDataServiceCollectionView<SecurityDomain>(odataServiceD.Service, odataServiceD.Entity);
    SecurityDomains.Expand = "SecurityRoles";

    Retrieve into grid works fine, as does update and delete of SecurityDomains.


    The problem: When I add an existing SecurityRole to a SecurityDomain (that was not previously associated with that SecurityRole) and SubmitChanges(), the OData controller method on the server, "SecurityDomainController.PostToSecurityRoles" executes and successfully adds a row into the database table SecurityDomainSecurityRole, but whatever I return from this method crashes the client.


    Using method signature "public IHttpActionResult PostToSecurityRoles([FromODataUri] int key, SecurityRole securityRole)", the following returns result in a "The context is already tracking a different entity with the same resource Uri." client crash:

    return Created(securityRole); // securityRole is the parameter.

    return Created(sr); // sr is the newly created securityRole object.

    var location = String.Format("{0}/{1}({2})/{3}({4})", Request.RequestUri, "SecurityDomains", key, "SecurityRoles", sr.Id);
    return Created(location, sr);


    With the same signature, this return results in a "The response to this POST request did not contain a 'location' header. That is not supported by this client." client crash.

    return StatusCode(HttpStatusCode.NoContent);


    With the same signature, using a "Created(SecurityDomain)" style return result in  "No NavigationLink factory was found for the navigation property 'SecurityRoles' from entity type
    'DB.Domain.Entities.SecurityDomain' on entity set 'SecurityRole'. Try calling HasNavigationPropertyLink on the EntitySetConfiguration" client crashes. These are the returns like this:

    return Created(businessLayer.SecurityDomain(key));

    var sd = businessLayer.WithSecurityRoles(key);
    return Created(sd);


    If I change the method signature to "public HttpResponseMessage PostToSecurityRoles([FromODataUri] int key, SecurityRole securityRole)", the following returns result in "The response to this POST request did not contain a 'location' header. That is not supported by this client." client crashes:

    return Request.CreateResponse(HttpStatusCode.Created, securityRole);

    return Request.CreateResponse(HttpStatusCode.NoContent);


    So my question is basically what does the GridView/QueryableDataServiceCollectionView want to get back from the Odata controller? If the Grid just kept running and refreshed, everything would be fine. The database is getting updated correctly.

    Thanks.
  2. Nick
    Admin
    Nick avatar
    593 posts

    Posted 21 Oct 2014 Link to this post

    Hello Greg,

    I am not sure what goes wrong in your case. Would it be possible to share the exact exception error message and stack trace? 

    Regards,
    Nik
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  3. Greg
    Greg avatar
    35 posts
    Member since:
    Sep 2013

    Posted 22 Oct 2014 in reply to Nick Link to this post

    Using "return Created(securityRole);" in the odata controller results in the client crashing with the Message and StackTrace below.

    This makes sense since no new entity is actually being created. Only a new navigation property between entities is being created. The grid being edited in the client is representing relationships, not entities, so when you add a row to the grid and save it, there is no new entity key to return. I have another window that is almost identical to this one except that its grid edits actual entities instead of relationships and it works fine.

    What I want to know is what the odata controller can return that will tell the QueryableDataServiceCollectionView / GridView that the action was a success and not crash the client.

    Message: "The context is already tracking a different entity with the same resource Uri."

    StackTrace: "   at System.Data.Services.Client.EntityTracker.ValidateDuplicateIdentity(String identity, EntityDescriptor descriptor)
       at System.Data.Services.Client.EntityTracker.AttachLocation(Object entity, String identity, Uri editLink)
       at System.Data.Services.Client.BaseSaveResult.HandleOperationResponseHeaders(HttpStatusCode statusCode, HeaderCollection headers)
       at System.Data.Services.Client.BaseSaveResult.AsyncEndGetResponse(IAsyncResult asyncResult)"
  4. Nick
    Admin
    Nick avatar
    593 posts

    Posted 27 Oct 2014 Link to this post

    Hello Greg,

    This indeed seems strange. Nevertheless I am not seeing any Telerik classes in the stack trace. Do you get the same problem with WPFs default services? If the problem is only with telerik binaries, would it be possible to prepare a small sample that shows the problem that we can debug and send it us? This will greatly help in the process of finding a solution to the problem. 

    Thank you in advance. 

    Regards,
    Nik
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  5. Greg
    Greg avatar
    35 posts
    Member since:
    Sep 2013

    Posted 30 Oct 2014 in reply to Nick Link to this post

    At some point I hope to prepare a demo of this.

    For now, to make this work I simply added a meaningless attribute to the many to many relationship so that Entity Framework sees it as an Entity and has a new key value to return to the client.
Back to Top