HiveHicks
HiveHicks

Reputation: 2334

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

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 in a static files (for some reason, these files must be placed in ~/Content folder). Is there a way that I can tell in my view something like

<% Html.Include("~/Content/snippet.html") %>   // not a real code

?

Upvotes: 15

Views: 34195

Answers (6)

Ogglas
Ogglas

Reputation: 69968

For ASP .NET Core 3.1 Razor page you can do it like this:

@Html.Raw(System.IO.File.ReadAllText("wwwroot/Content/snippet.html"));

See documentation regarding static files here:

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/static-files?view=aspnetcore-3.1

Upvotes: 0

Motlicek Petr
Motlicek Petr

Reputation: 776

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:

/// <summary>
/// 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
/// </summary>
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);

    /// <summary>
    /// Finds all tilda paths in the content and replace it for current path
    /// </summary>
    /// <param name="content"></param>
    /// <returns></returns>
    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

Upvotes: 5

Darin Dimitrov
Darin Dimitrov

Reputation: 1038830

You are better off using a partial view (even if it only contains static text) and include it with the Html.Partial helper. But if you insist:

<%= File.ReadAllText(Server.MapPath("~/Content/snippet.html")) %>

Upvotes: 22

Olivier de Rivoyre
Olivier de Rivoyre

Reputation: 1597

If you are in .Net MVC 5 and want to include a HTML file a partial file without having Razor that render it:

@Html.Raw(File.ReadAllText(Server.MapPath("~/Views/Shared/ICanHaz.html")))

Upvotes: 17

T Gupta
T Gupta

Reputation: 957

To include static html file into a MVC View goes like this:

<!-- #include virtual="~\Content\snippet.htm" -->

Upvotes: 0

AndyM
AndyM

Reputation: 1200

Is there a reason you are holding the content in an HTML file rather than a partial view?

If you create a file called snippet.ascx in your Views/Shared folder you can import the content of that snippet.ascx file into any view by using <% Html.RenderPartial("snippet"); %>

Upvotes: 0

Related Questions