将子域名请求路由到MVC区域
写了个扩展,分享给需要的朋友。
0x01 使用方法
在mvc区域中的{xxxx}AreaRegistration.cs文件中,如ProjectsAreaRegistration.cs
<pre>
<code>
using Dsvisual.Extensions;
namespace Dsvisual.WebApp.Areas.Projects
{
public class ProjectsAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "Projects";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapSubdomain("projects", true);
}
}
}
</code>
</pre>
0x02 扩展功能源码
<pre><code>
/// <summary>
/// an extension for map subdomain request to a mvc area
/// </summary>
public static class RouteExtension
{
/// <summary>
/// 创建该区域(Area)的路由并将子域名(subdomain)的请求映射到该区域
/// </summary>
/// <param name="ctx"></param>
/// <param name="subdomain">子域名</param>
/// <param name="allowShortUrl">是否启用短地址(当请求地址位于默认控制器时支持控制器路径省略)</param>
public static void MapSubdomain(this AreaRegistrationContext ctx, string subdomain, bool allowShortUrl)
{
ctx.Routes.MapSubdomain(subdomain, ctx.AreaName, ctx.Namespaces.ToArray(), allowShortUrl);
}
/// <summary>
/// 映射子域名到对应的区域
/// map the subdomain requests to the specific mvc Area
/// </summary>
/// <param name="routes"></param>
/// <param name="subdomain">子域名,支持多级 如admin.info.domain.com 则子域名为admin.info</param>
/// <param name="areaName">MVC Area名称</param>
/// <param name="namespaces">MVC Area所在的命名空间</param>
/// <param name="allowShortUrl">是否启用短地址(当请求地址位于默认控制器时支持控制器路径省略)</param>
private static void MapSubdomain(this RouteCollection routes, string subdomain, string areaName, string[] namespaces, bool allowShortUrl)
{
var prefix = areaName + "_";
var defaults = new { controller = "home", action = "index", id = UrlParameter.Optional };
bool flag = namespaces == null || namespaces.Length == 0;
var dataTokens = new { area = areaName, Namespaces = namespaces, UseNamespaceFallback = flag };
object constraints = null;
//通过配置两个路由来映射短路由和标准路由
//这里URL不带路由前缀目的是避免映射为二级域名后Html.ActionLink等输出路由前缀
//因为MVC区域默认是Projects/{controller}/{action}/{id}这样的格式,
//这样会导致Html.ActionLink等生成project.domain.com/project/home/index这样的路径
//而我们需要的是project.domain.com/home/index这样的格式
if (allowShortUrl)
{
//短路径输出支持路由默认控制器设置和当前调用的控制器相同的情况
//比如默认值设置为{controller="home",action="index"}
//当请求地址为projects.domain.com/details?id=5这样的地址时
//短路径可以将该请求解析到projects区域下HomeController的Details动作上
var shortUrl = new Route("{action}/{id}", new RouteValueDictionary(defaults), new RouteValueDictionary(constraints), new RouteValueDictionary(dataTokens), new MvcRouteHandler());
var shortUrlLocal = new Route(areaName + "/{action}/{id}", new RouteValueDictionary(defaults), new RouteValueDictionary(constraints), new RouteValueDictionary(dataTokens), new MvcRouteHandler());
var shortUrlRoute = new SubdomainRoute(subdomain, areaName, shortUrl, shortUrlLocal);
routes.Add(prefix + "shortUrl", shortUrlRoute);
}
var standard = new Route("{controller}/{action}/{id}", new RouteValueDictionary(defaults), new RouteValueDictionary(constraints), new RouteValueDictionary(dataTokens), new MvcRouteHandler());
var standardLocal = new Route(areaName + "/{controller}/{action}/{id}", new RouteValueDictionary(defaults), new RouteValueDictionary(constraints), new RouteValueDictionary(dataTokens), new MvcRouteHandler());
var standardRoute = new SubdomainRoute(subdomain, areaName, standard, standardLocal);
routes.Add(prefix + "standard", standardRoute);
}
/// <summary>
/// 子域名路由到Area
/// </summary>
internal class SubdomainRoute : Route
{
public Route LocalRoute { get; private set; }
public string LowercasedSubdomain { get; private set; }
public string LowercasedAreaName { get; set; }
public SubdomainRoute(string subdomain, string areaName, Route targetRoute, Route localRoute)
: base(targetRoute.Url, targetRoute.Defaults, targetRoute.Constraints, targetRoute.DataTokens, targetRoute.RouteHandler)
{
this.LocalRoute = localRoute;
this.LowercasedSubdomain = subdomain.ToLowerInvariant();
this.LowercasedAreaName = areaName.ToLowerInvariant();
//在缺失controller的默认值设定中补充一个controller默认值,否则MvcStandardRoute获取不到路由数据
if (!this.Defaults.ContainsKey("controller"))
{
this.Defaults["controller"] = "home";
}
}
public override RouteData GetRouteData(HttpContextBase httpContext)
{
//对于通过localhost或127.0.0.1访问的,SubdomainRoute相当于无效状态
if (httpContext.Request.IsLocal && httpContext.Request.Url.IsLoopback)
{
return LocalRoute == null ? null : LocalRoute.GetRouteData(httpContext);
}
var host = httpContext.Request.Url.Host.ToLowerInvariant();
if (host.StartsWith(LowercasedSubdomain))
{
var rest = host.Substring(LowercasedSubdomain.Length, host.Length - LowercasedSubdomain.Length);
if (rest.Count(x => x == '.') == 2)
{
var data = base.GetRouteData(httpContext);
//if (data == null)
//{
// data = new RouteData(this, this.RouteHandler);
// if (Defaults != null)
// {
// foreach (KeyValuePair<string, object> item in Defaults) //controller action index
// {
// if (!data.Values.ContainsKey(item.Key))
// data.Values[item.Key] = item.Value;
// }
// }
// if (DataTokens != null)
// {
// foreach (var item in DataTokens) //Namespaces,area,UseNamespaceFallback
// {
// if (!data.DataTokens.ContainsKey(item.Key))
// data.DataTokens[item.Key] = item.Value;
// }
// }
//}
//data.DataTokens["area"] = this.LowercasedAreaName;
return data;
}
}
return null;
}
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
if (requestContext.HttpContext.Request.IsLocal && requestContext.HttpContext.Request.Url.IsLoopback)
{
return LocalRoute == null ? null : LocalRoute.GetVirtualPath(requestContext, values);
}
var virturalPathData = base.GetVirtualPath(requestContext, values);
return virturalPathData;
}
}
}
</code></pre>
将子域名请求路由到MVC区域的更多相关文章
- mvc路由,mvc区域
1.路由在进行匹配时,会默认匹配第一个路由信息 2.路由规则的{control}和{action}时不能改变的 3.路由规则可以中间字符可以随便定义,但是{control}和{action}必须使用一 ...
- 浅谈ThinkPHP3.2的子域名部署和路由优化(一)
前言:建立一个网站系统,往往包含多个子网站,例如PC官网,移动端官网,后台管理,数据源自一个相同的数据库,整个架构上,从ThinkPHP来看,可以大体理解为Model(M)是一样的,Controlle ...
- .NET MVC 获取 当前请求的 控制器/视图/区域 的名字
.NET MVC 在action中或过滤器中或视图中,分别如何获取 当前请求的 控制器/视图/区域 的名字 1)过滤器中的: public class CMSAttribute : Filter ...
- Flask02 路由的书写、蓝图、利用蓝图实现url前缀、利用蓝图实现子域名、访问静态文件
1 书写路由的两种方法 1.1 利用Flask实例对象的 add_url_rule 方法实现 该方法有一个必填参数,两个默认参数 · rule : 请求路径的规则 endpoint : 端点,默认值是 ...
- MVC教程:MVC区域路由
一.区域路由 为了管理网站中大量的文件,在ASP.NET MVC 2.0版本中引入了一个新概念:区域(Area). 有了区域以后,可以让我们的项目不至于太复杂而导致管理混乱.每个模块的页面都放入相应的 ...
- Laravel 5 中间件、路由群组、子域名路由、 权限控制的基本使用方法
创建控制器: php artisan make:controller Admin/IndexController 创建Middleware: php artisan make:middleware T ...
- Laravel之路由 Route::get/post/any、路由参数、过滤器、命名、子域名、前缀、与模型绑定、抛出 404 错误、控制器
基本路由 应用中的大多数路都会定义在 app/routes.php 文件中.最简单的Laravel路由由URI和闭包回调函数组成. 基本 GET 路由 代码如下: Route::get('/', fu ...
- MVC区域使用
新建项目 Main: 添加一个MVC5控制器并添加index视图:(HomeController) Views/Home/Index.cshtml内容: @{ Layout = null; } < ...
- MVC区域小结
MVC区域小结 MVC区域小结 MVC3一直在学习,项目中有的时候也会用到,博客园也一直逛,想写点什么东西,可惜我这个人平时都很懒,理论层面的东西自己写不来,还是来点实际的简单入门的博客,对自己总结能 ...
随机推荐
- Xamarin自定义布局系列——瀑布流布局
Xamarin.Forms以Xamarin.Android和Xamarin.iOS等为基础,自己实现了一整套比较完整的UI框架,包含了绝大多数常用的控件,如下图 虽然XF(Xamarin.Forms简 ...
- JAVA面试题和答案
本文我们将要讨论Java面试中的各种不同类型的面试题,它们可以让雇主测试应聘者的Java和通用的面向对象编程的能力.下面的章节分为上下两篇,第一篇将要讨论面向对象编程和它的特点,关于Java和它的功能 ...
- 解决Antimalware Service Executable CPU占用高听语音
windows8/8.1,WIN10自带的安全软件Windows defender还不错,基本可以不用装其他杀毒软件了. 但是其进程Antimalware Service Executable 出现C ...
- ADO.NET温习(一)
ADO.NET概述 本节复习如何使用ADO.NET访问C#程序中的数据,主要介绍如何使用SqlConnection类和OleDbConnection类连接数据库,以及断开与数据库连接.深入讨论命令对象 ...
- box-shadow IE8兼容处理
根据canisue(http://caniuse.com/#search=box-shadow),box-shadow兼容性如下图所示: 测试代码: <!DOCTYPE html> < ...
- Python快速入门(2)
var = raw_input() 获取用户输入,该函数会将获取的值转化为一个字符串,因此有时需要强制类型转换. if-elif-else: 三元操作符:condition1 if exp else ...
- Android -- 贝塞尔曲线公式的推导
1,最近看了几个不错的自定义view,发现里面都会涉及到贝塞尔曲线知识,深刻的了解到贝塞尔曲线是进阶自定义view的一座大山,so,今天先和大家来了解了解. 2,贝塞尔曲线作用十分广泛,简单举几个的栗 ...
- vuejs模板使用方法
vuejs的模板功能很强大,下面是一些demo <!DOCTYPE html> <html lang="en"> <head> <meta ...
- poptest老李谈Socket
poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821478,咨询电话010-845052 ...
- backtracking问题
backtracking最基础的问题是Subsets,即给定一个数组,要求返回其所有子集. Given a set of distinct integers, nums, return all pos ...