.NET WebAPI属性路由和继承

时间:2013-11-14 21:43:41

标签: asp.net-mvc asp.net-web-api asp.net-mvc-routing

我正在尝试使用基本控制器,该控制器使用通用存储库为我的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

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

有没有人知道如何让路由使用来自基本控制器的属性?

3 个答案:

答案 0 :(得分:77)

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

你能否提供一个更真实的场景来确定你想要使用它的位置?

[<强>更新(2014年3月24日)]
在即将发布的MVC Web API的5.2版本中,将会有一个名为System.Web.Http.Routing.IDirectRouteProvider的可扩展点,您可以通过它在此处启用您要查找的继承方案。你可以自己尝试使用最新的夜间版本(关于如何使用夜间版本的文档是here

[<强>更新(2014年7月31日)]
如何在Web API 2.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);
    }
}

答案 1 :(得分:24)

使用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

答案 2 :(得分: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重命名路线)