We’ve been using ServiceStacks markdown features to generate text and email notification text / html. So far the implementation was simple. We pass in pre-defined properties (that were the same for each type of notification). There was no variance (We passed user first name, last name, email, phone, title, etc…).
Now we need to pass a “Property Bag” of information (maybe a dictionary or a list of some custom object) so that different entities generate customized text. But when I try to use the @foreach, it just prints the literal @foreach in the email that is sent out.
Maybe I am misunderstanding the context in which it’s running in. Or the feature that I’m using (MarkdownPagFormat vs Markdown Razor?). Here is how our app is setup:
First note that this might have been built before the new Razor Markdown was released (it was about a year ago, maybe a little less)
In Startup, we register TemplatePagesFeature
Plugins.Add(new TemplatePagesFeature()) // I don't remember why I had to do this, but it seems like this was required, even though the main Startup app doesn't really generate any of this, the Logic project does
(Ignore the obsolescence for now, just know that everything works as expected. I realize it has been replaced with SharpPagesFeature).
In our LENSSX.Logic (core business logic) project, we have a NotificationBuilder.cs, and a Templates folder where we house the HTML / md templates.
NotificationBuilder.cs
namespace LENSSX.Logic.Services
{
public class NotificationBuilder
{
private ScriptContext Context { get; }
public NotificationBuilder()
{
Context = new ScriptContext()
{
PageFormats = {new MarkdownPageFormat() },
VirtualFiles = new FileSystemVirtualFiles("Templates".MapNetCorePath())
}.Init();
}
public string GetTextNotification(Notification notification)
{
var textPage = Context.GetPage("EntityNotifications\\EntityNotificationText");
var text = new PageResult(textPage)
{
Args =
{
["notification"] = notification.Data.Notification,
["triggeringUser"] = notification.Data.TriggeringUser
}
}.Result;
return text;
}
public class DataBag
{
public string Key { get; set; }
public string Value { get; set; }
}
public IEmailTemplate GetEmailNotification(Notification notification)
{
var emailPage = Context.GetPage("EntityNotifications\\EntityNotificationEmail");
var textEmail = new PageResult(emailPage)
{
Args =
{
["notification"] = notification.Data.Notification,
["triggeringUser"] = notification.Data.TriggeringUser
}
}.Result;
var htmlEmail = new PageResult(emailPage)
{
Layout = "Layout",
PageTransformers = {MarkdownPageFormat.TransformToHtml},
Args =
{
["notification"] = notification.Data.Notification,
["triggeringUser"] = notification.Data.TriggeringUser,
["dataBag"] = new List<DataBag>()
{
new DataBag()
{
Key = "Test Key 1",
Value = "Test Value 1"
},
new DataBag()
{
Key = "Test Key 1",
Value = "Test Value 1"
}
}
}
}.Result;
return new NotificationEmailTemplateModel()
{
PlainText = textEmail,
Html = htmlEmail
};
}
}
}
Example MD where I’m attempting to use the dataBag (EntityNotificationsEmail.md)
# Notification Information
A(n) {{ notification.EntityType }} you are subscribed to was {{ notification.ActionVerbiage | otherwise(notification.Action) }}.
## Triggering User
Name: **{{ triggeringUser.FullName }}**
Phone: **{{ triggeringUser.UserPhone }}**
Email: **{{ triggeringUser.UserEmail }}**
## From Agency
Agency: **{{ triggeringUser.AgencyName }}**
Agency Phone: **{{ triggeringUser.AgencyPhone }}**
@foreach bag in dataBag {
@bag.Key: @bag.Value
}
## Link
[Click here to open]({{notification.Url}})
I feel like I’m mixing two different technologies. How can I use the @foreach syntax in my Markdown email / text templates?