Including static html file from ~/Content into ASP.NET MVC view

后端 未结 6 1186
长情又很酷
长情又很酷 2020-12-16 14:18

I\'ve got master page in my project, which contains some information about site copyright and some contact info in it. I\'d like to take it out of master page and place it i

6条回答
  •  天涯浪人
    2020-12-16 14:59

    Use your own view engine

    using

    @Html.Partial("_CommonHtmlHead")
    

    as

    /Views/Shared/_CommonHtmlHead.html
    

    or

    /Views/MyArea/Shared/_CommonHtmlHead.htm
    

    is the best for me.

    Creating your own view engine for this by using the System.Web.Mvc.VirtualPathProviderViewEngine ascending class seems to be relatively easy:

    /// 
    /// Simple render engine to load static HTML files, supposing that view files has the html/htm extension, supporting replacing tilda paths (~/MyRelativePath) in the content
    /// 
    public class HtmlStaticViewEngine : VirtualPathProviderViewEngine
    {
        private static readonly ILog _log = LogManager.GetLogger(typeof (HtmlStaticViewEngine));
    
        protected readonly DateTime? AbsoluteTimeout;
        protected readonly TimeSpan? SlidingTimeout;
        protected readonly CacheItemPriority? Priority;
    
        private readonly bool _useCache;
    
        public HtmlStaticViewEngine(TimeSpan? slidingTimeout = null, DateTime? absoluteTimeout = null, CacheItemPriority? priority = null)
        {
            _useCache = absoluteTimeout.HasValue || slidingTimeout.HasValue || priority.HasValue;
    
            SlidingTimeout = slidingTimeout;
            AbsoluteTimeout = absoluteTimeout;
            Priority = priority;
    
            AreaViewLocationFormats = new[]
            {
                "~/Areas/{2}/Views/{1}/{0}.html",
                "~/Areas/{2}/Views/{1}/{0}.htm",
                "~/Areas/{2}/Views/Shared/{0}.html",
                "~/Areas/{2}/Views/Shared/{0}.htm"
            };
            AreaMasterLocationFormats = new[]
            {
                "~/Areas/{2}/Views/{1}/{0}.html",
                "~/Areas/{2}/Views/{1}/{0}.htm",
                "~/Areas/{2}/Views/Shared/{0}.html",
                "~/Areas/{2}/Views/Shared/{0}.htm"
            };
            AreaPartialViewLocationFormats = new[]
            {
                "~/Areas/{2}/Views/{1}/{0}.html",
                "~/Areas/{2}/Views/{1}/{0}.htm",
                "~/Areas/{2}/Views/Shared/{0}.html",
                "~/Areas/{2}/Views/Shared/{0}.htm"
            };
    
            ViewLocationFormats = new[]
            {
                "~/Views/{1}/{0}.html",
                "~/Views/{1}/{0}.htm",
                "~/Views/Shared/{0}.html",
                "~/Views/Shared/{0}.htm"
            };
            MasterLocationFormats = new[]
            {
                "~/Views/{1}/{0}.html",
                "~/Views/{1}/{0}.htm",
                "~/Views/Shared/{0}.html",
                "~/Views/Shared/{0}.htm"
            };
            PartialViewLocationFormats = new[]
            {
                "~/Views/{1}/{0}.html",
                "~/Views/{1}/{0}.htm",
                "~/Views/Shared/{0}.html",
                "~/Views/Shared/{0}.htm"
            };
    
            FileExtensions = new[]
            {
                "html",
                "htm",
            };
        }
    
        protected virtual string GetContent(string viewFilePath)
        {
            string result = null;
            if (!string.IsNullOrWhiteSpace(viewFilePath))
            {
                if (_useCache)
                {
                    result = TryCache(viewFilePath);
                }
    
                if (result == null)
                {
                    using (StreamReader streamReader = File.OpenText(viewFilePath))
                    {
                        result = streamReader.ReadToEnd();
                    }
    
                    result = ParseContent(result);
    
                    if (_useCache)
                    {
                        CacheIt(viewFilePath, result);
                    }
                }
            }
    
            return result;
        }
    
        static readonly Regex TildaRegularExpression = new Regex(@"~/", RegexOptions.Compiled);
    
        /// 
        /// Finds all tilda paths in the content and replace it for current path
        /// 
        /// 
        /// 
        protected virtual string ParseContent(string content)
        {
            if (String.IsNullOrWhiteSpace(content))
            {
                return content;
            }
    
            string absolutePath = VirtualPathUtility.ToAbsolute("~/");
    
            string result = TildaRegularExpression.Replace(content, absolutePath);
            return result;
        }
    
        protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
        {
            HttpContextBase httpContextBase = controllerContext.RequestContext.HttpContext;
    
            string filePath = httpContextBase.Server.MapPath(partialPath);
            string content = GetContent(filePath);
            return new StaticView(content);
        }
    
        protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
        {
            HttpContextBase httpContextBase = controllerContext.RequestContext.HttpContext;
            
            string result = null;
            if (!string.IsNullOrWhiteSpace(masterPath))
            {
                string filePath = httpContextBase.Server.MapPath(masterPath);
                result = GetContent(filePath);
            }
    
            string physicalViewPath = httpContextBase.Server.MapPath(viewPath);
            result += GetContent(physicalViewPath);
            return new StaticView(result);
        }
    
        protected virtual string TryCache(string filePath)
        {
            HttpContext httpContext = HttpContext.Current;
            if (httpContext != null && httpContext.Cache != null)
            {
                string cacheKey = CacheKey(filePath);
                return (string)httpContext.Cache[cacheKey];
            }
            return null;
        }
    
        protected virtual bool CacheIt(string filePath, string content)
        {
            HttpContext httpContext = HttpContext.Current;
            if (httpContext != null && httpContext.Cache != null)
            {
                string cacheKey = CacheKey(filePath);
                httpContext.Cache.Add(cacheKey, content, new CacheDependency(filePath), AbsoluteTimeout.GetValueOrDefault(Cache.NoAbsoluteExpiration), SlidingTimeout.GetValueOrDefault(Cache.NoSlidingExpiration), Priority.GetValueOrDefault(CacheItemPriority.AboveNormal), CacheItemRemovedCallback);
                return true;
            }
    
            return false;
        }
    
        protected virtual string CacheKey(string serverPath)
        {
            return serverPath;
        }
    
        protected virtual void CacheItemRemovedCallback(string key, object value, CacheItemRemovedReason reason)
        {
            _log.InfoFormat("CacheItemRemovedCallback(string key='{0}', object value = ..., {1} reason={2})", key, reason.GetType().Name, reason);
        }
    }
    
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            ViewEngines.Engines.Add(new HtmlStaticViewEngine(new TimeSpan(12,0,0,0)));
        }
    }
    
    public class StaticView : IView
    {
        private readonly string _text;
    
        public StaticView(string text)
        {
            _text = text;
        }
    
        public void Render(ViewContext viewContext, TextWriter writer)
        {
            if (! string.IsNullOrEmpty(_text))
            {
                writer.Write(_text);
            }
        }
    }
    

    NOTE: This code is tested only with simple usage for rendering partial views

提交回复
热议问题