Render ViewUserControl from Class Library
I want to render some HTML to use in an e-mail. I have a collectio开发者_如何学Gon of objects that represent rows and columns, so I could be rendering the HTML in pure C# code using a StringBuilder.
But I prefer to have a ViewUserControl or just a ViewPage in a class library, that does the rendering. I want to be able to use the ViewUserControl and the rendering methostrong textd from outside an ASP.NET MVC app, e.g. a Windows Service.
How can I render a View from a class library?
I tried this, but the call to RenderPartial throws a NullReferenceException.
[TestMethod]
public void RenderViewToString()
{
string viewName = "EmailTest";
string viewData = "martin";
//Create memory writer
var sb = new StringBuilder();
var memWriter = new StringWriter(sb);
//Create fake http context to render the view
var fakeResponse = new HttpResponse(memWriter);
var fakeContext = new HttpContext(new HttpRequest("fake.html", "http://localhost/fake.html", ""), fakeResponse);
var fakeRouteData = new RouteData();
fakeRouteData.Values.Add("Controller", "Fake");
var fakeControllerContext = new ControllerContext(new HttpContextWrapper(fakeContext), fakeRouteData, new FakeController());
HttpContext.Current = fakeContext;
//Use HtmlHelper to render partial view to fake context
var html = new HtmlHelper(new ViewContext(fakeControllerContext, new FakeView(), new ViewDataDictionary(), new TempDataDictionary(), memWriter), new ViewPage());
html.RenderPartial(viewName, viewData);
//Flush memory and return output
memWriter.Flush();
var htmlString = sb.ToString();
}
Try this:
public static string RenderPartialToString(string controlName, object viewData)
{
ViewDataDictionary vd = new ViewDataDictionary(viewData);
ViewPage vp = new ViewPage { ViewData = vd };
Control control = vp.LoadControl(controlName);
vp.Controls.Add(control);
StringBuilder sb = new StringBuilder();
using (StringWriter sw = new StringWriter(sb))
{
using (HtmlTextWriter tw = new HtmlTextWriter(sw))
{
vp.RenderControl(tw);
}
}
return sb.ToString();
}
The issue you are getting is with the asp.net engine, which is what the default view engine uses.
You can avoid it by using a different view engine, like spark.
Another option is to use similar to your code, but starting an asp.net appdomain / I'll share some code that does so in a couple of days.
精彩评论