This is a migrated thread and some comments may be shown as answers.

OData PostTo Navigation Property - Grid Crashes

4 Answers 205 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Greg
Top achievements
Rank 1
Greg asked on 17 Oct 2014, 05:58 PM
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.

4 Answers, 1 is accepted

Sort by
0
Nick
Telerik team
answered on 21 Oct 2014, 12:34 PM
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.

 
0
Greg
Top achievements
Rank 1
answered on 22 Oct 2014, 07:28 PM
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)"
0
Nick
Telerik team
answered on 27 Oct 2014, 12:38 PM
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.

 
0
Greg
Top achievements
Rank 1
answered on 30 Oct 2014, 07:18 PM
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.
Tags
GridView
Asked by
Greg
Top achievements
Rank 1
Answers by
Nick
Telerik team
Greg
Top achievements
Rank 1
Share this question
or