Asp.net web api Web Api路由噩梦。Can';不能使它适用于所有控制器
我有一个MVC Web Api RESTful服务。我没有使用API版本2 我用默认的GET/POST/PUT/DELETE创建了一个控制器。一切都很好,直到我决定添加一些更多的功能到我的控制器 长话短说,我最终为我的控制器提供了近十几个路由模板(非常讨厌的WebApiConfig文件)。在……之前它一直运转良好。。。。我需要第二个控制器。然后混乱开始了 DocumentController的所有路由显然不适用于CompanyController,因为我之前配置的只是一堆蹩脚的补丁,使我的第一个控制器工作。四天后我到了这里,但仍然无法让它工作。我真的无法理解这整件事。(在我看来)如此复杂和僵硬 这里有一些代码供您理解Asp.net web api Web Api路由噩梦。Can';不能使它适用于所有控制器,asp.net-web-api,asp.net-mvc-routing,Asp.net Web Api,Asp.net Mvc Routing,我有一个MVC Web Api RESTful服务。我没有使用API版本2 我用默认的GET/POST/PUT/DELETE创建了一个控制器。一切都很好,直到我决定添加一些更多的功能到我的控制器 长话短说,我最终为我的控制器提供了近十几个路由模板(非常讨厌的WebApiConfig文件)。在……之前它一直运转良好。。。。我需要第二个控制器。然后混乱开始了 DocumentController的所有路由显然不适用于CompanyController,因为我之前配置的只是一堆蹩脚的补丁,使我的第一个
public class DocumentController : ApiController
{
public HttpResponseMessage Get()
{
return Request.CreateResponse(HttpStatusCode.OK,"This is GET");
}
[HttpGet]
public HttpResponseMessage Metadata()
{
return Request.CreateResponse(HttpStatusCode.OK,"This is Metadata");
}
public HttpResponseMessage Get(int id)
{
return Request.CreateResponse(HttpStatusCode.OK, "This is GET with ID");
}
public HttpResponseMessage Post([FromBody] DocumentDTO document)
{
return Request.CreateResponse(HttpStatusCode.OK, "This is Post");
}
public HttpResponseMessage Put(int id, [FromBody] DocumentDTO document)
{
return Request.CreateResponse(HttpStatusCode.OK, "This is PUT");
}
[HttpGet]
public HttpResponseMessage Tags(int id)
{
return Request.CreateResponse(HttpStatusCode.OK, "This is GET TAGS");
}
[HttpPost]
public HttpResponseMessage Tags(int id, [FromBody] IEnumerable<TagDefinitionDTO> tagDefinitions)
{
return Request.CreateResponse(HttpStatusCode.OK, "This is POST TAGS");
}
}
公共类文档控制器:ApiController
{
公共HttpResponseMessage Get()
{
return Request.CreateResponse(HttpStatusCode.OK,“这是GET”);
}
[HttpGet]
公共HttpResponseMessage元数据()
{
return Request.CreateResponse(HttpStatusCode.OK,“这是元数据”);
}
公共HttpResponseMessage获取(int id)
{
return Request.CreateResponse(HttpStatusCode.OK,“这是带有ID的GET”);
}
公共httpresponsemessagepost([FromBody]DocumentDTO document)
{
return Request.CreateResponse(HttpStatusCode.OK,“这是Post”);
}
公共httpresponsemessageput(int-id,[FromBody]documentd到document)
{
return Request.CreateResponse(HttpStatusCode.OK,“这是PUT”);
}
[HttpGet]
公共HttpResponseMessage标记(int id)
{
return Request.CreateResponse(HttpStatusCode.OK,“这是GET标签”);
}
[HttpPost]
公共HttpResponseMessage标记(int-id,[FromBody]IEnumerable标记定义)
{
return Request.CreateResponse(HttpStatusCode.OK,“这是POST标签”);
}
}
因此,我最初的梦想是实现以下目标
获取所有文档
获取/document/3
=>文档Id=3
发布/document/
=>创建文档
放置/document/3
=>编辑文档
GET/document/metadata
=>返回所有文档的常规配置
获取/document/6/tags
=>获取文档ID=6的所有标记
POST/document/6/tags
=>为文档ID=6创建标记
我甚至不发布WebApi,因为这很尴尬。正如我所说,我能够使用额外的方法使其工作,但它几乎是到我的控制器/操作的一对一映射。可怕的。。。我知道
当我添加第二个控制器时。。。。明显地任务不可能完成
现在,我不想让你认为我没有做过一些研究(我使用了约束、默认值等,但没有用……可怜)。一旦我让一个控制器工作,另一个就会中断
我会犯各种各样的错误。从“获取的多个方法”到“未找到资源”,“现在允许发布的方法”
五天后,我就在这里转了一圈。这是非常令人沮丧的
问题
有人面对过这些问题吗?路由协议是否限制了每个控件只能执行这4个操作?我是否应该为控制器中的每个操作创建一个路由模板,这意味着如果我有10个控制器和10个操作,我应该添加100个路由模板?是的,您可以切换到使用属性路由 然后,在每个操作或控制器上,您可以只放置路由模板 或者下面的路线应该适合你
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi1",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional },
constraints: new { id = @"\d+" }
);
config.Routes.MapHttpRoute(
name: "DefaultApi2",
routeTemplate: "api/{controller}/{id}/{action}",
defaults: null,
constraints: new { id = @"\d+" }
);
config.Routes.MapHttpRoute(
name: "DefaultApi3",
routeTemplate: "api/{controller}/{action}",
defaults: new {id = RouteParameter.Optional}
);
基于Yishai的回答,我认为将您的路线更改为以下路线应该适用于您的场景:
config.Routes.MapHttpRoute(
name: "DefaultApi1",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional, action = "Default" },
constraints: new { id = @"\d*" }
);
config.Routes.MapHttpRoute(
name: "DefaultApi2",
routeTemplate: "api/{controller}/{action}",
defaults: null,
constraints: new { action = @"[a-zA-Z]+" }
);
config.Routes.MapHttpRoute(
name: "DefaultApi3",
routeTemplate: "api/{controller}/{id}/{action}",
defaults: null,
constraints: new { id = @"\d+", action = @"[a-zA-Z]+" }
);
然后在默认操作上放置ActionName属性
public class DocumentController : ApiController
{
[ActionName("Default")]
[HttpGet]
public HttpResponseMessage Get()
{
return Request.CreateResponse(HttpStatusCode.OK,"This is GET");
}
[HttpGet]
public HttpResponseMessage Metadata()
{
return Request.CreateResponse(HttpStatusCode.OK,"This is Metadata");
}
[ActionName("Default")]
[HttpGet]
public HttpResponseMessage Get(int id)
{
return Request.CreateResponse(HttpStatusCode.OK, "This is GET with ID");
}
[ActionName("Default")]
[HttpPost]
public HttpResponseMessage Post([FromBody] DocumentDTO document)
{
return Request.CreateResponse(HttpStatusCode.OK, "This is Post");
}
[ActionName("Default")]
[HttpPut]
public HttpResponseMessage Put(int id, [FromBody] DocumentDTO document)
{
return Request.CreateResponse(HttpStatusCode.OK, "This is PUT");
}
[HttpGet]
public HttpResponseMessage Tags(int id)
{
return Request.CreateResponse(HttpStatusCode.OK, "This is GET TAGS");
}
[HttpPost]
public HttpResponseMessage Tags(int id, [FromBody] IEnumerable<TagDefinitionDTO> tagDefinitions)
{
return Request.CreateResponse(HttpStatusCode.OK, "This is POST TAGS");
}
}
公共类文档控制器:ApiController
{
[ActionName(“默认”)]
[HttpGet]
公共HttpResponseMessage Get()
{
return Request.CreateResponse(HttpStatusCode.OK,“这是GET”);
}
[HttpGet]
公共HttpResponseMessage元数据()
{
return Request.CreateResponse(HttpStatusCode.OK,“这是元数据”);
}
[ActionName(“默认”)]
[HttpGet]
公共HttpResponseMessage获取(int id)
{
return Request.CreateResponse(HttpStatusCode.OK,“这是带有ID的GET”);
}
[ActionName(“默认”)]
[HttpPost]
公共httpresponsemessagepost([FromBody]DocumentDTO document)
{
return Request.CreateResponse(HttpStatusCode.OK,“这是Post”);
}
[ActionName(“默认”)]
[HttpPut]
公共httpresponsemessageput(int-id,[FromBody]documentd到document)
{
return Request.CreateResponse(HttpStatusCode.OK,“这是PUT”);
}
[HttpGet]
公共HttpResponseMessage标记(int id)
{
return Request.CreateResponse(HttpStatusCode.OK,“这是GET标签”);
}
[HttpPost]
公共HttpResponseMessage标记(int-id,[FromBody]IEnumerable标记定义)
{
return Request.CreateResponse(HttpStatusCode.OK,“这是POST标签”);
}
}
如前所述,WebAPI2是一种更好的方式。我不能使用属性路由。我使用的是API v.1,而不是v.2。我要试试你的建议,我会让你知道的!当然-还有Tim McCall的Web API V1属性路由库安装包AttributeRouting.WebApi“找到多个与请求匹配的操作:System.Net.Http.HttpResponseMessage Get()”我在配置中遇到此错误。让我看看这个包。我的错是,这应该只适用于属性路由。如果可以的话,我会认真考虑升级到Web API 2。唯一的限制是您必须在.NET 4.5上运行您的解决方案对我有效。因此,到目前为止,我学到的是,您的action=“Default”基本上将调用“路由”到这4个方法(sin)