基于Web Api v2属性执行显式路由映射

时间:2013-10-22 09:35:56

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

我正在升级自定义解决方案,我可以动态注册和取消注册Web Api控制器以使用新的属性路由机制。但是,最近RTM的更新似乎打破了我的解决方案。

我的解决方案公开了一些用于管理目的的Web Api控制器。这些是使用新的HttpConfigurationExtensions.MapHttpAttributeRoutes方法调用注册的。

该解决方案还允许Web Api控制器托管在第三方程序集中并动态注册。在此阶段,一旦加载第三方控制器,第二次调用HttpConfigurationExtensions.MapHttAttributeRoutes将引发异常。因此,我的解决方案使用反射来检查RoutePrefix和Route属性,并在HttpConfiguration对象上注册相应的路由。

不幸的是,调用Web Api会导致以下错误:

“找不到与请求URI匹配的HTTP资源”。

这是一个我想要使用的简单控制器:

[RoutePrefix("api/ze")]
public sealed class ZeController : ApiController
{
    [HttpGet]
    [Route("one")]
    public string GetOne()
    {
        return "One";
    }

    [HttpGet]
    [Route("two")]
    public string GetTwo()
    {
        return "Two";
    }

    [HttpPost]
    [Route("one")]
    public string SetOne(string value)
    {
        return String.Empty;
    }
}

这是我尝试过的第一个解决方案:

configuration.Routes.MapHttpRoute("ZeApi", "api/ze/{action}");

这是我尝试的第二个解决方案:

var type = typeof(ZeController);
var routeMembers = type.GetMethods().Where(m => m.IsPublic);
foreach (MethodInfo method in routeMembers)
{
        var routeAttribute = method.GetCustomAttributes(false).OfType<RouteAttribute>().FirstOrDefault();
       if (routeAttribute != null)
        {
           string controllerName = type.Name.Substring(0, type.Name.LastIndexOf("Controller"));
           string routeTemplate = string.Join("/", "api/Ze", routeAttribute.Template);
           configuration.Routes.MapHttpRoute(method.Name, routeTemplate);
       }
}

我还尝试了第三种解决方案,即创建实现IHttpRoute的自定义类,并尝试使用配置注册它们无效。

是否可以根据新路由属性中包含的信息使用传统样式的路由映射?

更新

我已将我的控制器安装在Web应用程序中,以便使用Web Api Route Debugger对路由选择过程进行故障排除。以下是截图的结果:

Web Api Route Selection in the Route Debugger

如您所见,似乎选择了正确的操作,但我仍然收到404错误。

UPDATE2

经过进一步分析,根据Kiran Challa在下面的评论,似乎Web Api的设计阻止了混合属性路由和传统路由,并且使用这种方法我不想做的事情。

我创建了一个自定义属性[RouteEx],其功能与Web Api [Route]属性相同,现在我的代码运行完美。

我想,因为使用传统的属性路由是不可能的,所以这个问题的答案都不能合法地被认为是有效的。所以我还没有提名答案。

1 个答案:

答案 0 :(得分:0)

不应要求您使用反射并自行检查基于属性路由的属性。属性路由使用现有的Web API功能来获取要扫描的控制器列表。

问题:在切换到属性路由之前,如何加载具有该属性的这些程序集 控制器?

如果您是通过IAssembliesResolver服务执行此操作,那么此解决方案即使使用属性路由也应该有效,您不需要做任何额外的事情。

关于更新:您是否正在呼叫MapHttpAttributeRoutes