加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-mvc – 在MVC WebApi中的方法如何映射到http动词?

发布时间:2020-12-15 19:07:13 所属栏目:asp.Net 来源:网络整理
导读:在下面链接的5分钟视频中,在1:10标记,Jon Galloway说,添加一个名为DeleteComment的方法到他的CommentsController控制器类将按照惯例映射到删除http动词。 MVC与WebApi如何知道如何解决方法到正确的动词?我知道global.asax.cs文件中的路由将请求路由到正
在下面链接的5分钟视频中,在1:10标记,Jon Galloway说,添加一个名为DeleteComment的方法到他的CommentsController控制器类将按照惯例映射到删除http动词。

MVC与WebApi如何知道如何解决方法到正确的动词?我知道global.asax.cs文件中的路由将请求路由到正确的控制器,但是删除请求如何“按惯例映射”到删除方法或任何方法?特别是当每个动词可以有超过1个方法时? “按照惯例”让我认为它只是看着方法名称中的第一个单词…但是如果是这样,它将必须读取方法的签名告诉两个删除方法或两个get方法分开…和是这个定义吗?

视频:
http://www.asp.net/web-api/videos/getting-started/delete-and-update

谢谢!

编辑:
这里是WebApi模板中的示例ValuesController类中的代码。这是我原来问题的来源。区分这些(和控制器中的任何其他方法)的“约定”如何工作?

// GET /api/values
    public IEnumerable<string> Get()
    {
        return new string[] { "value1","value2" };
    }

    // GET /api/values/5
    public string Get(int id)
    {
        return value;
    }

解决方法

我提前道歉,这个帖子偏离了你的问题,但所有这些冒出来,当我阅读你的问题。

WebAPI匹配语义
WebAPI中的(默认路由)使用的匹配语义相当简单。

>它匹配动作的名称与动词(verb = GET?查找以“get”开头的方法名称)
>如果一个参数被传递,api寻找一个带有参数的动作

因此,在您的代码示例中,没有参数的GET请求与没有参数的Get *()函数匹配。 Get包含和ID寻找Get ***(int id)。

例子
虽然匹配的语义很简单,但它对MVC开发人员(至少是开发人员)造成了一些混乱。让我们看一些例子:

奇怪的名称 – 你的get方法可以命名任何东西,只要它以“get”开头。所以在widget控制器的情况下,你可以命名你的函数GetStrawberry(),它仍然会匹配。把匹配想象为:methodname.StartsWith(“Get”)

多个匹配方法 – 如果有两个没有参数的Get方法会发生什么? GetStrawberry()和GetOrange()。最好的我可以告诉,函数定义第一(文件的顶部)在你的代码中赢得…奇怪。这有副作用,使一些方法在您的控制器不可达(至少与默认路由)….陌生人。

NOTE : the beta behaved as above for ‘matching multiple methods’ – the RC & Release version is a bit more OCD. It throws an error if there are multiple potential matches. This change removes the confusion of multiple ambiguous matches. At the same time,it reduces our ability to mix REST and RPC style interfaces in the same controller,relying on the order & overlapping routes.

该怎么办?
那么,WebAPI是新的和共识仍然合并。社区似乎在达到REST原则相当多。然而,不是每个API都可以或应该是RESTful,有些更自然地表示为RPC样式。 REST&什么人称为REST似乎是quite a bit of confusion,well at least to Roy Fielding的来源。

作为一个实用主义者,我怀疑许多API将是70%的RESTful,有一些微小的RPC风格方法。首先,控制器增殖单独(给定webapi绑定方法)将驱动开发人员bonkers。第二,WebAPI真的没有一个内置的方式来创建api路径的嵌套结构(意思是:/ api / controller /很容易,但/ api / CATEGORY / Sub-Category / Controller是可行的,但是痛苦)。

从我的角度来看,我很想看到webAPI文件夹结构控制默认的API路径…意思如果我在我的UI项目中创建一个类别文件夹,那么/ api / Category将是默认路径(parallel to this MVC article)。

我做了什么?
所以,我有几个要求:(1)能够在大多数情况下使用restful语法,(2)有一些“命名空间”控制器分隔(认为子文件夹),(3)能够调用额外的rpc-当需要时。实现这些要求归结于聪明的路由。

// SEE NOTE AT END ABOUT DataToken change from RC to RTM

Route r;
r = routes.MapHttpRoute( name          : "Category1",routeTemplate : "api/Category1/{controller}/{id}",defaults      : new { id = RouteParameter.Optional } );
r.DataTokens["Namespaces"] = new string[] {" UI.Controllers.Category1"};

r = routes.MapHttpRoute( name          : "Category2",routeTemplate : "api/Category2/{controller}/{id}",defaults      : new { id = RouteParameter.Optional } );
r.DataTokens["Namespaces"] = new string[] {" UI.Controllers.Category2"};

routes.MapHttpRoute(     name          : "ApiAllowingBL",routeTemplate : "api/{controller}/{action}/{id}",defaults      : new { id = RouteParameter.Optional } );

routes.MapHttpRoute(     name          : "DefaultApi",routeTemplate : "api/{controller}/{id}",defaults      : new { id = RouteParameter.Optional } );

>前两个路由创建“子文件夹”路由。我需要为每个子文件夹创建一个路由,但我限于自己的主要类别,所以我最终只有3-10。注意这些路由如何添加Namespace数据令牌,以限制搜索特定路由的类。这很好地对应于在向UI项目添加文件夹时的典型命名空间设置。
>第三个路由允许调用特定的方法名(如传统的mvc)。由于网络API不包含网址中的操作名称,因此很容易分辨出哪些呼叫需要此路由。
>最后一个路由条目是默认的web api路由。这捕获任何类,特别是我的’子文件夹’之外的类。

另一种说法
我的解决方案归结到分离控制器多一点/ api / XXXX没有得到太拥挤。

>我在我的UI项目中创建一个文件夹(让我们说Category1),并将api控制器放在该文件夹中。
> Visual studio自然地基于文件夹设置类命名空间。因此,Category1文件夹中的Widget1获取一个默认的UI.Category1.Widget1命名空间。
>当然,我想要api URL反映文件夹结构(/ api / Category1 / Widget)。你看到的第一个映射完成了,通过硬编码/ api / Category1到路由,然后命名空间令牌限制将搜索匹配控制器的类。

NOTE: as of the release DataTokens are null by default. I’m not
sure if 07006. So I wrote a little helper
method and added to my RouteConfig.cs file….

r.AddRouteToken("Namespaces",new string[] {"UI.Controllers.Category1"});

private static Route AddRouteToken(this Route r,string key,string[] values) {
  //change from RC to RTM ...datatokens is null
if (r.DataTokens == null) {
       r.DataTokens = new RouteValueDictionary();
    }
    r.DataTokens[key] = values;
    return r;
}

NOTE 2: even thought this is a WebAPI 1 post,as @Jamie_Ide points out in the comments the above solution doesn’t work in WebAPI 2 because IHttpRoute.DataTokens has no setter. To get around this you can use a simple extension method like this:

private static IHttpRoute MapHttpRoute(this HttpRouteCollection routes,string name,string routeTemplate,object defaults,object constraints,string[] namespaceTokens)
{   
    HttpRouteValueDictionary    defaultsDictionary      = new HttpRouteValueDictionary(defaults);
    HttpRouteValueDictionary    constraintsDictionary   = new HttpRouteValueDictionary(constraints);
    IDictionary<string,object> tokens                  = new Dictionary<string,object>();
                                tokens.Add("Namespaces",namespaceTokens);

    IHttpRoute route = routes.CreateRoute(routeTemplate,defaultsDictionary,constraintsDictionary,dataTokens: tokens,handler:null);
    routes.Add(name,route);

    return route;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读