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.
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.