The OData questions keep coming :)
I have an Entity with a composite key, like this one:
public class Entity
{
public virtual Int32 FirstId { get; set; }
public virtual Guid SecondId { get; set; }
public virtual First First { get; set; }
public virtual Second Second { get; set; }
}
I created a CompositeKeyRoutingConvention that handles the composite keys for ODataController
s. Everything is working, except Navigation Links like this one:
http://localhost:51590/odata/Entities(FirstId=1,SecondId=guid'...')/First
I get the following error message in Firefox:
<?xml version="1.0" encoding="utf-8"?>
<m:error xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<m:code />
<m:message xml:lang="en-US">No HTTP resource was found that matches the request URI 'http://localhost:51950/odata/Entities(FirstId=1,SecondId=guid'a344b92f-55dc-45aa-b92f-271d74643493')/First'.</m:message>
<m:innererror>
<m:message>No action was found on the controller 'Entities' that matches the request.</m:message>
<m:type></m:type>
<m:stacktrace></m:stacktrace>
</m:innererror>
</m:error>
I traced the error message in the ASP.NET source code to the FindMatchingActions method in the ApiControllerActionSelector returning an empty list, but my knowledge of ASP.NET ends there.
For reference, this is the implementation of the navigation link action method (in an ODataController
):
public First GetFirst(
[FromODataUri(Name = "FirstId")] Int32 firstId,
[FromODataUri(Name = "SecondId")] Guid secondId)
{
var entity = repo.Find(firstId, secondId);
if (entity == null) throw new HttpResponseException(HttpStatusCode.NotFound);
return entity.First;
}
I tried not setting a name at the FromODataUri
attribute, setting a lowercase name, everything sensible I could think of. The only thing I noticed is when using a regular EntitySetController
is that the arguments for the key value have to be named key
(or the FromODataUri
attribute has to have the Name property set to key
), otherwise it won't work. I wonder if something like this is the case here as well...
I found what was missing:
In addition to a custom
EntityRoutingConvention
, you will need a customNavigationRoutingConvention
.And just add this to the front of the conventions like the custom
EntityRoutingConvention
. Done :)Update for the comment below:
You have to implement your own
NavigationRoutingConvention
that overrides theSelectAction
method and splits the composite keys inside the controller context into key and values. Then you have to add them to the route values yourself.Finally, in the configuration, where you call
MapODDataRoute
with your customEntityRoutingConvention
already, add the newNavigationRoutingConvention
to the list of conventions.NavigationRoutingConvention in C#:
Finally, you have to add it to the OData route (presumably in
App_Start/WebApiConfig.cs
), where you already added theEntityRoutingConvention
.