2
Vote

Using RazorGenerator in a WinRT project

description

I am producing some HTML content for the share charm in WinRT. So I need to precompile the cshtml to .cs in my WinRT project. I'm not entirely clear over the entire process that needs to be used here, but as I understand it I need to install
the RazorGenerator visual studio extension. Unfortunately I can only install that into visual studio 2010?

How do I get it installed into visual studio 2011, so that I can select a custom tool of RazorGenerator?

Secondly RazorGenerator.Templating isn't able to be installed in a WinRT project. So I decompiled the class and I can build that class, but there are some changes required in the write function. It should look like this:


public void Write(object value)
{
if (value == null)
    return;

if NETFX_CORE

MethodInfo method = null;

var methods = value.GetType().GetTypeInfo().GetDeclaredMethods("ToString");

if (methods != null)
{
    foreach (MethodInfo methodInfo in methods)
    {
        if (methodInfo.GetParameters().Count() == 1 && methodInfo.GetParameters()[0].ParameterType == typeof (IFormatProvider))
        {
            method = methodInfo;
        }
    }
}

else

MethodInfo method = value.GetType().GetMethod("ToString", new Type[1]
{
typeof (IFormatProvider)
});

endif

string textToAppend;
if (method == (MethodInfo)null)
    textToAppend = value.ToString();
else
    textToAppend = (string)method.Invoke(value, new object[1]
{
(object) CultureInfo.InvariantCulture
});
this.WriteLiteral(textToAppend);
}


And then it works fine. Hopefully a WinRT specific version of the nuget project can be built at some point, but in the meantime if I include that class myself, I will be fine. Is just a matter of getting the razor generator functioning. Hope
someone is able to help with that.

Thanks,

Stefan

comments

StefanOlson wrote May 9, 2012 at 5:51 PM

Have done some additional work on testing with WinRT. Because many of the API methods are asynchronous, there are a few more changes that need to be made. The following functions needs to be made async aware (ideally, you will probably have a separate Async version of the function, but I'm not sure that would work in this situation)
public async virtual Task<bool> Execute()

public async Task<string> TransformText()

and the last line of TransformText needs to be changed to:
return await this.Layout.TransformText();

Then the generated code needs couple of changes, the Execute function signature needs to change to :
public async override Task<bool> Execute()

and there needs to be a return true at the end so that the function is awaitable.

Most of these can be #ifdef'd if necessary I guess.

I just took a look at the currently checked in source code for RazorTemplateBase.cs. It is substantially different than the one that I decompiled having installed the nugget package. So I have tested that one, and updated it to work under WinRT. Unfortunately, like most of my cross-platform code these days, it's a big mess of #ifdef :-)

using System;
using System.Globalization;
using System.Text;

if NETFX_CORE

using System.Threading.Tasks;

endif

namespace RazorGenerator.Templating
{
public class RazorTemplateBase
{
    private string _content;
    public RazorTemplateBase Layout { get; set; }

    private readonly StringBuilder _generatingEnvironment = new StringBuilder();

if NETFX_CORE

    public async virtual Task<bool> Execute()

else

    public virtual void Execute()

endif

    {

if NETFX_CORE

        return true;

endif

    }

    public void WriteLiteral(string textToAppend)
    {
        if (String.IsNullOrEmpty(textToAppend))
        {
            return;
        }
        _generatingEnvironment.Append(textToAppend);
    }

    public void Write(object value)
    {
        if ((value == null))
        {
            return;
        }

        WriteLiteral(Convert.ToString(value, CultureInfo.InvariantCulture));
    }

    public string RenderBody()
    {
        return _content;
    }

if NETFX_CORE

    public async virtual Task<string> TransformText()

else

    public string TransformText()

endif

    {
        Execute();
        if (Layout != null)
        {
            Layout._content = _generatingEnvironment.ToString();

if NETFX_CORE

            return await Layout.TransformText();

else

            return Layout.TransformText();

endif

        }
        return _generatingEnvironment.ToString();
    }
}
}

...Stefan

StefanOlson wrote May 9, 2012 at 5:53 PM

Having thought about it, I have changed the method name TransformText to TransformTextAsync for the NETFX_CORE build because that more clearly indicates that it is awaitable.

...Stefan

StefanOlson wrote May 9, 2012 at 6:43 PM

New, and hopefully final update, the Execute function needs to be awaited. So here's the final code:
using System;
using System.Globalization;
using System.Text;

if NETFX_CORE

using System.Threading.Tasks;

endif

namespace RazorGenerator.Templating
{
public class RazorTemplateBase
{
    private string _content;
    public RazorTemplateBase Layout { get; set; }

    private readonly StringBuilder _generatingEnvironment = new StringBuilder();

if NETFX_CORE

    public async virtual Task<bool> Execute()

else

    public virtual void Execute()

endif

    {

if NETFX_CORE

        return true;

endif

    }

    public void WriteLiteral(string textToAppend)
    {
        if (String.IsNullOrEmpty(textToAppend))
        {
            return;
        }
        _generatingEnvironment.Append(textToAppend);
    }

    public void Write(object value)
    {
        if ((value == null))
        {
            return;
        }

        WriteLiteral(Convert.ToString(value, CultureInfo.InvariantCulture));
    }

    public string RenderBody()
    {
        return _content;
    }

if NETFX_CORE

    public async virtual Task<string> TransformTextAsync()

else

    public string TransformText()

endif

    {

if NETFX_CORE

        await 

endif

            Execute();
        if (Layout != null)
        {
            Layout._content = _generatingEnvironment.ToString();

if NETFX_CORE

            return await Layout.TransformTextAsync();

else

            return Layout.TransformText();

endif

        }
        return _generatingEnvironment.ToString();
    }
}
}

pranavkm wrote Jan 24 at 4:21 AM

Do you think you could send this as a patch file or a pull request?