网页API 2属性路由控制器选择(Web API 2 Attribute Routing Contr

2019-11-02 19:42发布

我使用的Web API 2属性的路由在我的项目在我的数据提供了JSON接口。 我对着控制器的选择,没有决定它是否是一个错误或功能的怪异的行为:)让我描述我的做法。

我想模拟与属性路由的帮助的OData语法(OData的直接使用已被拒绝,由于设计原理)。 例如,为了获得与实体ID = 5我使用HTTP GET请求URI http://mydomain.com/api/Entity(5) 。 我希望使用相同的URI与HTTP PUT动词更新实体。 这是旅程开始的地方......

我想有用于获取实体(单独的控制器FirstController在下面提供的实施例),另一种用于修改实体( SecondController )。 两个控制器处理相同的URI(例如http://mydomain.com/api/Entity(5) )的唯一差别是与用于URI HTTP动词-获取应该由处理FirstController ,PUT应由处理SecondController 。 但URI是他们没有处理; 代替返回HTTP 404错误。 当我“合并” GET和PUT行动只有一个控制器(在注释掉FirstController ),这两个动词正确处理。 我使用IIS Express和所有常规路线是残疾人,只有属性路由负责。

它看起来像控制器选择过程中不使用HTTP动词工作。 换句话说, HttpGetHttpPut属性只是限制行动使用,但他们不作为控制器的选择过程中的标准。 我不是很熟悉的MVC /网络API的基本面,所以让我问你我的大问题:

在本文中之前描述的行为,故意MVC /网页API 2或错误实现的功能是固定的?

如果它被认为是一种功能,它可以防止我遵循的设计原则。 我可以“合并”控制器生活,但仍然将其视为一种不好的做法......还是我失去了我的思路的东西吗?

我的环境设置:

  • 视窗7(使用Oracle VirtualBox的虚拟机)的
  • 的Visual Studio 2013
  • .NET 4.5.1
  • 网页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; }
}

在此先感谢您的答复,

扬Kacin

Answer 1:

这个设计是故意的,因为我们认为这是一个错误的情况下,用户将是具有不同的控制器,可以在选择过程中产生歧义原路模板。

此外,如果我们留着备用路由的属性,怎么会与常规路由这项工作? 让我们想象一下,我们有2条航线,其中第一个是针对FirstController第二要SecondController。 现在,如果请求的URL是一样api/Entity(5)则Web API总是匹配的路由表,它会一直打到FirstController并不会到达SecondController一号路线。 请记住,一旦网络API的路由匹配它试图去,直到动作选择过程,如果动作选择过程中不动作结果被选中,那么错误响应发送到客户端。 你可能是假设,如果在一个控制器没有选择则Web API的行动将其路由到路由配置中的下一个。 这是不正确。

路由探测只发生一次,如果它导致了匹配,那么接下来的步骤发生......这是控制器和操作选择。 希望这可以帮助。



文章来源: Web API 2 Attribute Routing Controller Selection