前言

默认情况下,微软提供的MVC框架模板中,WebAPI路由是不支持Namespace参数的。这导致一些比较大型的项目,无法把WebApi分离到单独的类库中。

本文将提供解决该问题的方案。

微软官方曾经给出过一个关于WebAPI支持Namespace的扩展,其主要内容就是自定义实现了IHttpControllerSelector接口,通过路由配置时替换掉MVC中自带的DefaultHttpControllerSelector达到WebAPI支持Namespace的目的。但是经过我的测试,效果并不好。这就就不贴微软官方的源码了。

解决方案

下面我介绍一下我的解决方案。

首先看一下我自定义的目录结构,如下图:

首先定义一个类,名字可以随意,我这里命名为ZhuSirNamespaceHttpControllerSelector,他继承自MVC框架默认的DefaultHttpControllerSelector类,该继承类主要目的是在请求URI到达WebAPI路由时检索我们指定的命名空间的WebAPI控制器。下面是ZhuSirNamespaceHttpControllerSelector类的源代码,可直接复制到你自己的项目中就可以用:

/// <summary>
/// 扩展自DefaultHttpControllerSelector类的控制器选择器,目前在用
/// </summary>
public class ZhuSirNamespaceHttpControllerSelector : DefaultHttpControllerSelector
{
private const string NamespaceRouteVariableName = "namespaces";
private readonly HttpConfiguration _configuration;
private readonly Lazy<ConcurrentDictionary<string, Type>> _apiControllerCache; public ZhuSirNamespaceHttpControllerSelector(HttpConfiguration configuration)
: base(configuration)
{
_configuration = configuration;
_apiControllerCache = new Lazy<ConcurrentDictionary<string, Type>>(
new Func<ConcurrentDictionary<string, Type>>(InitializeApiControllerCache));
} private ConcurrentDictionary<string, Type> InitializeApiControllerCache()
{
IAssembliesResolver assembliesResolver = this._configuration.Services.GetAssembliesResolver();
var types = this._configuration.Services.GetHttpControllerTypeResolver()
.GetControllerTypes(assembliesResolver).ToDictionary(t => t.FullName, t => t); return new ConcurrentDictionary<string, Type>(types);
} public IEnumerable<string> GetControllerFullName(HttpRequestMessage request, string controllerName)
{
object namespaceName;
var data = request.GetRouteData();
IEnumerable<string> keys = _apiControllerCache.Value.ToDictionary<KeyValuePair<string, Type>, string, Type>(t => t.Key,
t => t.Value, StringComparer.CurrentCultureIgnoreCase).Keys.ToList(); if (!data.Values.TryGetValue(NamespaceRouteVariableName, out namespaceName))
{
return from k in keys
where k.EndsWith(string.Format(".{0}{1}", controllerName,
DefaultHttpControllerSelector.ControllerSuffix), StringComparison.CurrentCultureIgnoreCase)
select k;
} string[] namespaces = (string[])namespaceName;
return from n in namespaces
join k in keys on string.Format("{0}.{1}{2}", n, controllerName,
DefaultHttpControllerSelector.ControllerSuffix).ToLower() equals k.ToLower()
select k;
} public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
Type type;
if (request == null)
{
throw new ArgumentNullException("request");
}
string controllerName = this.GetControllerName(request);
if (string.IsNullOrEmpty(controllerName))
{
throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound,
string.Format("无法通过API路由匹配到您所请求的URI '{0}'",
new object[] { request.RequestUri })));
}
IEnumerable<string> fullNames = GetControllerFullName(request, controllerName);
if (fullNames.Count() == 0)
{
throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound,
string.Format("无法通过API路由匹配到您所请求的URI '{0}'",
new object[] { request.RequestUri })));
} if (this._apiControllerCache.Value.TryGetValue(fullNames.First(), out type))
{
return new HttpControllerDescriptor(_configuration, controllerName, type);
}
throw new HttpResponseException(request.CreateErrorResponse(HttpStatusCode.NotFound,
string.Format("无法通过API路由匹配到您所请求的URI '{0}'",
new object[] { request.RequestUri })));
}
}
   第二步,需要我们配置WebAPI路由设置,添加{ namespaces }片段变量,同时也可以直接为其设置默认值,然后替换掉原MVC框架中的DefaultHttpControllerSelector选额器为我们之前扩展的ZhuSirNamespaceHttpControllerSelector选额器。这里需要注意片段变量的变量名namespaces一定要与我们ZhuSirNamespaceHttpControllerSelector中定义的NamespaceRouteVariableName字符串常量的值一致。下面贴出WebApiConfig的源码:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
//配置检查Api控制后缀为ApiController
//var suffix = typeof(MicrosoftNamespaceHttpControllerSelector)
// .GetField("ControllerSuffix", BindingFlags.Static | BindingFlags.Public);
//if (suffix != null)
//{
// suffix.SetValue(null, "ApiController");
//} // Web API 配置和服务
// 将 Web API 配置为仅使用不记名令牌身份验证。
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); // 对 JSON 数据使用混合大小写。
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); // Web API 路由
config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}/{namespaces}",
defaults: new { id = RouteParameter.Optional ,namespaces = new[] { "ZhuSir.HMS.WebApi.ApiControllers" } }
); config.Services.Replace(typeof(IHttpControllerSelector), new ZhuSirNamespaceHttpControllerSelector(config));
}
}

如上源码。我们替换了原MVC框架的DefaultHttpControllerSelector为ZhuSirNamespaceHttpControllerSelector,并且指定了默认的namespaces为ZhuSir.HMS.WebApi.ApiControllers。大体意思就是当URL为 http://XXX/api/testApi时,WebApi路由将在ZhuSir.HMS.WebApi.ApiControllers命名空间下寻找名称为testApi的WebAPI控制器的Get方法。

当然,WebAPI控制器除了集成字ApiController意外还要注意命名规范,都需要以Controller结尾,为了不让API控制器与MVC控制器重名,我都以ApiController结尾。下面贴出testAPI的源码:

namespace ZhuSir.HMS.WebApi.ApiControllers
{
public class TestApiController : ApiController
{
[HttpGet]
public string Gettest()
{
return "测试数据";
}
}
}

测试

程序Debug,录入URL: http://localhost:4541/api/TestApi,得到如下结果:

可以看出,WebAPI路由成功访问到了其他类库中的WebAPI控制器。

希望本文对你能有所帮助,如果转载请注明出处:http://www.cnblogs.com/smallprogram/p/5673066.html

作者:smallprogram
感谢您的阅读。喜欢的、有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力。欢迎转载!另外,文章在表述和代码方面如有不妥之处,欢迎批评指正。留下你的脚印,欢迎评论!
 
分类: Asp.NET MVC

asp.net MVC5为WebAPI添加命名空间的支持的更多相关文章

  1. MVC5为WebAPI添加命名空间的支持

    前言 默认情况下,微软提供的MVC框架模板中,WebAPI路由是不支持Namespace参数的.这导致一些比较大型的项目,无法把WebApi分离到单独的类库中. 本文将提供解决该问题的方案. 微软官方 ...

  2. MVC5为WebAPI添加命名空间的支持1

    前言 默认情况下,微软提供的MVC框架模板中,WebAPI路由是不支持Namespace参数的.这导致一些比较大型的项目,无法把WebApi分离到单独的类库中. 本文将提供解决该问题的方案. 微软官方 ...

  3. 给Asp.Net MVC及WebApi添加路由优先级

    一.为什么需要路由优先级 大家都知道我们在Asp.Net MVC项目或WebApi项目中注册路由是没有优先级的,当项目比较大.或有多个区域.或多个Web项目.或采用插件式框架开发时,我们的路由注册很可 ...

  4. 【转载】为ASP.NET MVC及WebApi添加路由优先级

    路由方面的: 转载地址:http://www.jb51.net/article/73417.htm Author:lijiao 这是一个对Asp.Net Mvc的一个很小的功能拓展,小项目可能不太需要 ...

  5. 为Asp.net WebApi 添加跨域支持

    Nuget安装包:microsoft.aspnet.webapi.cors 原文地址:https://www.asp.net/web-api/overview/security/enabling-cr ...

  6. 为 ASP.NET Core (6.0)服务应用添加ApiKey验证支持

    这个代码段演示了如何为一个ASP.NET Core项目中添加Apikey验证支持. 首先,通过下面的代码创建项目 dotnet new webapi -minimal -o yourwebapi 然后 ...

  7. [Asp.net MVC]Asp.net MVC5系列——在模型中添加验证规则

    目录 概述 在模型中添加验证规则 自定义验证规则 伙伴类的使用 总结 系列文章 [Asp.net MVC]Asp.net MVC5系列——第一个项目 [Asp.net MVC]Asp.net MVC5 ...

  8. 四、 添加模型Model(ASP.NET MVC5 系列)

    在这一章节中我们将添加一些classes类来管理数据库中的movies.这些classes类就是ASP.NET MVC应用程序中的"model". 我们将用.NET框架中的数据访问 ...

  9. 构建ASP.NET MVC5+EF6+EasyUI 1.4.3+Unity4.x注入的后台管理系统(66)-MVC WebApi 用户验证 (2)

    前言: 构建ASP.NET MVC5+EF6+EasyUI 1.4.3+Unity4.x注入的后台管理系统(65)-MVC WebApi 用户验证 (1) 回顾上一节,我们利用webapi简单的登录并 ...

随机推荐

  1. oracle11g自动内存管理

    Oracle一直不停的在为Orace数据库的自动化管理努力着,11G中的自动内存管理是Oracle数据库中又一新的里程碑,通过新参数MEMORY_TARGET 来代替PGA和SGA的配置,ORACLE ...

  2. j2cache笔记

    初步理解 eg: https://my.oschina.net/javayou https://my.oschina.net/tinyframework/blog/538363?p=2 https:/ ...

  3. python与用户交互、数据类型

    一.与用户交互 1.什么是用户交互: 程序等待用户输入一些数据,程序执行完毕反馈信息. 2.如何使用 在python3中使用input,input会将用户输入的如何内容存为字符串:在python中分为 ...

  4. 洛谷P5072 [Ynoi2015]盼君勿忘 [莫队]

    传送门 辣鸡卡常题目浪费我一下午-- 思路 显然是一道莫队. 假设区间长度为\(len\),\(x\)的出现次数为\(k\),那么\(x\)的贡献就是\(x(2^{len-k}(2^k-1))\),即 ...

  5. Confluence 6 Windows 中以服务方式自动重启为服务手动安装 Confluence 分发包

    在 Windows: 打开一个命令输入框,然后修改目录到 <CONFLUENCE-INSTALL>/bin 目录中.你需要以管理员权限运行这个命令行输入框(Run as administr ...

  6. 其他 Confluence 6 的 cookies 和备注

    其他 Confluence 的 cookies 针对 Confluence 的功能,我们还使用了其他的一些 cookies 来存储基本的 产品持久性(product presentation).Con ...

  7. 设置 Confluence 6 日志

    Confluence 使用的是 Apache's log4j 日志服务.能够允许管理员通过编辑配置文件来控制日志的表现和日志输出文件.在系统中有 6 个日志输出级别,请参考 log4j logging ...

  8. map函数和reduce函数的区别

    ①从参数方面来讲:map()函数: map()包含两个参数,第一个是参数是一个函数,第二个是序列(列表或元组).其中,函数(即map的第一个参数位置的函数)可以接收一个或多个参数.reduce()函数 ...

  9. GetSystemInfo()

    关于“GetSystemInfo()”的详细信息,参考:https://msdn.microsoft.com/en-us/library/windows/desktop/ms724381(v=vs.8 ...

  10. WIN 7 使用shutdown命令设置电脑自动关机

    使用组合键“WIN + R”,在弹出的对话窗“运行”中输入“cmd”,点击“确定”按钮或直接按回车键“Enter”.  设置电脑在一定时间后关机,比如60分钟,在弹出的对话框中,输入“shutdown ...