自定义WebViewPage,实现Url.Action生成绝对地址
2015-10-29 16:53
323 查看
前言
运营部门一直对公司官网SEO有意见,认为做得不好(说得好像运营做不好都是seo似的)。为此两部门老大还闹到CEO那去了。
也因为这事,工作计划终于排上日程。沟通一番后得知有如下几点需求:
1.所有链接都得是绝对地址。比如之前是/about.html,现在得变成http://xxx.com/about.html(你妹啊,这样我本地怎么测试)
2.所有目录最后都加/,没有的定久重定向到加/的。比如之前/xxx ,现在得变成http://xxx.com/xxx/
3.图片必须加alt ,width height 属性
分析编码
前些天图片问题已经改完了,现在重点是链接。因为项目链接大多走的Url.Action,所以自然的想到得从这入手。
其实微软已经为我们提供了这个实现,即 @Url.Action("actionName","controllerName","routeValues","protocol","hostName")
全解决方案搜索Url.Action,一千多处。想到前面优化img标签加alt,才五百多处就花了一天半时间,这肯定是不能接受的。
mvc 不是开源了吗,把源码down下来看看,https://git01.codeplex.com/aspnetwebstack
分析源码定位到两个核心的类 UrlHelper WebViewPage
修改后CustomUrlHelper
代码中构造函数读取配置您需要改写成自己的实现逻辑。
参考:
Changing Base Type Of A Razor View
Create Your Own Custom ViewWebPage for ASP.NET MVC
MVC中自定义ViewPage和WebViewPage
运营部门一直对公司官网SEO有意见,认为做得不好(说得好像运营做不好都是seo似的)。为此两部门老大还闹到CEO那去了。
也因为这事,工作计划终于排上日程。沟通一番后得知有如下几点需求:
1.所有链接都得是绝对地址。比如之前是/about.html,现在得变成http://xxx.com/about.html(你妹啊,这样我本地怎么测试)
2.所有目录最后都加/,没有的定久重定向到加/的。比如之前/xxx ,现在得变成http://xxx.com/xxx/
3.图片必须加alt ,width height 属性
分析编码
前些天图片问题已经改完了,现在重点是链接。因为项目链接大多走的Url.Action,所以自然的想到得从这入手。
其实微软已经为我们提供了这个实现,即 @Url.Action("actionName","controllerName","routeValues","protocol","hostName")
全解决方案搜索Url.Action,一千多处。想到前面优化img标签加alt,才五百多处就花了一天半时间,这肯定是不能接受的。
mvc 不是开源了吗,把源码down下来看看,https://git01.codeplex.com/aspnetwebstack
分析源码定位到两个核心的类 UrlHelper WebViewPage
using System; using System.Globalization; using System.Web.Mvc; using System.Web.Routing; using System.Web.WebPages; using System.Collections.Generic; using MSP.Common.Tools; namespace SF.MVC.Core { public class CustomUrlHelper : UrlHelper { /// <summary> /// 是否需要加端口号 /// </summary> private static bool IsNeedProtocol = false; public CustomUrlHelper(RequestContext requestContext) : base(requestContext, RouteTable.Routes) { ConfigManager config = new ConfigManager(); config.LoadConfig("common"); string configValue = config.GetConfig("NeedProtocol") == null ? "false" : config.GetConfig("NeedProtocol").Value; bool.TryParse(configValue, out IsNeedProtocol); } public new string Action(string actionName, string controllerName) { var hostName = RequestContext.HttpContext.Request.Url.Host; return GenerateUrl(null, actionName, controllerName, null, hostName, null, (RouteValueDictionary)null, RouteCollection, RequestContext, true); } public new string Action(string actionName, string controllerName, object routeValues) { var hostName = RequestContext.HttpContext.Request.Url.Host; return GenerateUrl(null, actionName, controllerName, null, hostName, null, new RouteValueDictionary(routeValues), RouteCollection, RequestContext, true); } public new string RouteUrl(string routeName) { var hostName = RequestContext.HttpContext.Request.Url.Host; return GenerateUrl(routeName, null, null, null, hostName, null, (RouteValueDictionary)null, RouteCollection, RequestContext, false); } public new static string GenerateUrl(string routeName, string actionName, string controllerName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, RouteCollection routeCollection, RequestContext requestContext, bool includeImplicitMvcValues) { string url = GenerateUrl(routeName, actionName, controllerName, routeValues, routeCollection, requestContext, includeImplicitMvcValues); if (url != null) { if (!IsContain(url)) url += "/"; if (!String.IsNullOrEmpty(fragment)) { url = url + "#" + fragment; } if (!String.IsNullOrEmpty(protocol) || !String.IsNullOrEmpty(hostName)) { Uri requestUrl = requestContext.HttpContext.Request.Url; protocol = (!String.IsNullOrEmpty(protocol)) ? protocol : Uri.UriSchemeHttp; hostName = (!String.IsNullOrEmpty(hostName)) ? hostName : requestUrl.Host; string port = String.Empty; string requestProtocol = requestUrl.Scheme; if (IsNeedProtocol && String.Equals(protocol, requestProtocol, StringComparison.OrdinalIgnoreCase)) { port = requestUrl.IsDefaultPort ? String.Empty : (":" + Convert.ToString(requestUrl.Port, CultureInfo.InvariantCulture)); } url = protocol + Uri.SchemeDelimiter + hostName + port + url; } } return url; } /// <summary> /// 判断字符串中是否包含某部分 /// </summary> /// <param name="input"></param> /// <returns></returns> private static bool IsContain(string input) { if (string.IsNullOrWhiteSpace(input)) return false; if (input == "/") { return true; } else if(input.Contains("articledetial")) { return true; } else if (input.Contains("special")) { return true; } else if(input.EndsWith(".html", StringComparison.CurrentCultureIgnoreCase)) { return true; } return false; } } }
修改后CustomUrlHelper
代码中构造函数读取配置您需要改写成自己的实现逻辑。
参考:
Changing Base Type Of A Razor View
Create Your Own Custom ViewWebPage for ASP.NET MVC
MVC中自定义ViewPage和WebViewPage
相关文章推荐
- Android Lint 检查规则的定制(基本篇)
- java.lang.ClassCastException 在 android 当尝试获取应用程序的图标
- AndroidStudio之Gradle离线配置
- Android 底部导航菜单
- SWIFT——条件语句(if/switch)
- Android启动流程
- android lint简介
- App自动更新之通知栏下载
- Android LayoutInflater原理分析(一)
- Android的数据持久化存储
- ios开发系列-界面
- [Objective-C]关联(objc_setAssociatedObject、objc_getAssociatedObject、objc_removeAssociatedObjects)
- Android代码静态检查工具---android lint
- android 中popupwindow 和类似360悬浮小球
- phonegap + Framework7 之 ios 推送跳转测试
- Android ScrollView
- iPhone How-to:解析URL中的键值对
- iOS新技术特性
- Android之SimpleAdapter
- Android: 在 TextView 里使用删除线