RazorEngine and parsing physical view files always

2019-03-11 04:12发布

I have the following RazorEngine call:

public class RazorEngineRender
{
    public static string RenderPartialViewToString(string templatePath, string viewName, object model)
    {            
        string text = System.IO.File.ReadAllText(Path.Combine(templatePath, viewName));
        string renderedText = Razor.Parse(text, model);
        return renderedText;
    }
}

This is called from:

_emailService.Render(TemplatePath, "Email.cshtml", new { ActivationLink = activationLink });

I also have this view file (email.cshtml):

    <div>
      <div>
            Link: <a href="@Model.ActivationLink" style="color:#666" target="_blank">@Model.ActivationLink</a>
      </div>
    </div>

When the call to Razor.Parse() occurs, I always get a: Unable to compile template. Check the Errors list for details.

The error list is:

error CS1061: 'object' does not contain a definition for 'ActivationLink' and no extension method 'ActivationLink' accepting a first argument of type 'object' could be found 

I've tried everything under the sun, including trying a concrete type as opposed to anonymous type, declaring the @Model line at the top of the view file but no luck. I'm wondering if the library is at fault or definately me?

By the way, the razorengine I am referring to is available here at codeplex: RazorEngine

3条回答
对你真心纯属浪费
2楼-- · 2019-03-11 04:48

If you make the call like so:

Razor.Parse(System.IO.File.ReadAllText(YourPath), 
            new { ActivationLink = activationLink });

That should give you the correct output. But after I see your method posted above I'll be able to make a determination where the problem lies.

Update

Change your method to the following:

public class RazorEngineRender {
    public static string RenderPartialViewToString<T>(string templatePath, string viewName, T model) {            
        string text = System.IO.File.ReadAllText(Path.Combine(templatePath, viewName));
        string renderedText = Razor.Parse(text, model);
        return renderedText;
    }
}

and you can call it like you do above.

The reason it doesn't work is because you're telling the Parser that the model is of type object rather than passing in what type it really is. In this case an anonymous type.

查看更多
【Aperson】
3楼-- · 2019-03-11 04:54

Here are a few hints you might try:

  1. Make your razor view strongly typed to a model:

    @model Foo
    <div>
        <div>
            Link: 
            <a href="@Model.ActivationLink" style="color:#666" target="_blank">
                @Model.ActivationLink
            </a>
        </div>
    </div>
    
  2. When rendering it pass a Foo model:

    _emailService.Render(
        TemplatePath, 
        "Email.cshtml", 
        new Foo { ActivationLink = activationLink }
    )
    
  3. If you are trying to send emails from your Views make sure you checkout Postal before reinventing something.

查看更多
Lonely孤独者°
4楼-- · 2019-03-11 04:59

The accepted answer was perfect in 2011 (I believe pre-v3 of RazorEngine) but this code is now marked as obsolete in latest version (in time of typing it is 3.7.3).

For newer version your method can be typed like this:

public static string RenderPartialViewToString<T>(string templatePath, string templateName, string viewName, T model)
        {
            string template = File.ReadAllText(Path.Combine(templatePath, viewName));
            string renderedText = Engine.Razor.RunCompile(template, templateName, typeof(T), model);
            return renderedText;
        }

and in order for it to work you need to add

using RazorEngine.Templating;
查看更多
登录 后发表回答