Ad

How To Programmatically Set Template For Html Rendered With ServiceStack Markdown?

- 1 answer

I'm using the Razor/Markdown engine from ServiceStack and am having a bit of difficulty applying my own custom Template/Layout to some rendered Markdown. The Markdown content renders perfectly, I just want to inject that into a Template/Layout file of my choice.

Currently I have this (which works perfectly) :

var rootPath = HttpContext.Current.Server.MapPath("~/");
var markdownPath = Path.Combile(rootPath, "NotFound.md");
var format = new MarkdownFormat();
var markdownContent = File.ReadAllText(markdownPath);
const string pageTitle = "Not Found";
var page = new MarkdownPage(format, rootPath, pageTitle, markdownContent);
format.AddPage(page);
var scopeArgs = new Dictionary<string, object>();
var html = format.RenderDynamicPageHtml(pageTitle, scopeArgs);

Now I have a layout file I wish to use located at "~/ErrorLayout.cshtml", however I have no idea how to inject it. At first I thought to set the Template variable on MarkdownPage to my Layout file's path, however that didn't work. I then tried to call format.AddLayout() and unfortunately that threw an exception.

Any help would be highly appreciated, feel free to ask for any further clarification from myself if I have not made what I am trying to do clear.

Ad

Answer

So I have solved the problem, however I am uncertain if what I have done is the correct method or not, however it works and no exceptions are thrown. Perhaps somebody with a bit more knowledge could correct me if I have done this incorrectly (so I will leave this question open for a couple days before accepting my answer).

I have created a new class which implements the IVirtualPathProvider interface, and named it PathProvider

I have also created a class which implements the IVirtualFile interface, and named it VirtualFile

I then set the VirtualPathProvider in my instance of MarkdownFormat to a new instance of PathProvider. I then set the Template variable on my instance of Markdownpage to a relative path to the cshtml layout/template file I want to make use of, and within the two classes I mentioned before, returned related content for this Template when requested to do so.

My code now looks like this (in case somebody else has the same problem as me) :

var rootPath = HttpContext.Current.Server.MapPath("~/");
if (contents == null)
{
    var notFoundPath = Path.Combine(rootPath, "NotFound.md");
    contents = File.ReadAllText(notFoundPath);
}
var format = new MarkdownFormat
{
    VirtualPathProvider = new PathProvider()
};
const string pageTitle = "Not Found";
var page = new MarkdownPage(format, rootPath, pageTitle, contents)
{
    Template = "~/_Layout.cshtml"
};
 format.AddPage(page);
var view = new Dictionary<string, object>();
var html = format.RenderDynamicPageHtml(pageTitle, view);

My PathProvider class looks like this :

public class PathProvider : IVirtualPathProvider
{
    public IVirtualDirectory RootDirectory { get; private set; }
    public string VirtualPathSeparator { get; private set; }
    public string RealPathSeparator { get; private set; }
    public string CombineVirtualPath(string basePath, string relativePath)
    {
        throw new NotImplementedException();
    }

    public bool FileExists(string virtualPath)
    {
        throw new NotImplementedException();
    }

    public bool DirectoryExists(string virtualPath)
    {
        throw new NotImplementedException();
    }

    public IVirtualFile GetFile(string virtualPath)
    {
        return new VirtualFile(this, virtualPath);
    }

    public string GetFileHash(string virtualPath)
    {
        throw new NotImplementedException();
    }

    public string GetFileHash(IVirtualFile virtualFile)
    {
        throw new NotImplementedException();
    }

    public IVirtualDirectory GetDirectory(string virtualPath)
    {
        throw new NotImplementedException();
    }

    public IEnumerable<IVirtualFile> GetAllMatchingFiles(string globPattern, int maxDepth = 2147483647)
    {
        throw new NotImplementedException();
    }

    public bool IsSharedFile(IVirtualFile virtualFile)
    {
        throw new NotImplementedException();
    }

    public bool IsViewFile(IVirtualFile virtualFile)
    {
        throw new NotImplementedException();
    }
}

and finally my VirtualFile class :

public class VirtualFile : IVirtualFile
{
    public IVirtualDirectory Directory { get; private set; }
    public string Name { get; private set; }
    public string VirtualPath { get; private set; }
    public string RealPath { get; private set; }
    public bool IsDirectory { get; private set; }
    public DateTime LastModified { get; private set; }
    public IVirtualPathProvider VirtualPathProvider { get; private set; }
    public string Extension { get; private set; }

    public VirtualFile(IVirtualPathProvider virtualPathProvider, string filePath)
    {
        VirtualPathProvider = virtualPathProvider;
        VirtualPath = filePath;
        RealPath = HttpContext.Current.Server.MapPath(filePath);
    }

    public string GetFileHash()
    {
        throw new NotImplementedException();
    }

    public Stream OpenRead()
    {
        throw new NotImplementedException();
    }

    public StreamReader OpenText()
    {
        throw new NotImplementedException();
    }

    public string ReadAllText()
    {
        return File.ReadAllText(RealPath);
    }
}
Ad
source: stackoverflow.com
Ad