PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/Xoohoo/Extensions/UrlHelperExtensions.cs

#
C# | 233 lines | 149 code | 36 blank | 48 comment | 20 complexity | a20eef9c835437607ea0941e831f436c MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Net;
  5. using System.Text;
  6. using System.Web;
  7. using System.Web.Caching;
  8. using System.Web.Mvc;
  9. using System.Web.Routing;
  10. using Xoohoo.ViewEngines;
  11. namespace Xoohoo.Extensions
  12. {
  13. public static class UrlHelperExtensions
  14. {
  15. /// <summary>
  16. /// 构建绝对路径
  17. /// </summary>
  18. /// <param name="urlHelper">UrlHelper</param>
  19. /// <param name="relativeUrl">相对路径</param>
  20. /// <returns></returns>
  21. public static string AbsolutePath(this UrlHelper urlHelper, string relativeUrl)
  22. {
  23. Uri url = urlHelper.RequestContext.HttpContext.Request.Url;
  24. UriBuilder uriBuilder = new UriBuilder(url.Scheme, url.Host, url.Port) { Path = relativeUrl };
  25. string path = uriBuilder.Uri.ToString();
  26. if (path.EndsWith("/"))
  27. path = path.Substring(0, path.Length - 1);
  28. //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
  29. path = path.Replace("%23", "#");
  30. return path;
  31. }
  32. /// <summary>
  33. /// 构建应用程序路径
  34. /// </summary>
  35. /// <param name="urlHelper">UrlHelper</param>
  36. /// <param name="relativeUrl">相对路径(或绝对路径)</param>
  37. /// <returns></returns>
  38. public static string AppPath(this UrlHelper urlHelper, string relativePath)
  39. {
  40. if (relativePath == null) return null;
  41. if (relativePath.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase)
  42. || relativePath.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase))
  43. return relativePath;
  44. if (!relativePath.StartsWith("~/"))
  45. {
  46. if (!relativePath.StartsWith("/"))
  47. relativePath = "/" + relativePath;
  48. if (!relativePath.StartsWith("~"))
  49. relativePath = "~" + relativePath;
  50. }
  51. return VirtualPathUtility.ToAbsolute(relativePath, urlHelper.RequestContext.HttpContext.Request.ApplicationPath);
  52. }
  53. /// <summary>
  54. /// 构建样式表文件路径
  55. /// </summary>
  56. /// <param name="urlHelper">UrlHelper</param>
  57. /// <param name="relativeUrl">相对路径</param>
  58. /// <param name="viewContext">ViewContext</param>
  59. /// <returns></returns>
  60. public static string StylePath(this UrlHelper urlHelper, string relativePath, ViewContext viewContext)
  61. {
  62. string path = relativePath;
  63. if (!string.IsNullOrEmpty(path) && !path.StartsWith("/"))
  64. path = "/" + path;
  65. urlHelper.FilePath(viewContext, (ve, p) => ve.FindFile(p), ref path);
  66. return path;
  67. }
  68. /// <summary>
  69. /// 构建脚本文件路径
  70. /// </summary>
  71. /// <param name="urlHelper"></param>
  72. /// <param name="relativePath"></param>
  73. /// <param name="viewContext"></param>
  74. /// <returns></returns>
  75. public static string ScriptPath(this UrlHelper urlHelper, string relativePath, ViewContext viewContext)
  76. {
  77. string path = relativePath;
  78. if (!string.IsNullOrEmpty(path) && !path.StartsWith("/"))
  79. path = "/" + path;
  80. urlHelper.FilePath(viewContext, (ve, p) => ve.FindFile(p), ref path);
  81. return path;
  82. }
  83. /// <summary>
  84. /// 构建文件路径
  85. /// </summary>
  86. /// <param name="urlHelper">UrlHelper</param>
  87. /// <param name="viewContext">ViewContext</param>
  88. /// <param name="findFile">要查找的文件</param>
  89. /// <param name="path">要返回的路径</param>
  90. internal static void FilePath(this UrlHelper urlHelper, ViewContext viewContext, Func<IXoohooViewEngine, string, FileEngineResult> findFile, ref string path)
  91. {
  92. List<string> searchedLocations = new List<string>(50);
  93. //key为XoohooViewEngines的ViewData是通过ViewEnginesResultFilter设置的
  94. foreach (IXoohooViewEngine viewEngine in (IEnumerable<IXoohooViewEngine>)viewContext.ViewData["XoohooViewEngines"])
  95. {
  96. FileEngineResult result = findFile(viewEngine, path);
  97. if (result.SearchedLocations.Count() > 0)
  98. searchedLocations.AddRange(result.SearchedLocations);
  99. else
  100. {
  101. path = urlHelper.AppPath(result.FilePath);
  102. searchedLocations.Clear();
  103. break;
  104. }
  105. }
  106. if (searchedLocations.Count > 0)
  107. {
  108. //如果是调试模式,如果没找到文件,抛出异常
  109. //key为Debug的ViewData是通过DebugActionFilter设置的
  110. if (viewContext.ViewData["Debug"] is bool && (bool)viewContext.ViewData["Debug"])
  111. {
  112. StringBuilder locationsText = new StringBuilder();
  113. foreach (string location in searchedLocations)
  114. {
  115. locationsText.AppendLine();
  116. locationsText.Append(location);
  117. }
  118. throw new InvalidOperationException(string.Format("The file '{0}' could not be found. The following locations were searched:{1}", path, locationsText));
  119. }
  120. else
  121. {
  122. path = urlHelper.AppPath(searchedLocations.ElementAt(0));
  123. }
  124. }
  125. }
  126. /// <summary>
  127. /// 站点首页
  128. /// </summary>
  129. /// <param name="urlHelper">UrlHelper</param>
  130. /// <returns></returns>
  131. public static string Home(this UrlHelper urlHelper)
  132. {
  133. return urlHelper.AppPath("~/");
  134. }
  135. /// <summary>
  136. /// 缩略网址
  137. /// </summary>
  138. /// <param name="urlHelper"></param>
  139. /// <param name="absoluteUrlEncoded"></param>
  140. /// <returns></returns>
  141. public static string CompressUrl(this UrlHelper urlHelper, string absoluteUrlEncoded)
  142. {
  143. string cacheKey = "tinyurl:" + absoluteUrlEncoded.ToLower();
  144. Cache cache = urlHelper.RequestContext.HttpContext.Cache;
  145. string url = (string)cache[cacheKey];
  146. if (string.IsNullOrEmpty(url))
  147. {
  148. try
  149. {
  150. const string urlToSendTo = "http://is.gd/api.php?longurl={0}";
  151. WebClient wc = new WebClient();
  152. url = wc.DownloadString(string.Format(urlToSendTo, absoluteUrlEncoded));
  153. cache.Add(cacheKey, url, null, DateTime.Now.AddHours(1), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
  154. }
  155. catch
  156. {
  157. url = absoluteUrlEncoded;
  158. }
  159. }
  160. return url;
  161. }
  162. public static string ActionEx(this UrlHelper helper, string action, object routeValues)
  163. {
  164. var values = routeValues == null ?
  165. new RouteValueDictionary() :
  166. new RouteValueDictionary(routeValues);
  167. values.Add("action", action);
  168. values.Add("controller", helper.RequestContext.RouteData.Values["controller"]);
  169. var pathData = helper.RouteCollection.GetPath(helper.RequestContext, values);
  170. var url = pathData.VirtualPath;
  171. return IsAbsolute(url) ? url : "/" + url;
  172. }
  173. #region Private Methods
  174. private static VirtualPathData GetPath(
  175. this RouteCollection routes,
  176. RequestContext requestContext,
  177. RouteValueDictionary values)
  178. {
  179. foreach (RouteBase r in routes)
  180. {
  181. VirtualPathData pathData = r.GetVirtualPath(requestContext, values);
  182. if (pathData != null)
  183. {
  184. return pathData;
  185. }
  186. }
  187. throw new ArgumentException("Invalid values for building URL.");
  188. }
  189. private static bool IsAbsolute(string url)
  190. {
  191. return
  192. url.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase) ||
  193. url.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase);
  194. }
  195. #endregion
  196. }
  197. }