15

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

?

6 Answers 6

22

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")) %>
Sign up to request clarification or add additional context in comments.

3 Comments

There's a particular reason for storing snippets in Content folder. We've got multiple instances of the same application, and each instance has access to the same dlls which are stored in one place. To customize each of the instance we can only change items in Content folder.
Your answer seems just what I need. Thanks!
Your answer was Grate except that File needs to place IO.File :)
17

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")))

Comments

5

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

Comments

0

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"); %>

2 Comments

Yep, there's a reason for that.
Like working together with someone who has no visual studio :-) This is pretty useful for quickly integrating vanilla html into a MVC solution.
0

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

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

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.