/Xoohoo/Extensions/UrlHelperExtensions.cs
C# | 233 lines | 149 code | 36 blank | 48 comment | 20 complexity | a20eef9c835437607ea0941e831f436c MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net;
- using System.Text;
- using System.Web;
- using System.Web.Caching;
- using System.Web.Mvc;
- using System.Web.Routing;
- using Xoohoo.ViewEngines;
-
- namespace Xoohoo.Extensions
- {
- public static class UrlHelperExtensions
- {
- /// <summary>
- /// 构建绝对路径
- /// </summary>
- /// <param name="urlHelper">UrlHelper</param>
- /// <param name="relativeUrl">相对路径</param>
- /// <returns></returns>
- public static string AbsolutePath(this UrlHelper urlHelper, string relativeUrl)
- {
- Uri url = urlHelper.RequestContext.HttpContext.Request.Url;
- UriBuilder uriBuilder = new UriBuilder(url.Scheme, url.Host, url.Port) { Path = relativeUrl };
-
- string path = uriBuilder.Uri.ToString();
-
- if (path.EndsWith("/"))
- path = path.Substring(0, path.Length - 1);
-
- //TODO: (erikpo) Instead of this workaround, chop off the hash before feeding the url to UrlBuilder, then tack it back on before returning the final url
- path = path.Replace("%23", "#");
- return path;
- }
-
- /// <summary>
- /// 构建应用程序路径
- /// </summary>
- /// <param name="urlHelper">UrlHelper</param>
- /// <param name="relativeUrl">相对路径(或绝对路径)</param>
- /// <returns></returns>
- public static string AppPath(this UrlHelper urlHelper, string relativePath)
- {
- if (relativePath == null) return null;
-
- if (relativePath.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase)
- || relativePath.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase))
- return relativePath;
-
- if (!relativePath.StartsWith("~/"))
- {
- if (!relativePath.StartsWith("/"))
- relativePath = "/" + relativePath;
- if (!relativePath.StartsWith("~"))
- relativePath = "~" + relativePath;
- }
-
- return VirtualPathUtility.ToAbsolute(relativePath, urlHelper.RequestContext.HttpContext.Request.ApplicationPath);
- }
-
- /// <summary>
- /// 构建样式表文件路径
- /// </summary>
- /// <param name="urlHelper">UrlHelper</param>
- /// <param name="relativeUrl">相对路径</param>
- /// <param name="viewContext">ViewContext</param>
- /// <returns></returns>
- public static string StylePath(this UrlHelper urlHelper, string relativePath, ViewContext viewContext)
- {
- string path = relativePath;
-
- if (!string.IsNullOrEmpty(path) && !path.StartsWith("/"))
- path = "/" + path;
-
- urlHelper.FilePath(viewContext, (ve, p) => ve.FindFile(p), ref path);
-
- return path;
- }
-
- /// <summary>
- /// 构建脚本文件路径
- /// </summary>
- /// <param name="urlHelper"></param>
- /// <param name="relativePath"></param>
- /// <param name="viewContext"></param>
- /// <returns></returns>
- public static string ScriptPath(this UrlHelper urlHelper, string relativePath, ViewContext viewContext)
- {
- string path = relativePath;
-
- if (!string.IsNullOrEmpty(path) && !path.StartsWith("/"))
- path = "/" + path;
-
- urlHelper.FilePath(viewContext, (ve, p) => ve.FindFile(p), ref path);
-
- return path;
- }
-
- /// <summary>
- /// 构建文件路径
- /// </summary>
- /// <param name="urlHelper">UrlHelper</param>
- /// <param name="viewContext">ViewContext</param>
- /// <param name="findFile">要查找的文件</param>
- /// <param name="path">要返回的路径</param>
- internal static void FilePath(this UrlHelper urlHelper, ViewContext viewContext, Func<IXoohooViewEngine, string, FileEngineResult> findFile, ref string path)
- {
- List<string> searchedLocations = new List<string>(50);
-
- //key为XoohooViewEngines的ViewData是通过ViewEnginesResultFilter设置的
- foreach (IXoohooViewEngine viewEngine in (IEnumerable<IXoohooViewEngine>)viewContext.ViewData["XoohooViewEngines"])
- {
- FileEngineResult result = findFile(viewEngine, path);
-
- if (result.SearchedLocations.Count() > 0)
- searchedLocations.AddRange(result.SearchedLocations);
- else
- {
- path = urlHelper.AppPath(result.FilePath);
- searchedLocations.Clear();
-
- break;
- }
- }
-
- if (searchedLocations.Count > 0)
- {
- //如果是调试模式,如果没找到文件,抛出异常
- //key为Debug的ViewData是通过DebugActionFilter设置的
- if (viewContext.ViewData["Debug"] is bool && (bool)viewContext.ViewData["Debug"])
- {
- StringBuilder locationsText = new StringBuilder();
-
- foreach (string location in searchedLocations)
- {
- locationsText.AppendLine();
- locationsText.Append(location);
- }
-
- throw new InvalidOperationException(string.Format("The file '{0}' could not be found. The following locations were searched:{1}", path, locationsText));
- }
- else
- {
- path = urlHelper.AppPath(searchedLocations.ElementAt(0));
- }
- }
- }
-
- /// <summary>
- /// 站点首页
- /// </summary>
- /// <param name="urlHelper">UrlHelper</param>
- /// <returns></returns>
- public static string Home(this UrlHelper urlHelper)
- {
- return urlHelper.AppPath("~/");
- }
-
- /// <summary>
- /// 缩略网址
- /// </summary>
- /// <param name="urlHelper"></param>
- /// <param name="absoluteUrlEncoded"></param>
- /// <returns></returns>
- public static string CompressUrl(this UrlHelper urlHelper, string absoluteUrlEncoded)
- {
- string cacheKey = "tinyurl:" + absoluteUrlEncoded.ToLower();
- Cache cache = urlHelper.RequestContext.HttpContext.Cache;
- string url = (string)cache[cacheKey];
-
- if (string.IsNullOrEmpty(url))
- {
- try
- {
- const string urlToSendTo = "http://is.gd/api.php?longurl={0}";
- WebClient wc = new WebClient();
-
- url = wc.DownloadString(string.Format(urlToSendTo, absoluteUrlEncoded));
-
- cache.Add(cacheKey, url, null, DateTime.Now.AddHours(1), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
- }
- catch
- {
- url = absoluteUrlEncoded;
- }
- }
-
- return url;
- }
-
- public static string ActionEx(this UrlHelper helper, string action, object routeValues)
- {
- var values = routeValues == null ?
- new RouteValueDictionary() :
- new RouteValueDictionary(routeValues);
- values.Add("action", action);
- values.Add("controller", helper.RequestContext.RouteData.Values["controller"]);
-
- var pathData = helper.RouteCollection.GetPath(helper.RequestContext, values);
- var url = pathData.VirtualPath;
- return IsAbsolute(url) ? url : "/" + url;
- }
-
- #region Private Methods
-
- private static VirtualPathData GetPath(
- this RouteCollection routes,
- RequestContext requestContext,
- RouteValueDictionary values)
- {
- foreach (RouteBase r in routes)
- {
- VirtualPathData pathData = r.GetVirtualPath(requestContext, values);
- if (pathData != null)
- {
- return pathData;
- }
- }
-
- throw new ArgumentException("Invalid values for building URL.");
- }
-
- private static bool IsAbsolute(string url)
- {
- return
- url.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase) ||
- url.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase);
- }
- #endregion
-
- }
- }