我在我的项目中使用Web API 2属性路由来为我的数据提供JSON接口。我面临着控制器选择的怪异行为,并未决定它是一个错误还是一个功能:) 让我来描述一下我的方法。Web API 2属性路由控制器选择
我想借助属性路由来模拟OData语法(由于设计原则,直接OData使用已被拒绝)。例如,要获取id = 5的实体,我使用HTTP GET请求来访问URI http://mydomain.com/api/Entity(5)。我期望与HTTP PUT动词使用相同的URI来更新实体。这是旅程的开始...
我想单独控制器获取实体(FirstController
在下面提供的示例中提供)和另一个用于修改实体(SecondController
)。两个控制器处理相同的URI(例如http://mydomain.com/api/Entity(5)),唯一的区别是与URI一起使用的HTTP动词 - GET应该由FirstController
处理,PUT应该由SecondController
处理。但是URI并没有被处理。而不是HTTP 404错误返回。 当我将GET和PUT操作“合并”到一个控制器(在FirstController
中注释掉)时,两个动词都被正确处理。 我使用的是IIS Express,并且所有常规路由都被禁用,只有属性路由负责。
它看起来像控制器选择过程不适用于HTTP动词。换句话说,HttpGet
和HttpPut
属性只是限制操作使用,但它们不作为控制器选择期间的标准。我对MVC/Web API基础知识并不熟悉,所以让我问你我的一个大问题:
以上描述的行为是MVC/Web API 2有意实现的功能还是需要修复的错误?
如果它被认为是一个功能,它会阻止我遵循设计原则。我可以和“合并”的控制者一起生活,但仍然认为这是一种不好的做法...... 或者我错过了我的思路?
我的环境设置:
- 的Windows 7(使用Oracle的VirtualBox虚拟机)
- 的Visual Studio 2013
- .NET 4.5。1
- 的Web API 2
以下是实现FirstController
类:
public class FirstController : ApiController
{
[HttpGet]
[Route("api/Entity({id:int})")]
public Output GetEntity(int id)
{
Output output = new Output() { Id = id, Name = "foo" };
return output;
}
//[HttpPut]
//[Route("api/Entity({id:int})")]
//public Output UpdateEntity(int id, UpdateEntity command)
//{
// Output output = new Output() { Id = id, Name = command.Name };
// return output;
//}
}
以下是实现SecondController
类:
public class SecondController : ApiController
{
[HttpPut]
[Route("api/Entity({id:int})")]
public Output UpdateEntity(int id, UpdateEntity command)
{
Output output = new Output() { Id = id, Name = command.Name };
return output;
}
}
以下是实现一个控制台应用程序来测试所描述的行为:
class Program
{
static void Main(string[] args)
{
// HTTP client initialization
HttpClient httpClient = new HttpClient();
httpClient.BaseAddress = new Uri("http://localhost:1567");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// HTTP GET - FirstController.GetEntity
HttpResponseMessage getEntityResponse = httpClient.GetAsync("/api/Entity(5)").Result;
Output getOutput = getEntityResponse.Content.ReadAsAsync<Output>().Result;
// HTTP PUT - SecondController.UpdateEntity
UpdateEntity updateCommand = new UpdateEntity() { Name = "newEntityname" };
HttpResponseMessage updateEntityResponse = httpClient.PutAsJsonAsync("/api/Entity(10)", updateCommand).Result;
Output updateOutput = updateEntityResponse.Content.ReadAsAsync<Output>().Result;
}
}
完成,以下是使用的DTO:提前为您的答复
public class UpdateEntity
{
public string Name { get; set; }
}
public class Output
{
public int Id { get; set; }
public string Name { get; set; }
}
感谢,
月Kacina
对于“Google搜索”完成,这里是您在这种情况下的错误: “找到了与URL匹配的多个控制器类型,如果多个控制器上的属性路由匹配请求的URL,就会发生这种情况。 –
我已经看到了最好的问题之一,很好地完成:) – Scozzard