soundaranbu/Razor.Templating.Core

Accept ViewData and ViewBag as Anonymous object

Closed this issue · 2 comments

Hi,

Found your library after coming from RazorLight for which I was so disappointed by the author who has been condescending and unpleasant relatively to a simple question I was asking.
I thought such library was quite difficult to write but I found yours is such easy to use and feature complete (views where you expect them to be, Layout, ViewImports)... Really, this is a great job. Thank you for this work.

I just wanted to let you know some simple addition I made to have a more straightforward ViewBag that I could set up as an anonymous object. Maybe this is something you will want to add in your lib. I did it with a static wrapper:

public static class RazorTemplateEngineWrapper
{
    public async static Task<string> RenderAsync<TModel>([DisallowNull] string viewName, [DisallowNull] TModel model, [DisallowNull] object viewBag)
    {
        return await RazorTemplateEngine.RenderAsync(viewName, model, AnonymousTypeToDictionary(viewBag));
    }

    private static Dictionary<string, object> AnonymousTypeToDictionary(object obj)
    {
        var result = new Dictionary<string, object>();

        if (obj != null)
        {
            foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(obj))
            {
                result.Add(pd.Name, pd.GetValue(obj));
            }
        }

        return result;
    }
}

Note that instead of Dictionary<string, object>, if the code was using a IDictionary<string, object?> it would be more exact I think.

I'm using it like this:

var body = await RazorTemplateEngineWrapper.RenderAsync("~/Views/EmailTemplates/EmailConfirm.text.cshtml", model, new { Message = message });

Thanks again.

Hi @cadilhac, glad to know that you find this library helpful and easy to use.

and for your suggestion, yes, it's a good to have feature and will be more intuitive for the users. I'm thinking of implementing it in the upcoming versions.

Keep supporting. Thanks!

Initially I planned to add this to the library but I'm hesitant to allow anonymous type in the argument. But I agree that it's much nicer to read.

However, the new C# features like Target-typed new expression and collection initializer allows us to simplify the dictionary initialization like:

var html = await RazorTemplateEngine.RenderAsync("/Views/ExampleView.cshtml", model, new()
{
    ["Value1"] = "1",
    ["Value2"] = "2"
});

Thanks for the suggestion anyway and people can use this extension method if they want!