的ASP.NET Web API的OData:使用组合键时,导航链接 [英] ASP.NET Web API OData: Navigation Links when using Composite Keys

查看:187
本文介绍了的ASP.NET Web API的OData:使用组合键时,导航链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在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 ODataControllers. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆