Thanks to everyone for telling us how they work. I gathered a lot of knowledge from here. I liked @MartinHN using the Razor parser with a specific data model.
However, for me this did not work.
Demand:
I need to store letter templates so that I can display them on
Interested parties at any time. Thus, it should be available for viewing the Intranet - preferably through the sae website as a hosted API.
Interface designers should be able to easily modify templates. Thus, I want to save it in the usual HTML format so that the designer does not need to go through too many technical details.
Email templates should be easily accessible to administrators (future requirements). In the near future, various notifications for SMS, Screen. Thus, the patterns are different.
Based on these requirements, I did the following:
Since I used MVC, I created a folder called "STATIC" that is viewable directly (and the MVC / http handler excludes this folder from performing its MVC actions).
With this approach, I could easily achieve the first requirement, and I can send my link to shareholders as http://api.aksdfjl.com/static/welcomeemailtemplate.html
Each email template gave its own html, so it was easy for the designer to access it and transfer it to their repository as a shortcut to my repository folder. CSS is embedded in Html and it is completely independent html - via email.
The last basic requirement was to support this design, and the user can modify it. Well, then definitely I don’t want to deal with the file system at all. What I did is now these notifications are stored in the database, and I initialize them once. After that, the admin panel has a wysiwyg html editor that can give them a quick look, as well as control over what it should send.
Now I wanted to make sure that future requirements are easily handled, and since my company introduced various notifications for different modes, such as Email, Screen, SMS notifications. I decided to expand the software design with an XML template initializer that stores these responses.
The mother of the whole template, called MessageTemplates.xml, stores various information that I need to initialize templates of different types, that is, email, SMS, screen, etc.

Here's what the code looks like now.
[HttpGet] [Route("applications/initializenotificationtemplate")] public IHttpActionResult InitializeNotificationTemplate() { return InitializeNotificationTemplate(Path.Combine(HostingEnvironment.ApplicationPhysicalPath, @"Static\InitializeData\MessageTemplates.xml")); } [NonAction] public IHttpActionResult InitializeMailTemplate(string filePath) { try { _applicationService.InitializeTemplate(filePath); return Ok("Application Notification templates are initialized."); } catch (Exception ex) { return InternalServerError(ex); } }
_applicationService.InitializeTemplate has the following definition:
public bool InitializeTemplate(string filePath) { if (string.IsNullOrEmpty(filePath)) { throw new ArgumentNullException("File Path"); } if (!File.Exists(filePath)) { throw new FileNotFoundException(filePath); } var data = _notificationTemplateService.Get(); var exceptionMessages = string.Empty; if (data != null) { var historicalTemplates = data.ToList(); historicalTemplates.ForEach((d) => _notificationTemplateService.Delete(d, out exceptionMessages)); } XDocument xmlDocument = XDocument.Load(filePath); IEnumerable<NotificationTemplate> templates = (from template in xmlDocument.Descendants("Template") select new NotificationTemplate() { Title = template.Element("Subject").Value, Description = template.Element("Body").Value, Type = (NotificationTypeOptions)Enum.Parse(typeof(NotificationTypeOptions), template.Element("Type").Value, true), Category = (NotificationCategoryOptions)Enum.Parse(typeof(NotificationCategoryOptions), template.Attribute("category").Value, true), }).ToList(); foreach (var t in templates) { var path = Path.Combine(Path.GetDirectoryName(filePath), Regex.Replace(t.Description, @"\t|\n|\r| ", "")); if (File.Exists(path)) { StreamReader reader = new StreamReader(path); t.Description = reader.ReadToEnd(); } else { t.Description = string.Empty; } } return _notificationTemplateService.InsertRange(templates, out exceptionMessages); }
This is how my model looks, similar to the database model (first the code is the EF approach).
public class NotificationTemplate : IdentityBase { public string Category { get; set; } public NotificationTypeOptions Type { get; set; } public string Title { get; set; } public string Description { get; set; } public NotificationTemplate() { Type = NotificationTypeOptions.Email; } } [Flags] public enum NotificationTypeOptions { Email = 0, Screen = 1, }
The first time I install my application, I call the API initialization call, which installs my notification templates into the database, and all other options are available and ready to use.
Now with this approach, I have made everyone happy in the organization, and I have great power to expand this further, so it’s easy for me to introduce new templates.