RazorEngine string layouts and sections?

前端 未结 3 955
[愿得一人]
[愿得一人] 2020-12-24 03:09

I use razor engine like this:

public class EmailService : IService
{
    private readonly ITemplateService templateService;

    public EmailService(ITemplat         


        
3条回答
  •  悲&欢浪女
    2020-12-24 03:39

    Turns out after some digging that layouts are supported, we just have to declare them with _Layout instead of Layout

    As for the embedded resource issue, I implemented the following ITemplateResolver

    using System;
    using System.IO;
    using System.Reflection;
    using Bruttissimo.Common;
    using RazorEngine.Templating;
    
    namespace Website.Extensions.RazorEngine
    {
        /// 
        /// Resolves templates embedded as resources in a target assembly.
        /// 
        public class EmbeddedTemplateResolver : ITemplateResolver
        {
            private readonly Assembly assembly;
            private readonly Type type;
            private readonly string templateNamespace;
    
            /// 
            /// Specify an assembly and the template namespace manually.
            /// 
            /// The assembly where the templates are embedded.
            /// 
            public EmbeddedTemplateResolver(Assembly assembly, string templateNamespace)
            {
                if (assembly == null)
                {
                    throw new ArgumentNullException("assembly");
                }
                if (templateNamespace == null)
                {
                    throw new ArgumentNullException("templateNamespace");
                }
                this.assembly = assembly;
                this.templateNamespace = templateNamespace;
            }
    
            /// 
            /// Uses a type reference to resolve the assembly and namespace where the template resources are embedded.
            /// 
            /// The type whose namespace is used to scope the manifest resource name.
            public EmbeddedTemplateResolver(Type type)
            {
                if (type == null)
                {
                    throw new ArgumentNullException("type");
                }
                this.assembly = Assembly.GetAssembly(type);
                this.type = type;
            }
    
            public string Resolve(string name)
            {
                if (name == null)
                {
                    throw new ArgumentNullException("name");
                }
                Stream stream;
                if (templateNamespace == null)
                {
                    stream = assembly.GetManifestResourceStream(type, "{0}.cshtml".FormatWith(name));
                }
                else
                {
                    stream = assembly.GetManifestResourceStream("{0}.{1}.cshtml".FormatWith(templateNamespace, name));
                }
                if (stream == null)
                {
                    throw new ArgumentException("EmbeddedResourceNotFound");
                }
                string template = stream.ReadFully();
                return template;
            }
        }
    }
    

    Then you just wire it like this:

        internal static ITemplateService InstanceTemplateService()
        {
            TemplateServiceConfiguration configuration = new TemplateServiceConfiguration
            {
                Resolver = new EmbeddedTemplateResolver(typeof(EmailTemplate))
            };
            ITemplateService service = new TemplateService(configuration);
            return service;
        }
    

    The type you pass is just for referencing the assembly and namespace where the resources are embedded.

    namespace Website.Domain.Logic.Email.Template
    {
        /// 
        /// The purpose of this class is to expose the namespace of razor engine templates in order to
        /// avoid having to hard-code it when retrieving the templates embedded as resources.
        /// 
        public sealed class EmailTemplate
        {
        }
    }
    

    One last thing, in order to have the templates resolved with our resolver we have to resolve them like this:

    ITemplate template = templateService.Resolve(templateName, model);
    string body = template.Run();
    return body;
    

    .Run is just a simple extension method since I can't find any use for a ViewBag.

    public static class ITemplateExtensions
    {
        public static string Run(this ITemplate template)
        {
            ExecuteContext context = new ExecuteContext();
            string result = template.Run(context);
            return result;
        }
    }
    

    UPDATE

    Here are the missing extensions

        public static string FormatWith(this string text, params object[] args)
        {
            return string.Format(text, args);
        }
    
        public static string ReadFully(this Stream stream)
        {
            using (StreamReader reader = new StreamReader(stream))
            {
                return reader.ReadToEnd();
            }
        }
    

提交回复
热议问题