【问题标题】:How to map different HTTP methods on the same url to different controllers?如何将同一 url 上的不同 HTTP 方法映射到不同的控制器?
【发布时间】:2015-02-04 10:34:37
【问题描述】:

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

现在,我有一个 url,我想用 PascalCasing 映射 GET,但用 camelCasing 映射 PUT,所以我尝试了以下方法:

[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 个控制器需要与另一个不同的依赖项,现在所有依赖项都注入到 1 个控制器中:-(
  • 有没有人知道最后是否有办法解决这个问题?我即将合并控制器,但我想我至少会提出这个问题以防万一......

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


【解决方案1】:

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

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

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

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

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

【讨论】:

  • 谢谢!我还没有尝试过(因为这个问题已经有几年了,我只是求助于使用部分课程并继续前进......)但似乎这种方法会奏效,所以我会给你代表无论如何:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-31
  • 2016-07-04
  • 1970-01-01
  • 2011-09-20
  • 1970-01-01
  • 1970-01-01
  • 2011-04-23
相关资源
最近更新 更多