【发布时间】:2018-07-09 13:57:27
【问题描述】:
我有一个 API 控制器,它支持用户对象的 DELETE、GET、POST 和 PUT 操作。 GET-one 操作可以通过用户 ID 检索用户帐户。但我也想通过用户名来获取用户。我为每个方法创建了单独的方法,它似乎工作正常,因为我可以通过两种方式获得预期的数据。
// GET: api/UserAccounts/5
[HttpGet]
[ResponseType(typeof(UserAccount))]
[Route("~/api/UserAccounts/{id:int}")]
public async Task<IHttpActionResult> GetUserAccount(int id) { ... }
// GET: api/UserAccounts/JohnDoe
[HttpGet]
[ResponseType(typeof(UserAccount))]
[Route("~/api/UserAccounts/{userName}")]
public async Task<IHttpActionResult> GetUserAccount(string userName) { ... }
// DELETE: api/UseAccounts/5
[HttpDelete]
[ResponseType(typeof(UserAccount))]
public async Task<IHttpActionResult> DeleteUserAccount(int id) { ... }
// GET: api/UserAccounts
[HttpGet]
public IQueryable<UserAccount> GetUserAccounts() { ... }
// POST: api/UserAccounts
[HttpPost]
[ResponseType(typeof(UserAccount))]
public async Task<IHttpActionResult> PostUserAccount(UserAccount userAccount) { ... }
// PUT: api/UserAccounts/5
[HttpPut]
[ResponseType(typeof(void))]
public async Task<IHttpActionResult> PutUserAccount(int id, UserAccount userAccount)
问题是,每当我尝试执行 DELETE、POST 或 PUT 操作时,都会收到 405 - Method Not allowed 响应。如果我注释掉 GetUser(string) 方法,它们都可以工作。
我浏览了一堆文章和文档,发现了一些关于在 Route 属性上使用 RouteOrder 属性的内容,但这并没有什么区别。
我的 WebApiConfig 有这个代码:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
由于我为我的 GetUser 方法使用属性路由,我认为这应该可以工作。我正在为其他方法/动词使用默认路由。
肯定有办法让这个工作,对吧?
更新:
我仍然遇到这个问题。我删除了 GET(字符串)操作并删除了所有属性路由,因为其他操作使用 DefaultApi 路由。所有标准操作都有效。但是,如果我引入 GET(字符串)操作,则只有 GET-all 操作有效。 GET (int) 版本没有返回响应,大概是因为 API 无法确定要使用哪个 GET 重载。所有其他操作都返回 405 Method Not Allowed。为了解决这个问题,我为 GET (int) 和 GET (string) 方法添加了一个属性路由,这些方法现在可以工作,但是 DELETE、POST 和 PUT 操作返回 405 Method Not Allowed。
如果我为所有方法添加属性路由,那么除了 POST 操作之外,一切都正常。在这种情况下,我得到 405 Method Not Allowed。以下是带有属性路由的方法签名:
[HttpDelete]
[ResponseType(typeof(UserAccount))]
[Route("~/api/UserAccounts/{id:int}")]
public async Task<IHttpActionResult> DeleteUserAccount(int id)
[HttpGet]
[ResponseType(typeof(UserAccount))]
[Route("~/api/UserAccounts/{id:int}")]
public async Task<IHttpActionResult> GetUserAccount(int id)
[HttpGet]
[ResponseType(typeof(EnrollmentApiAccountDto))]
[Route("~/api/UserAccounts/{userName}")]
public async Task<IHttpActionResult> GetUserAccount(string userName)
[HttpGet]
[Route("~/api/UserAccounts")]
public IQueryable<UserAccount> GetUserAccounts()
[HttpPost]
[ResponseType(typeof(UserAccount))]
[Route("~/api/UserAccounts")]
public async Task<IHttpActionResult> PostUserAccount(UserAccount userAccount)
[HttpPut]
[ResponseType(typeof(void))]
[Route("~/api/UserAccounts/{id:int}")]
public async Task<IHttpActionResult> PutUserAccount(int id, UserAccount userAccount)
GET(字符串)属性路由没有限制。我不能使用 {username:alpha} 因为用户名可能包含数字。
我需要支持 GET by userName 操作,因为我需要它来进行用户身份验证。但除非我能弄清楚这一点,否则我可能必须创建一个不同的控制器来支持该操作。我不喜欢。
【问题讨论】:
-
您有
[HttpGet]作为属性。您不需要 a) 其余的 http 动词属性,还是 b) 不需要动词属性(这也允许 PATCH)? -
我的方法具有所有属性。它们实际上是可选的,但我喜欢添加它们以减少歧义,
-
请发布其他方法 - POST、PUT 等。
-
其他方法的代码在上面
-
尝试将
[Route(...)]属性复制到所有其他方法。我感觉没有路由属性的操作正在使用“DefaultApi”路由。
标签: c# asp.net-web-api2