RazorGenerator, Templates, and @Html
Asked Answered
L

2

6

I'm trying to use RazorGenerator as an email template engine. I want to take a model with the data, assemble the correct set of partial views, and return HTML that I can email out.
Edit: In addition to this workflow, any solution would need to be editable as a .cshtml file and be able to be compiled into a dll. For various reasons, it is not practical to deploy the cshtml files themselves - if we can't embed all our razor views into a single file, then we can't use that suggestion. Hence RazorGenerator.

So far, I've worked out every part of it, except for the partials. When I try to use @Html.Partial() in a template file, I get: The name 'Html' does not exist in the current context.

Based on this answer, I know that @Html isn't part of Razor by default, and there's many answers out there as to how to create a HtmlHelper in a controller. However, I need to create one in a template, which doesn't have the ControllerContext that I'd need to follow those examples.

I've also tried using @Include, but the RazorGenerator template doesn't seem to support that. Edit: I also tried creating a new class which inherited from TemplateBase<> and copied all the functionality of RazorTemplateBase, but I get NullReferenceExceptions on the @Include line.

So, my primary question is: Is there a better way to include another Razor file (with model) into my file?

Secondarily, if there isn't a better way, how can I get the HtmlHelper created?


Edit for bounty: Just to reiterate, the four things I need in an acceptable answer are:

  1. The ability to edit .cshtml files with the standard editor (no "store it as a string" or such)
  2. The ability to compile everything into a single dll which can be deployed using our current build system (we can't deploy lots of individual .cshtml's)
  3. The ability to reference one .cshtml file from another, and pass a model - equivalent to @Includes or @Html.Partial (Either of which are perfectly acceptable if they work)
  4. The ability to email out the result, with attachments. (I already have code for this, if the result is a string or convertible to one.)

I currently can get most combinations of three of these working, but I can't get all four at once. I'm open to new libraries, replacing RazorGenerator, or throwing out any part of what I already have, so long as the result works as needed.

Lamellicorn answered 23/10, 2012 at 16:48 Comment(9)
Is the partial in the same views folder? I've never had any issue with using Html.Partial()Seek
I ask simply because using that method you have two options for specifying the partial... Html.Partial("_PartialInSameFolder") or Html.Partial("~/Views/Folder/PartialInAnotherFolder.cshtml") you may know this it's just the only thing that I can think of that would cause the error that you mentioned.Seek
@Seek - he is not doing this in the context of a generated View. He is attempting to create HTML emails using the Razor engine from a backend class. '@Html' does not work in these situations. From what I can gather when we did the same thing, '@Html' takes a HtmlHelper parameter which contains the ViewContext of the View. Since this is in the backend -> there is no ViewContext which is part of the issue in solving this problem. I hope Bobson gets some good replies, becuase we gave up on trying to use any of the '@Html' items in our Razor templates (wanted to use '@Html.Raw')Ceratodus
@Ceratodus gotcha missed that part.Seek
@Ceratodus - Exactly. I'd be happy with no @Html and a working @Include, but a working @Html would be even better.Lamellicorn
Why don't you use the already existing projects that do this, like FluentEmail? All the work is already done.Abrupt
@MystereMan - I wasn't the one to pick this solution in the first place, I'm just trying to add more functionality to it (the original usage didn't involve piecing together templates). That being said, our requirements include being able to edit the templates as individual files, compile them into a dll for deployment, send attachments with the email, and the problematic piecing together of templates. If another client (like FluentEmail) will allow all four, I'll take a look and make a case for switching.Lamellicorn
Wouldn't you rather use this? nuget.org/packages/ActionMailerAlleras
@Alleras - If it meets my four criteria, I'd love to. Taking a quick look, it looks like it fails the compilation test, and is unclear on the attachment one. If you can confirm that we would be able to deploy all our emails as a single dll (or even several), then I'll take another look.Lamellicorn
S
1

Just a thought, but why couldn't you set up other pages and in your Controller Code open up an HTTPWebRequest / WebClient send the data you need there, get all the html/text out of that view, merge several calls together and then email out all that string.

public ActionResult SomeAction() {
  // call other section logic using HttpWebRequest or WebClient
  // /controller/emailsection/{vars}/......
  // Get the string out of the request add it to ViewData["xxx"]
  // rinse and repeat for other sections

}

public ActionResult EmailSection() {
  //put section logic here

  Response.ContentType = "text/html"; // "text/plain"
  Response.Write("Some HttpWebResponse");
  return null;
}
Schellens answered 25/10, 2012 at 19:1 Comment(5)
We're actually embedding this into a WinForm application (part of the reason for #2), so there's no place to request them from. In theory, we could host the pages on our web server, but that's going to slow down the process of each one, and we need to generate a lot of these emails at once. Good idea, though.Lamellicorn
Deploy IIS Express with your Winform app and then load them from localmachine request there.Schellens
Hmm. Interesting idea. I'll give that a try either tomorrow or Monday.Lamellicorn
Our current plan is to go with a variant of this idea. I only thought of hosting on our web server, with the problems I mentioned, but one of my co-workers pointed out that since most of the use for this will be from an automated job, rather than the WinForm app, it would make the most sense to set up a dedicated internal website that only does these pages on a spare server, and just request the page from that for both the automated job and the few WinForm uses.Lamellicorn
We have a similar server setup for just internal jobs like this for our administrative scripts, plus it feeds a few of our websites through the DMZ. Wasn't completely sure what your infrastructure was like so just took a random shot in the dark. Glad I could render a different view.Schellens
T
-1

Is this what you want?

Render a view as a string

How to Email Screen in ASP.Net/MVC

http://www.brightmix.com/blog/how-to-renderpartial-to-string-in-asp-net-mvc/

Tallou answered 27/10, 2012 at 5:25 Comment(3)
On a quick perusal, I don't think it is. All those seem to require having an existing context of some sort (look for the new ViewContext(ControllerContext) sections), and the intent is to render it without any context.Lamellicorn
Does the second link use it too? I think we can fake HttpContext.Tallou
It does, but you have to follow the link to the source, and look down into the comments to see the problems related to it that people were having. The last comment on that page may work without a context, but it's not clear either way for sure.Lamellicorn

© 2022 - 2024 — McMap. All rights reserved.