将子域名请求路由到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一直在学习,项目中有的时候也会用到,博客园也一直逛,想写点什么东西,可惜我这个人平时都很懒,理论层面的东西自己写不来,还是来点实际的简单入门的博客,对自己总结能 ...
随机推荐
- 使用es6特性封装async-mysql
node.js的mysql模块本身没有提供返回promise的函数,即是说都是用的回调函数,那么对于我们使用async函数是很不方便的一件事.node.js有一个mysql封装库叫mysql-prom ...
- 【前端】ACE Editor 简易使用示例
身为一个早已退役的Oier,当然忘不了当年一个个OJ页面上的代码显示和代码编辑器. 其中,洛谷使用的ACE Editor就是之一,非常的简洁美观.以及实际上在前端页面上搭建一个ACE Editor也是 ...
- 1623: [Usaco2008 Open]Cow Cars 奶牛飞车
1623: [Usaco2008 Open]Cow Cars 奶牛飞车 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 291 Solved: 201[S ...
- 用ListView实现对数据库的内容显示
用ListView实现对数据库的内容显示 创建一个触发机制 ---------(作用)将数据读入ArrayList集合中 MyBase base = new MyBase(); SQLiteDatab ...
- vue简易轮播图
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- python多线程学习笔记(超详细)
python threading 多线程 一. Threading简介 首先看下面的没有用Threading的程序 ): s += i time.sleep( ): s += i time. ...
- Linux 和 Windows 下实现多进程的方式以及管道操作
一.多进程 1.windows 多进程 使用 #include<windows.h> 下面的 BOOL CreateProcess( LPCWSTR pszImageName, LPCWS ...
- 大数据学习记录之ssh绵密登录
1,在服务器端 ssh-keygen 2,使用ssh-copy-id 192.168.2.146 3,再测试一下ssh 192.168.2.146 exit 退出当前登录 具体流程为:A,B两台机器 ...
- Realm数据持久化方案的简单介绍和使用(二)
接上篇... 4. 可空属性&默认值&忽略属性 默认情况下, 属性值可空, 如果强制要求某个属性非空, 可以使用如下方法: 遵循协议方法 + (NSArray *)requiredPr ...
- [原]android sdk更新的终极解决方案
由于众所周知的原因,国内更新Android SDK一直是个老大难的事情,一般都要到处找VPN之类的工具来曲线救国.不过其实谷歌已经帮我们想到这点了,我们自身就可以解决问题,步骤如下: 打开SDK Ma ...