rkd*_*rkd 15 c# asp.net asp.net-web-api asp.net-web-api-routing asp.net-web-api2
我正在尝试添加API版本,我的计划是为不同命名空间中的每个版本创建一个控制器.我的项目结构如下所示(注意:每个版本没有单独的区域)
Controllers
|
|---Version0
| |
| |----- ProjectController.cs
| |----- HomeController.cs
|
|---Version1
|
|----- ProjectController.cs
|----- HomeController.cs
Run Code Online (Sandbox Code Playgroud)
我正在使用RoutingAttribute作为路由.因此,Version0中的ProjectController具有路由功能
namespace MyProject.Controllers.Version0
{
class ProjectController : BaseController
{
...
[Route(api/users/project/getProjects/{projectId})]
public async GetProjects(string projectId)
{
...
}
}
}
Run Code Online (Sandbox Code Playgroud)
和Version1中的ProjectController具有路由功能
namespace MyProject.Controllers.Version1
{
class ProjectController : BaseController
{
...
[Route(api/v1/users/project/getProjects/{projectId})]
public async GetProjects(string projectId)
{
...
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试使用该服务时,我得到404-NotFound.
如果我将控制器重命名为具有唯一名称(Project1Controller和Project2Controller),则路由可以正常工作.但是,我试图避免重命名以简化.
我按照此链接解决了问题,但没有帮助.我确实创造了一些领域但仍然没有成功.在global.aspx文件中添加路由逻辑没有帮助.命名空间也不起作用. http://haacked.com/archive/2010/01/12/ambiguous-controller-names.aspx/
上面的链接建议创建区域,但属性路由不支持按链接区域:http: //www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-在-Web的API-2
还有其他解决方案吗?RoutingAttributes有错误吗?
谢谢!
Jot*_*aBe 21
首先,Web API路由和MVC路由不能以完全相同的方式工作.
您的第一个链接指向带有区域的MVC路由.虽然您可以尝试制作与它们类似的内容,但Web API并未正式支持这些区域.但是,即使您尝试执行类似的操作,也会得到相同的错误,因为Web API寻找控制器的方式并没有考虑控制器的命名空间.
因此,开箱即用,它永远不会奏效.
但是,您可以修改大多数Web API行为,这不是一个例外.
Web API使用控制器选择器来获取所需的控制器.上面解释的行为是DefaultHttpControllerSelector的行为,它随Web API一起提供,但您可以实现自己的选择器来替换默认选择器,并支持新行为.
如果你谷歌搜索"自定义web api控制器选择器"你会发现很多样本,但我发现这对你的问题最有趣:
这个实现也很有趣:
如你所见,基本上你需要:
IHttpControllerSelector,它会考虑命名空间来查找控制器,以及命名空间路由变量,以选择其中一个.我知道这回答了一段时间,并且已经被原始海报接受了.但是,如果你像我一样需要使用属性路由并尝试了建议的答案,你会知道它不会很有效.
当我尝试这样做,我发现,它实际上是缺少应该已经通过调用扩展方法产生的路由信息MapHttpAttributeRoutes的的HttpConfiguration类:
config.MapHttpAttributeRoutes();
Run Code Online (Sandbox Code Playgroud)
这意味着SelectController替换IHttpControllerSelector实现的方法实际上永远不会被调用,这就是请求产生http 404响应的原因.
该问题是由一个内部类引起的,该类HttpControllerTypeCache是命名空间System.Web.Http下程序集中的内部类System.Web.Http.Dispatcher.有问题的代码如下:
private Dictionary<string, ILookup<string, Type>> InitializeCache()
{
return this._configuration.Services.GetHttpControllerTypeResolver().GetControllerTypes(this._configuration.Services.GetAssembliesResolver()).GroupBy<Type, string>((Func<Type, string>) (t => t.Name.Substring(0, t.Name.Length - DefaultHttpControllerSelector.ControllerSuffix.Length)), (IEqualityComparer<string>) StringComparer.OrdinalIgnoreCase).ToDictionary<IGrouping<string, Type>, string, ILookup<string, Type>>((Func<IGrouping<string, Type>, string>) (g => g.Key), (Func<IGrouping<string, Type>, ILookup<string, Type>>) (g => g.ToLookup<Type, string>((Func<Type, string>) (t => t.Namespace ?? string.Empty), (IEqualityComparer<string>) StringComparer.OrdinalIgnoreCase)), (IEqualityComparer<string>) StringComparer.OrdinalIgnoreCase);
}
Run Code Online (Sandbox Code Playgroud)
您将在此代码中看到它是按类型名称进行分组而没有命名空间.的DefaultHttpControllerSelector类使用该功能时,它积聚的内部高速缓存HttpControllerDescriptor为每个控制器.当使用MapHttpAttributeRoutes方法它使用另一种被称为内部类AttributeRoutingMapper,其是一部分System.Web.Http.Routing命名空间.该类使用方法GetControllerMapping的IHttpControllerSelector,以配置路由.
因此,如果您要编写自定义,IHttpControllerSelector那么您需要重载该GetControllerMapping方法才能使其工作.我提到这个的原因是我在互联网上看到的所有实现都没有这样做.
| 归档时间: |
|
| 查看次数: |
10069 次 |
| 最近记录: |