Asp.net mvc MVC WebApi中的方法如何映射到http谓词?
在下面链接的5分钟视频中,在1:10处,Jon Galloway说,按照惯例,将名为DeleteComment的方法添加到他的CommentsController类将自动映射到delete http谓词 MVC和WebApi如何知道如何将方法路由到正确的谓词?我知道global.asax.cs文件中的路由将请求路由到正确的控制器,但是删除请求如何“按约定映射”到delete方法或任何方法?特别是当每个动词可以有一个以上的方法时?“按惯例”让我觉得它只是在看方法名称中的第一个单词。。。但如果是这样,它必须读取方法的签名才能区分两个delete方法或两个get方法。。。这一切的定义是什么 视频: 谢谢 编辑: 下面是WebApi模板中的示例ValuesController类中的代码。这就是我最初问题的来源。区分这些方法(以及控制器中的任何其他方法)的“约定”是如何工作的Asp.net mvc MVC WebApi中的方法如何映射到http谓词?,asp.net-mvc,asp.net-mvc-routing,asp.net-web-api,Asp.net Mvc,Asp.net Mvc Routing,Asp.net Web Api,在下面链接的5分钟视频中,在1:10处,Jon Galloway说,按照惯例,将名为DeleteComment的方法添加到他的CommentsController类将自动映射到delete http谓词 MVC和WebApi如何知道如何将方法路由到正确的谓词?我知道global.asax.cs文件中的路由将请求路由到正确的控制器,但是删除请求如何“按约定映射”到delete方法或任何方法?特别是当每个动词可以有一个以上的方法时?“按惯例”让我觉得它只是在看方法名称中的第一个单词。。。但如果是这样
//GET/api/values
公共IEnumerable Get()
{
返回新字符串[]{“value1”,“value2”};
}
//获取/api/values/5
公共字符串Get(int-id)
{
返回值;
}
这种情况经常出现。对此有不同的看法。我个人目前还没有订阅任何特定的想法,但似乎每个资源有一个控制器的想法在REST社区中最受欢迎
所以基本上你可以:
action
视为类似于MVC),但通常不打算使用它我提前道歉,这篇文章有点偏离了你的要求,但当我读到你的问题时,所有这些都冒了出来 WebAPI匹配语义
WebAPI(中的默认路由)使用的匹配语义相当简单
GET*()
函数匹配。包含and ID的Get查找Get***(int ID)
示例虽然匹配的语义很简单,但它会给MVC开发人员(至少这个开发人员)带来一些混乱。让我们看一些例子: 奇数名称-get方法可以命名为任何名称,只要它以“get”开头。因此,对于小部件控制器,您可以将函数命名为
get草莓()
,它仍然是匹配的。可以将匹配想象为:methodname.StartsWith(“Get”)
多个匹配方法-如果有两个没有参数的Get方法,会发生什么get草莓()
和GetOrange()
。据我所知,代码中首先定义的函数(文件顶部)获胜……奇怪。这样做的副作用是使控制器中的某些方法无法访问(至少在默认路由下)…陌生人
注意:测试版的表现与上述“匹配多种方法”相同——RC&Release版本更具强迫性。如果存在多个可能的匹配项,则会抛出错误。此更改消除了多个不明确匹配的混淆。同时,它降低了我们在同一控制器中混合REST和RPC风格接口的能力,这依赖于顺序和重叠路由
怎么办?好吧,WebAPI是新的,共识仍在凝聚。社区似乎在很大程度上达到了休息的原则。然而,并不是每个API都可以或者应该是RESTful的,有些API更自然地以RPC样式表示。休息&人们称之为休息的东西似乎是 作为一个实用主义者,我怀疑许多API将是70%RESTful的,带有少量RPC风格的方法。首先,仅控制器的扩散(给定webapi绑定方法)就会让开发人员发疯。其次,WebAPI实际上没有一种内置的方法来创建api路径的嵌套结构(这意味着:
/api/controller/
很容易,但是/api/CATEGORY/Sub-CATEGORY/controller
是可行的,但是很痛苦)
从我的角度来看,我希望看到webAPI文件夹结构控制默认的API路径。。。这意味着如果我在UI项目中创建一个Category文件夹,那么默认路径将是/api/Category
我做了什么?因此,我有一些要求:(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个。注意这些路由如何添加
数据标记,以限制为特定路由搜索哪些类。这与向UI项目添加文件夹时的典型名称空间设置很好地对应名称空间
- 第三条路径允许调用特定的方法名(如传统的mvc)。由于WebAPI去掉了URL中的操作名称,因此相对容易判断哪些调用需要此路由李>
- l
// 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 } );
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; }
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; }