我已经在这里看过几次问这个问题了,但是没有一个答案似乎适用于我的情况。
我的web api控制器上有三个GET方法,我也想在这里添加POST / PUT / DELETE方法。
请在此处查看控制器代码:
public PagedResult<ApiStudentNote> Get([FromUri] StudentNoteApiCriteria criteria)
public ApiStudentNote Get(long id)
[HttpGet]
[ActionName("Download")]
public HttpResponseMessage Download(long id)
我正在尝试配置路由,但仍然会收到标题中提到的错误:
context.Routes.MapHttpRoute(
name: "V2/DownloadStudentNotes",
routeTemplate: areaName + "/V2/student-notes/{id}/Download",
defaults: new { controller = "StudentNotes", action = "Download" },
constraints: new { id = @"\d+" });
context.Routes.MapHttpRoute(
name: "V2/StudentNotesApi",
routeTemplate: areaName + "/V2/student-notes/{id}",
defaults: new { controller = "StudentNotes", id = RouteParameter.Optional });
答案 0 :(得分:1)
如果您使用的是ASP.NET Web API 2+,则可以使用“属性路由”来解决此问题。它将为您提供更大的灵活性。
Attribute Routing in ASP.NET Web API 2
为什么要进行属性路由?
Web API的第一个版本使用基于约定的路由。在那里面 路由类型,您定义一个或多个路由模板,它们是 基本上参数化字符串。当框架收到一个 请求,它匹配路由模板的URI。
基于约定的路由的一个优点是模板 在一个地方定义,并应用路由规则 贯穿所有控制器。不幸的是,基于会议 路由使得很难支持常见的某些URI模式 在RESTful API中。例如,资源通常包含子资源: 客户有订单,电影有演员,书有作者等等 向前。创建反映这些关系的URI是很自然的:
/客户/ 1 /订单
这种类型的URI很难使用基于约定的方法创建 路由。虽然可以做到,但如果你这样做,结果就不能很好地扩展 有许多控制器或资源类型。
使用属性路由,为此URI定义路由非常简单。 您只需向控制器操作添加一个属性:
配置路由
public static class WebApiConfig {
public static void Register(HttpConfiguration config) {
// Web API routes
config.MapHttpAttributeRoutes();
// Other Web API configuration not shown.
}
}
控制器代码:
[RoutePrefix("api/v2/student-notes")]
public class StudentNotesController : ApiController {
// GET api/v2/student-notes
[HttpGet]
[Route("")]
public PagedResult<ApiStudentNote> GetNotes([FromUri] StudentNoteApiCriteria criteria) {...}
// GET api/v2/student-notes/1234567
[HttpGet]
[Route("{id:long}")]
public ApiStudentNote GetNote(long id) {...}
// GET api/v2/student-notes/1234567/Download
[HttpGet]
[Route("{id:long}/Download")]
public HttpResponseMessage Download(long id) {...}
}
因为在模板
中添加了Route ConstraintsAPI / V2 /学生笔记/ {ID}
以下URI与此模板匹配:
api/v2/student-notes/1234
其中id =&gt; 1234 api/v2/student-notes/1234/Download
其中id =&gt; 1234 /下载这将反映您最初与基于会议的路线的多个匹配。
答案 1 :(得分:0)
我认为您使用的是Web API 2或更高版本。如果是这样,您在WebApiConfig
中不需要任何基于约定的路由。您只需启用属性路由并装饰您的方法:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config) {
config.MapHttpAttributeRoutes();
// No route config needed beyond this point.
}
}
[RoutePrefix("api/v2/student-notes")]
public class StudentNotesController : ApiController
{
public PagedResult<ApiStudentNote> GetNotes(
[FromUri] StudentNoteApiCriteria criteria)
{
//...
}
[Route("{id}", Name="GetNote")]
public ApiStudentNote GetNote(long id)
{
//...
}
[Route("{id}/Download")]
public HttpResponseMessage Download(long id)
{
//...
}
// in future scenarios this will work as well
public ApiStudentNote PostNote(ApiStudentNote studentNote)
{
// persist new student note
return CreatedAt("GetNote", new {id = studentNote.Id }, studentNote);
}
[Route("{id}")]
public ApiStudentNote PutNote(ApiStudentNote studentNote)
{
// retrieve
// update
// persist
return Ok();
}
}
正如您所看到的,我没有用HttpGet
等来装饰方法,因为路由服务可以从方法名称推断出HTTP方法(GetNote
推断GET
,{{ 1}}推断PostNote
)。为清楚起见,您可以添加属性。
关于POST
方法的命名路线。我补充说,为了向您展示您在未来场景中如何实现GetNote
以及如何在POST
标题中返回新创建的注释的位置。如果您提供路线名称,Location
可以为您做到这一点。