Reputation: 11615
I am rendering PartialViews/Models with the method below in order to template emails that get sent out.
I am using the code below to convert the partial and model into an html string that I can pass to my email sending code.
public class BaseController : Controller
{
public string RenderPartialViewToString(string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
throw new ArgumentException("No View Path Provided.");
ViewData.Model = model;
using (StringWriter sw = new StringWriter())
{
ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
viewResult.View.Render(viewContext, sw);
return sw.GetStringBuilder().ToString();
}
}
}
Currently, this lives in the BaseController, I would like to move it out into a helper method so that I can move my email model building out/sending out of the controller too.
The problem is I don't have access to ViewData/TempData/ControllerContext
I can new up a ControllerContext but I don't know what to do about ViewData/TempData.
This is how I would use what I have in the Controller currently:
//Do Stuff in Controller
var html = RenderPartialViewToString("~/Views/Mail/_ForgotPassword.cshtml", new MailModel { Username = "Skrillex", SomethingElse = "foo" });
//Send the Email
Upvotes: 5
Views: 5295
Reputation: 1407
I have used 2 methods for Razor rendering emails that need to be sent out side of a controller... first I passed the ControllerContext to my service layer which worked as expected, but not ideal.... Often my services are used by command line apps or compiled into a Windows Service where there is no ControllerContext available... On my second attempt I used this Razor render engine: http://razorengine.codeplex.com/ or https://github.com/Antaris/RazorEngine
Upvotes: 0
Reputation: 41
You can create an instance or static property of BaseController in the helper class as shown below,
public sealed class Helper {
///Gets or sets BaseController
public BaseController { get; set; }
#region "Constructors"
/// <summary>
/// Initialises a new instance of the <see cref="Helper" /> class.
/// </summary>
public Helper() : base() {
}
/// <summary>
/// Initialises a new instance of the <see cref="Helper" /> class.
/// </summary>
public Helper(BaseController baseController) : this() {
this.BaseController = baseController;
}
#endregion
public void SendEmail(){
// Here you can call your RenderPartialViewToString from the BaseController
var m_RenderPartialViewToString = this.BaseController.RenderPartialViewToString( .......);
}}
Regards. Hope this helps.
Upvotes: 0
Reputation: 81680
I think you are on the right track, but the problem is your eagerness to complete separation, it is rather too eager.
You are using Razor view engine to render your rich text HTML email. A very noble approach. However, this means that you will be very close to your presentation layer and running this from outside a controller - in my view - does not make a lot of sense.
I believe you need to make (if not already made):
So the point is, calling of the rendering does not need to go out of the controller, building of the email model should.
Now if you are doing all of that it means I have not understood your question and requires more explanation.
Upvotes: 2