Reputation: 3055
I have two entirely separate web (api) services.
One resembles the business case (bc) and the other's only concern is sending (and building) e-mails (ms).
So basically the BC sends all relevant data to the mail service.
BC ===== { Sender, Receipient, Subject, Template, Model } =====> MS
The mail service takes the template (razor template) and the model and builds the mail's content. It does the same with the subject which may also be a razor template.
The question now is... in order for razorengine to work properly... I need to specify unique names for my mail templates and I'd prefer not to trust the business case with this task. Because the client may choose a name which is already in use by another client (business case).
My solution right now looks like this:
string uniqueTemplateName = sha1(template); // bad idea?
string result = _razorEngineService.RunCompile(template, uniqueTemplateName, null, (object)model);
Using sha1(template)
should do the trick, right? Are there any drawbacks to this?
Upvotes: 1
Views: 171
Reputation: 1704
You actually have several problems here depending on your requirements. Initially it seemed like "clientname/templatename" would be a fit. Usually you just use the path where the template came from (full directory path, database id).
Any kind of hash completely defeats the purpose of the caching layer for you to be able to notice when you need to recycle the current AppDomain because of stale templates. The default CachingProvider will always use the cached entry and changes will be ignored (no recompiles). But you can customize that to your needs. For example you could implement a strategy like: If a single template is edited more than 10 times the AppDomain is recycled. One can achieve this by implementing an ITemplateManager
and an ICachingProvider
and some AppDomain recycle code. How to do that is a bit out of scope for the question you asked, but you can look at the existing implementations.
This AppDomain recycle stuff is hard and defeating it with a hash seems like an easy solution, but if you have the requirement of changing template you need to think about it, because we can't abstract that away from you (because loaded assemblies cannot be unloaded). And depending on your users and your environment you might get into a situation where users can start a DOS attack to your service by filling up your memory. If you are fine with the performance you can look at the isolation API as well. With isolation you can use very simple approach like recycle the AppDomain every 1000 compiles (you still need to implement the notification yourself with a custom ICachingProvider
or even simpler just count the number of times you are using RunCompile
).
TL;DR Drawbacks:
Hope this helps,
matthid (Disclosure: A RazorEngine Contributor)
Upvotes: 0