Reputation: 477
I have the following project structure:
Solution
Project
Properties/
References/
Model/
Message.cs
Views/
Index.cshtml
EmailBuilder/
EmailBuilder.cs
Program.cs
I would like to read all text from Index.cshtml file and pass my models to the file. However, I am not able to open Index.cshtml from my code without setting Copy to Output Directory: Copy if newer
. I do not want to copy these files to output directory because I do not want user who is generating emails to see the template files. This is what I am currently doing:
private static readonly string TemplateFolderPath =
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Views");
RazorEngineManager.Instance.Razor.AddTemplate("Index",
File.ReadAllText(Path.Combine(TemplateFolderPath, "Index.cshtml")));
How can I read from the cshtml file without having to copy it to an output directory? I come from the Java world and its as simple as parsing the text or velocity file from classpath which does not requiring copying files to the output directory. The files stay embedded in my jar.
How can I do this in .NET?
Please help.
Upvotes: 1
Views: 1084
Reputation: 4957
A similar technique in .NET (I hesitate to say "equivalent" because I don't know Java well enough to be sure) is to use embedded resources. Set your Build Action for your .cshtml files to Embedded resource and use Assembly.GetManifestResourceStream
to open a stream with the resource's contents.
string resourceName = typeof(Program).FullName + ".Views.Index.cshtml";
using (Stream resourceStream = typeof(Program).Assembly.GetManifestResourceStream(resourceName))
{
// Read the contents
}
This assumes that the Program class's namespace is the default namespace for the assembly. Normally, this wil be the case but if you've renamed things since project creation, it could get out of sync, so keep an eye on that. Also, the stream will be null
if the resource can't be found so make sure you check that, too.
You can also use Assembly.GetManifestResourceNames
to enumerate templates.
string prefix = typeof(Program).FullName + ".Views.";
var templates = (from rn in typeof(Program).Assembly.GetManifestResourceNames()
where rn.EndsWith(".cshtml")
select new TemplateInfo
{
Key = Path.GetFileName(rn)
FileName = rn.Substring(prefix.Length)
ResourceName = rn
}).ToList();
Now you have list of objects (you define TemplateInfo
yourself) with the resource name, the file name, and a key you can use in a template manager.
There is one drawback to this technique: when you add new CSHTML files, you have to remember to change it to Embedded Resource. Tip: if you copy/paste the file within Visual Studio, it will copy the Build Action property to the new file.
Upvotes: 3