I am trying to render shapes as email templates. I would like to be able to do this from a background task as well as from the current request. Does anyone have any tips for me? I think the Orchard.DisplayManagement.IDisplayHelperFactory is the key, but then I need to manufacture the Vie开发者_如何学运维wContext and IViewDataContainer, which I could possibly get from the Orchard.Mvc.ViewEngines.Razor.WebViewPage perhaps?
Anyone done anything similar? I am looking at https://github.com/andrewdavey/postal/blob/master/src/Postal/EmailViewRenderer.cs for some inspiration, just wondering if anyone can put me on the right track?
Thanks again in advance!
After a bit of digging through the Orchard source and some inspiration taken from Andrew Davey's postal application I managed to come up with a solution. See code fragment below
private void RenderMessage(MessageContext context, dynamic shape)
{
var httpContext = new EmailHttpContext(new Uri("http://localhost/orchard/"));
var routeData = new RouteData();
routeData.DataTokens.Add("IWorkContextAccessor", _workContextAccessor);
routeData.Values["controller"] = "Dummy";
var requestContext = new RequestContext(httpContext, routeData);
var controllerContext = new ControllerContext(requestContext, new DummyController());
var viewContext = new ViewContext(controllerContext, new ShapeView(shape), new ViewDataDictionary(shape.Model), new TempDataDictionary(), new StringWriter());
var scope = _workContextAccessor.CreateWorkContextScope(viewContext.HttpContext);
scope.WorkContext.CurrentTheme = _siteThemeService.GetSiteTheme();
var page = new EmailWebViewPage(viewContext, new ViewDataDictionary<dynamic>(shape.Model));
var displayHelperFactory = _services.WorkContext.Resolve<IDisplayHelperFactory>();
var display = displayHelperFactory.CreateHelper(page.ViewContext, page);
context.MailMessage.Body = display(shape).ToHtmlString();
scope.Dispose();
}
class DummyController : Controller
{
}
class ShapeView : IView
{
private readonly dynamic _shape;
public ShapeView(dynamic shape)
{
_shape = shape;
}
#region IView Members
public void Render(ViewContext viewContext, TextWriter writer)
{
}
#endregion
}
The EmailHttpContext was taken from the postal project. This was used to constructu the controller and view contexts. I then just had to extend orchard's WebViewPage to create the EmailWebViewPage that enables me to tap into the orchard infrastructure to access view engines etc.
It's not the prettiest solution, and needs to be thoroughly tested, but appears to do what I am after.
If anyone has some feedback, or would like the complete code, feel free to drop me a line.
It sounds like you have this sorted, but I also wanted to tap into the Razor View Engine in Orchard to create templated emails. So, I asked a question about using FindView in Orchard.
I thought you might find the answers useful, including the one I added to show my final solution:
Using FindView in Orchard
精彩评论