Using Razor Layouts With Insite Emails


Insite's EmailService allows a developer to easily send emails to a customer whenever they perform an action on the system. This EmailService utilizes the RazorEngine in order to parse HTML and generate rich content emails for delivery. On a recent project, I had many scenarios where an email was being sent to the customer. All of the emails contained a common look and feel, including a fully rendered header and footer. In this post, I will go over the process I followed in order to allow for the use of the standard Layout property in the Razor template for emails.

When the email templates were first created, I immediately tried to utilize the standard Layout property for a Razor view in order specify which content it should use.

Layout File:





    
    @ViewBag.Title
    


    
This is the common header for all of the emails sent from Insite
@RenderBody()
This is the common footer for all of the emails sent from Insite

Email Template

@{
    Layout = "~/Views/DefaultEmails/MainEmailLayout.cshtml";
}


Unfortunately, this immediately started generating errors in the EmailService.

Error

 

Turns out, the relative path specified is a part of the Insite web application, and isn't resolvable from the context in which the EmailService executes. After looking through the OOTB EmailService code, I was able to determine that the content parser could be customized.

 

public class EmailServiceRio : EmailService
{
    public EmailServiceRio(IEmailTemplateUtilities emailTemplateUtilities, IContentManagerUtilities contentManagerUtilities, IEntityTranslationService entityTranslationService)
        : base(emailTemplateUtilities, contentManagerUtilities, entityTranslationService)
    {
    }

    // Insite apparently has issue with using Layout in the Razor.
    // We are overriding their parse template method to manually resolve and inject the Layout content.
    public override string ParseTemplate(string template, ExpandoObject model, string templateName)
    {
        #region Customize - Allow for Layouts in templates

        var noLineTemplate = template.Replace("\r", "").Replace("\n", "").Replace("\t", "");

        // @{    Layout = "~/Views/DefaultEmails/EmailMainLayout.cshtml"; }
        var layoutRegex = new Regex("@{\\s*?Layout\\s*?=\\s*?\"(?.*?)\";\\s*?}");

        // If we are using a layout
        if (layoutRegex.IsMatch(noLineTemplate))
        {
            var filePath = layoutRegex.Match(noLineTemplate).Groups["filePath"].Value;

            noLineTemplate = layoutRegex.Replace(noLineTemplate, string.Empty);

            var layoutLines = string.Join(Environment.NewLine, File.ReadLines(HostingEnvironment.MapPath(filePath)).ToList());

            template = layoutLines.Replace("@RenderBody()", noLineTemplate);
        }

        #endregion

        var content = Razor.Parse(template, model, templateName);

        return content;
    }
}
The above code uses a Regular Expression and some basic string manipulation magic in order to detect and resolve a layout file being referenced in a email template. As mentioned above, the normal execution context of the EmailService means that it will not have access to a web based relative path to retrieve the content. In order to get the file, I need to get the fully qualified path for the layout file (e.g. C:\Projects\InsiteCommerce-4.2.0\InsiteCommerce.Web\Views\DefaultEmail\MainEmailLayout.cshtml). Once I have the fully qualified path for the layout, I can manually read the file off of the server. By simply replacing "@RenderBody()" from the layout file with the original template content, I now have a fully formed email ready to be parsed and delivered.

Email

There you have it. With the help of regular expressions and a some string manipulations, I now how a solution that allows me to utilize Razor Layouts in my email templates, saving me a lot of work when modifying the content of my emails.

The example used in this blog post has been implemented on Insite version 4.2.0.34172, a MVC application running on .NET Framework 4.5.2.
Tags: email, Net, Insite;

SEARCH ARTICLES

CATEGORIES

Sitecore 144
Commerce 100
Web Development 100
Sitecore Commerce 83
Sitecore Experience Commerce 9 64
Sitecore Experience Commerce 59
Content Management 55
eCommerce 48
B2B eCommerce 42
Sitecore Experience Platform 39
Sitecore Platinum Partner 39
Architecture 34
Insite 29
User Experience 26
Strategy 22
B2C eCommerce 21
B2B Commerce Blogs 21
commerceconnect 21
CloudCraze 20
SaaS (Software as a Service) 20
Cloud 17
Commerce Server 17
Salesforce B2B Commerce Cloud 16
Mobile 13
Search 13
Plugins 12
Analytics 12
Application Development 12
Digital Transformation 11
Sitecore Symposium 11
SPEAK 10
Helix 10
DMS 8
Social 8
Business Process 7
Authentication 7
5 Reasons 7
BI and Big Data 6
Data Visualization 6
Sitecore Presentation 6
Coveo 6
NET Development 5
Microsoft Azure 5
Automation 5
Front-End Development 4
SaaS (Software as a Service) 4
Digital Strategy 4
Brightcove 4
Press Release 4
Avalara Tax 3
Sitecore Experience Accelerator (SXA) 3
Sitecore Layouts 3
Video 3
SPE 3
Multi-site 3
Multi-lingual 3
Accessibility 3
Habitat 3
Vault 3
Identity 2
Managed Services 2
CDN 2
SMB 2
Cryptocurrency 2
Sitecore Forms 2
Sitecore Experience Commerce 9 Promotions 2
Uncategorized 2
EXM 2
Conversational Commerce 2
Sitecore SaaS 2
Security 2
Unit Testing 2
Headless Architecture 2
Sitecore Experience Awards 2
Google 1
Content Delivery Network 1
Configure Price Quote 1
CPQ 1
Blockchain 1
Coupons 1
Sitecore Rss 1
Artificial Intelligence 1
Machine Learning 1
Okta 1
RFP Process 1
NoSQL 1
Flex Accelerator for Sitecore 1
Reviews 1
SEO 1
Page Labels 1