如何将同一网址上的不同HTTP方法映射到不同的控制器?

时间:2015-02-04 10:34:37

标签: asp.net-web-api attributerouting http-method

由于API中JSON数据大小的(外部)要求,我的应用程序的一小部分分配了两个控制器,我的API(一些请求应该使用camelCasing,而其他请求应该使用PascalCasing)。

现在,我有一个我想用GET的PascalCasing映射的网址,但是PUT的camelCasing,所以我尝试了以下内容:

[PascalCasing] // custom attribute, part of our code
               // We configure all controllers that *don't* have this to use
               // camelCasing
public class PascalCasedController : ApiController
{
    [HttpGet]
    [Route("url/to/my/resource/{id}")]
    public IHttpActionResult(int id)
    {
        return Ok(GetResource(id));
    }
}

public class CamelCasedController : ApiController
{
    [HttpPut]
    [Route("url/to/my/resource/{id}")]
    public IHttpActionResult(int id, Resource resource)
    {
        SaveResource(id, resource);
        return Ok();
    }
}

GET请求按预期工作,但如果我尝试使用Fiddler PUT,我会收到以下错误消息:

  

找到了与URL匹配的多种控制器类型。如果多个控制器上的属性路由与请求的URL匹配,则会发生这种情况   该请求已找到以下匹配的控制器类型:
   MyProject.PascalCaseController
   MyProject.CamelCaseController

我意识到这可能是因为WebAPI首先将路由映射到控制器并接下来执行操作,但是如果考虑HTTP方法,那么这里确实没有任何歧义。有什么方法可以告诉WebAPI如何做到这一点,而不必在同一个控制器中有方法?

1 个答案:

答案 0 :(得分:0)

@Tomas - 这是一个界面" System.Web.Http.Dispatcher.IHttpControllerSelector"在System.Web.Http程序集中公开。您可以使用该接口并创建自己的HttpControllerSelector。然后,您可以在AreaRegistration期间使用HttpConfiguration中的自定义控制器选择器替换DefaultControllerSelector。

httpConfig.Services.Replace(typeof(IHttpControllerSelector),new CustomControllerSelector(services.GetHttpControllerSelector()));

在这个自定义控制器选择器中,您可以编写自己的IHttpControllerSelector的SelectController()方法实现,您可以在其中调用IHttpControllerSelector的GetControllerMapping()方法。这将为您提供已注册的所有控制器的列表。对于每个控制器,您可以检查DeclaredMethods并检查每个DeclaredMethods的CustomAttributes。在您的情况下,它将是HttpGetAttribute或HttpPutAttribute。

检查传入的HttpRequestMessage(GET / PUT)的Method类型,并将其与CustomAttributes的值进行比较。如果您找到传入请求URL和相应Http Verb组合的匹配项,那么您将获取该HttpControllerDiscriptor并从SelectController()方法返回它。

这将允许您在两个不同的控制器中使用不同方法的相同URL。