的ASP.NET Web API的OData:使用组合键时,导航链接 [英] ASP.NET Web API OData: Navigation Links when using Composite Keys
问题描述
在OData的问题不断传来:)
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; }
}
我创建了一个 CompositeKeyRoutingConvention 处理该组合键为 ODataController
秒。一切正常,除了导航链接像这样的:
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
我在Firefox中收到以下错误信息:
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>
我跟踪在ASP.NET源$ C $ c中的错误信息<一个href=\"http://aspnetwebstack.$c$cplex.com/SourceControl/latest#src/System.Web.Http/Controllers/ApiControllerActionSelector.cs\"相对=nofollow>在ApiControllerActionSelector的FindMatchingActions 的方法返回一个空的列表,但我的ASP.NET的认识仅止于此。
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.
作为参考,这是导航链接操作方法的实现(在 ODataController
)
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;
}
我试过在 FromODataUri
属性设置不是一个名字,创下了小写的名字,一切都懂事我能想到的。使用时,我注意到的唯一的事情是一个普通的 EntitySetController
是项值的参数都被命名为键
(或 FromODataUri
属性必须有名称属性设置为键
),否则将无法正常工作。我不知道这样的事情在这里的话,以及...
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...
推荐答案
我找到了失踪:
在除了自定义的 EntityRoutingConvention
,您将需要一个定制 NavigationRoutingConvention
。
In addition to a custom EntityRoutingConvention
, you will need a custom NavigationRoutingConvention
.
type CompositeKeyNavigationRoutingConvention () =
inherit NavigationRoutingConvention ()
override this.SelectAction (odataPath, controllerContext, actionMap) =
match base.SelectAction (odataPath, controllerContext, actionMap) with
| null -> null
| action ->
let routeValues = controllerContext.RouteData.Values
match routeValues.TryGetValue ODataRouteConstants.Key with
| true, (:? String as keyRaw) ->
keyRaw.Split ','
|> Seq.iter (fun compoundKeyPair ->
match compoundKeyPair.Split ([| '=' |], 2) with
| [| keyName; keyValue |] ->
routeValues.Add (keyName.Trim (), keyValue.Trim ())
| _ -> ()
)
| _ -> ()
action
和只添加这对公约的像定制 EntityRoutingConvention
的前面。完成:)
And just add this to the front of the conventions like the custom EntityRoutingConvention
. Done :)
更新下面的评论:
您必须实现自己的 NavigationRoutingConvention
的覆盖 SelectAction
方法并拆分控制器上下文中的组合键成键和值。然后,你必须将它们添加到路由值自己。
You have to implement your own NavigationRoutingConvention
that overrides the SelectAction
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.
最后,在配置上,在那里你叫 MapODDataRoute
与您的自定义 EntityRoutingConvention
已经添加了新的 NavigationRoutingConvention
来的公约清单。
Finally, in the configuration, where you call MapODDataRoute
with your custom EntityRoutingConvention
already, add the new NavigationRoutingConvention
to the list of conventions.
NavigationRoutingConvention在C#中:
public class CompositeKeyNavigationRoutingConvention : NavigationRoutingConvention
{
public override String SelectAction(System.Web.OData.Routing.ODataPath odataPath, HttpControllerContext controllerContext, ILookup<String, HttpActionDescriptor> actionMap)
{
String action = base.SelectAction(odataPath, controllerContext, actionMap);
// Only look for a composite key if an action could be selected.
if (action != null)
{
var routeValues = controllerContext.RouteData.Values;
// Try getting the OData key from the route values (looks like: "key1=value1,key2=value2,...").
Object keyRaw;
if (routeValues.TryGetValue(ODataRouteConstants.Key, out keyRaw))
{
// Split the composite key into key/value pairs (like: "key=value").
foreach (var compoundKeyPair in ((String)keyRaw).Split(','))
{
// Split the key/value pair into its components.
var compoundKeyArray = compoundKeyPair.Split(new[] { '=' }, 2);
if (compoundKeyArray.Length == 2)
// Add the key and value of the composite key to the route values.
routeValues.Add(compoundKeyArray[0].Trim(), compoundKeyArray[1].Trim());
}
}
}
return action;
}
}
最后,你必须将它添加到OData的路线(presumably在 App_Start / WebApiConfig.cs
),在那里你已经添加了 EntityRoutingConvention
。
Finally, you have to add it to the OData route (presumably in App_Start/WebApiConfig.cs
), where you already added the EntityRoutingConvention
.
这篇关于的ASP.NET Web API的OData:使用组合键时,导航链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!