重命名 Web API 控制器已破坏 POST 路由
Renaming a Web API controller has broken POST routing
我有一个 Web API 控制器向 Angular SPA 提供数据,我决定重命名它,使用 VS 2015 的重命名功能来更新我的所有引用。结果,我不能再 POST 了(尽管 GET 仍然有效),我在客户端上不断收到以下错误:
"A route named 'api/Trainees' could not be found in the route collection.
Parameter name: name"
此控制器之前使用默认路由时运行良好 - RouteConfig.cs
中没有任何内容,也没有属性路由,这使它变得很陌生。我假设 ASP.NET 仅从控制器和方法名称计算出默认路由,还是它在任何地方缓存路由信息?
我的控制器看起来像这样:
public class TraineesController : ApiController
{
private UserRepository repo = new UserRepository();
// GET: api/Trainees
public IEnumerable<Trainee> Get()
{
return this.repo.GetUsers();
}
// GET: api/Trainees/5
public Trainee Get(string email)
{
if (!string.IsNullOrEmpty(email))
{
return this.repo.GetUser(email);
}
throw new ArgumentNullException("email");
}
// POST: api/Trainees
public IHttpActionResult Post([FromBody]Trainee value)
{
try
{
this.repo.AddUser(value);
return CreatedAtRoute("api/Trainees", value.Email, value);
}
catch (ArgumentOutOfRangeException)
{
return Conflict();
}
}
// PUT: api/Trainees/5
public IHttpActionResult Put([FromBody]Trainee value)
{
try
{
this.repo.UpdateUser(value);
return StatusCode(HttpStatusCode.NoContent);
}
catch (ArgumentOutOfRangeException)
{
return NotFound();
}
}
// DELETE: api/Trainees/5
public IHttpActionResult Delete(string email)
{
try
{
this.repo.RemoveUser(email);
return StatusCode(HttpStatusCode.NoContent);
}
catch (ArgumentOutOfRangeException)
{
return NotFound();
}
}
}
这是失败的请求(由 Angular $resource 生成):
Request: POST /api/Trainees HTTP/1.1
Content-Type: application/json;charset=utf-8
Accept: application/json, text/plain, */*
Referer: http://localhost:11423/
Accept-Language: en-GB
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: localhost:11423
Content-Length: 64
DNT: 1
Connection: Keep-Alive
Cache-Control: no-cache
正文:
{"Email":"tony@starkindustries.com","DisplayName":"Tony Stark"}
有点晚了,但发生这种情况是因为您试图将 route template
作为 CreatedAtRoute
的第一个参数传递
return CreatedAtRoute("api/Trainees", value.Email, value);
您需要传递一个路由名称。您可以使用 RouteAttribute
命名您的路线
[Route("api/Trainees", Name="TraineesRoute")]`
我有一个 Web API 控制器向 Angular SPA 提供数据,我决定重命名它,使用 VS 2015 的重命名功能来更新我的所有引用。结果,我不能再 POST 了(尽管 GET 仍然有效),我在客户端上不断收到以下错误:
"A route named 'api/Trainees' could not be found in the route collection.
Parameter name: name"
此控制器之前使用默认路由时运行良好 - RouteConfig.cs
中没有任何内容,也没有属性路由,这使它变得很陌生。我假设 ASP.NET 仅从控制器和方法名称计算出默认路由,还是它在任何地方缓存路由信息?
我的控制器看起来像这样:
public class TraineesController : ApiController
{
private UserRepository repo = new UserRepository();
// GET: api/Trainees
public IEnumerable<Trainee> Get()
{
return this.repo.GetUsers();
}
// GET: api/Trainees/5
public Trainee Get(string email)
{
if (!string.IsNullOrEmpty(email))
{
return this.repo.GetUser(email);
}
throw new ArgumentNullException("email");
}
// POST: api/Trainees
public IHttpActionResult Post([FromBody]Trainee value)
{
try
{
this.repo.AddUser(value);
return CreatedAtRoute("api/Trainees", value.Email, value);
}
catch (ArgumentOutOfRangeException)
{
return Conflict();
}
}
// PUT: api/Trainees/5
public IHttpActionResult Put([FromBody]Trainee value)
{
try
{
this.repo.UpdateUser(value);
return StatusCode(HttpStatusCode.NoContent);
}
catch (ArgumentOutOfRangeException)
{
return NotFound();
}
}
// DELETE: api/Trainees/5
public IHttpActionResult Delete(string email)
{
try
{
this.repo.RemoveUser(email);
return StatusCode(HttpStatusCode.NoContent);
}
catch (ArgumentOutOfRangeException)
{
return NotFound();
}
}
}
这是失败的请求(由 Angular $resource 生成):
Request: POST /api/Trainees HTTP/1.1
Content-Type: application/json;charset=utf-8
Accept: application/json, text/plain, */*
Referer: http://localhost:11423/
Accept-Language: en-GB
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: localhost:11423
Content-Length: 64
DNT: 1
Connection: Keep-Alive
Cache-Control: no-cache
正文:
{"Email":"tony@starkindustries.com","DisplayName":"Tony Stark"}
有点晚了,但发生这种情况是因为您试图将 route template
作为 CreatedAtRoute
return CreatedAtRoute("api/Trainees", value.Email, value);
您需要传递一个路由名称。您可以使用 RouteAttribute
[Route("api/Trainees", Name="TraineesRoute")]`