66

我正在考虑拥有一个使用通用存储库的基本控制器来为我的 API 控制器提供基本 CRUD 方法的想法,这样我就不必在每个新控制器中复制相同的基本代码。但是当路由属性在基本控制器中时,我遇到了识别路由属性的问题。为了准确显示我遇到的问题,我创建了一个非常简单的 WebAPI 控制器。

当我Get在主控制器中有一个方法并且它ApiController直接继承自控制器时,我没有任何问题,并且可以按预期工作。

[RoutePrefix("admin/test")]
public class TestController : ApiController
{
    [Route("{id:int:min(1)}")]
    public string Get(int id)
    {
        return "Success";
    }
}

当我将该Get方法移动到基本控制器中时,它会返回 404 页面的内容。

[RoutePrefix("admin/test")]
public class TestController : TestBaseController
{

}

public class TestBaseController : ApiController
{
    [Route("{id:int:min(1)}")]
    public string Get(int id)
    {
        return "Success";
    }
}

一些更有趣的注释:

  • 我可以在 访问操作GET /Test/1。所以它仍然根据默认路由找到它。

  • 当我尝试访问POST /admin/test时,它返回以下 JSON

    { "Message":"未找到与请求 URI ' http://test.com/admin/test '匹配的 HTTP 资源。", "MessageDetail":"未找到与名为 'admin' 的控制器匹配的类型。 " }

有谁知道让路由与基本控制器的属性一起使用的方法?

4

3 回答 3

82

属性路由不能被继承。这是一个深思熟虑的设计决定。我们感觉不对,也没有看到继承它们有意义的有效场景。

你能给出一个更现实的场景来说明你想在哪里使用它吗?

[更新(2014 年 3 月 24 日)]
在即将发布的 5.2 版 MVC Web API 中,将有一个称为扩展点System.Web.Http.Routing.IDirectRouteProvider,您可以通过它启用您在此处寻找的继承方案。您可以使用最新的夜间构建自己尝试此操作(有关如何使用夜间构建的文档在此处

[更新(2014 年 7 月 31 日)]
如何在 Web API2.2版本中完成此操作的示例:

config.MapHttpAttributeRoutes(new CustomDirectRouteProvider());

//---------

public class CustomDirectRouteProvider : DefaultDirectRouteProvider
{
    protected override IReadOnlyList<IDirectRouteFactory> 
    GetActionRouteFactories(HttpActionDescriptor actionDescriptor)
    {
        // inherit route attributes decorated on base class controller's actions
        return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>
        (inherit: true);
    }
}
于 2013-11-14T22:03:11.833 回答
28

使用 Web API 2.2,您可以:

public class BaseController : ApiController
{
    [Route("{id:int}")]
    public string Get(int id)
    {
        return "Success:" + id;
    }
}
[RoutePrefix("api/values")]
public class ValuesController : BaseController
{
}

config.MapHttpAttributeRoutes(new CustomDirectRouteProvider());
public class CustomDirectRouteProvider : DefaultDirectRouteProvider
{
    protected override IReadOnlyList<IDirectRouteFactory> 
    GetActionRouteFactories(HttpActionDescriptor actionDescriptor)
    {
        return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>
        (inherit: true);
    }
}

如此处所述:http ://www.asp.net/web-api/overview/releases/whats-new-in-aspnet-web-api-22

于 2014-07-26T10:00:48.683 回答
3

知道了。

[Route("api/baseuploader/{action}")]
public abstract class BaseUploaderController : ApiController
{
    [HttpGet] 
    public string UploadFile() 
    {
        return "UploadFile";
    }
}


[Route("api/values/{action}")]
public class ValuesController : BaseUploaderController
{
    [HttpGet]
    public string Get(int id)
    {
        return "value";
    }
}

这里需要注意的是,路由操作参数必须与操作名称相同。我找不到解决这个问题的方法。(您不能使用 RouteAttribute 重命名路由)

于 2013-12-03T22:20:40.673 回答