asp.net-mvc MVC 5 将视图渲染为字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23494741/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
MVC 5 Render View to String
提问by wh1sp3r
It seems, most code for rendering view into string doesn't work in MVC 5.
看来,将视图渲染为字符串的大多数代码在 MVC 5 中都不起作用。
I have latest MVC 5.1.2 templates and I am trying to render view into string.
我有最新的 MVC 5.1.2 模板,我正在尝试将视图呈现为字符串。
public static String RenderViewToString(ControllerContext context, String viewPath, object model = null)
{
context.Controller.ViewData.Model = model;
using (var sw = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindView(context, viewPath, null);
var viewContext = new ViewContext(context, viewResult.View, context.Controller.ViewData, context.Controller.TempData, sw);
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(context, viewResult.View);
return sw.GetStringBuilder().ToString();
}
}
Well, it's working but its output contains lots of $ marks instead tags. I read something about it was fixed in RC version, but that's old news.
嗯,它正在工作,但它的输出包含很多 $ 标记而不是标签。我读到一些关于它在 RC 版本中已修复的内容,但那是旧消息。
Problem looks like this
问题看起来像这样
<$A$><h1></h1>
<table</$A$><$B$> class=""</$B$><$C$>> <tbody</$C$><$D$></$D$><$E$>></tbody>
</table></$E$>
I would like to ask, how do you render views into string in latest MVC 5 template ? Thanks.
我想问一下,你如何在最新的 MVC 5 模板中将视图渲染成字符串?谢谢。
回答by wh1sp3r
Ok, seems I found a solution. Author of the idea is Yakir Manor.
好吧,看来我找到了解决方案。这个想法的作者是亚基尔庄园。
class FakeController : ControllerBase
{
protected override void ExecuteCore() { }
public static string RenderViewToString(string controllerName, string viewName, object viewData)
{
using (var writer = new StringWriter())
{
var routeData = new RouteData();
routeData.Values.Add("controller", controllerName);
var fakeControllerContext = new ControllerContext(new HttpContextWrapper(new HttpContext(new HttpRequest(null, "http://google.com", null), new HttpResponse(null))), routeData, new FakeController());
var razorViewEngine = new RazorViewEngine();
var razorViewResult = razorViewEngine.FindView(fakeControllerContext, viewName, "", false);
var viewContext = new ViewContext(fakeControllerContext, razorViewResult.View, new ViewDataDictionary(viewData), new TempDataDictionary(), writer);
razorViewResult.View.Render(viewContext, writer);
return writer.ToString();
}
}
}
It's a trick with fake context and response.
这是带有虚假上下文和响应的技巧。
Example:
例子:
String renderedHTML = RenderViewToString("Email", "MyHTMLView", myModel );
My file MyHTMLView.cstml is stored in Views/Email/MyHTMLView.cshtml. Email is a fake controller name.
我的文件 MyHTMLView.cstml 存储在 Views/Email/MyHTMLView.cshtml 中。电子邮件是一个虚假的控制器名称。
回答by Alok
following is the solution that works with session and areas on MVC5.
以下是适用于 MVC5 上的会话和区域的解决方案。
public class FakeController : ControllerBase
{
protected override void ExecuteCore() { }
public static string RenderViewToString(string controllerName, string viewName,string areaName, object viewData,RequestContext rctx)
{
try
{
using (var writer = new StringWriter())
{
var routeData = new RouteData();
routeData.Values.Add("controller", controllerName);
routeData.Values.Add("Area", areaName);
routeData.DataTokens["area"] = areaName;
var fakeControllerContext = new ControllerContext(rctx, new FakeController());
//new ControllerContext(new HttpContextWrapper(new HttpContext(new HttpRequest(null, "http://google.com", null), new HttpResponse(null))), routeData, new FakeController());
fakeControllerContext.RouteData = routeData;
var razorViewEngine = new RazorViewEngine();
var razorViewResult = razorViewEngine.FindView(fakeControllerContext, viewName, "", false);
var viewContext = new ViewContext(fakeControllerContext, razorViewResult.View, new ViewDataDictionary(viewData), new TempDataDictionary(), writer);
razorViewResult.View.Render(viewContext, writer);
return writer.GetStringBuilder().ToString();
//use example
//String renderedHTML = RenderViewToString("Email", "MyHTMLView", myModel );
//where file MyHTMLView.cstml is stored in Views/Email/MyHTMLView.cshtml. Email is a fake controller name.
}
}
catch (Exception ex)
{
//do your exception handling here
}
}
}
here is how you call this from another controller
这是你从另一个控制器调用它的方式
var modal = getModal(params);
return FakeController.RenderViewToString(controllerName, viewName, areaName, modal, this.Request.RequestContext);
using requestcontext we can easily pass current session in fakecontroller and render razor string.
使用 requestcontext 我们可以轻松地在 fakecontroller 中传递当前会话并呈现剃刀字符串。
回答by William Bosacker
I had an immediate need to return 6 partial views as strings in a JSON object. Instead of creating a static method, and passing all the unneeded parameters, I decided to add protected methods to our ControllerBase class that derives from Controller, and is used as the base class for all of our controllers.
我迫切需要将 6 个部分视图作为 JSON 对象中的字符串返回。我没有创建静态方法并传递所有不需要的参数,而是决定将受保护的方法添加到从 Controller 派生的 ControllerBase 类中,并用作我们所有控制器的基类。
Here is a fully functional ControllerBase class that provides this functionality, and works very similar to the PartialView() and View() methods that are in the Controller class. It includes the additions from @Alok.
这是一个提供此功能的全功能 ControllerBase 类,其工作方式与 Controller 类中的 PartialView() 和 View() 方法非常相似。它包括来自@Alok 的补充。
public abstract class ControllerBase : Controller
{
#region PartialViewToString
protected string PartialViewToString(string partialViewName, object model = null)
{
ControllerContext controllerContext = new ControllerContext(Request.RequestContext, this);
return ViewToString(
controllerContext,
ViewEngines.Engines.FindPartialView(controllerContext, partialViewName) ?? throw new FileNotFoundException("Partial view cannot be found."),
model
);
}
#endregion
#region ViewToString
protected string ViewToString(string viewName, object model = null)
{
ControllerContext controllerContext = new ControllerContext(Request.RequestContext, this);
return ViewToString(
controllerContext,
ViewEngines.Engines.FindView(controllerContext, viewName, null) ?? throw new FileNotFoundException("View cannot be found."),
model
);
}
protected string ViewToString(string viewName, string controllerName, string areaName, object model = null)
{
RouteData routeData = new RouteData();
routeData.Values.Add("controller", controllerName);
if (areaName != null)
{
routeData.Values.Add("Area", areaName);
routeData.DataTokens["area"] = areaName;
}
ControllerContext controllerContext = new ControllerContext(HttpContext, routeData, this);
return ViewToString(
controllerContext,
ViewEngines.Engines.FindView(controllerContext, viewName, null) ?? throw new FileNotFoundException("View cannot be found."),
model
);
}
#endregion
#region Private Methods
private string ViewToString(ControllerContext controllerContext, ViewEngineResult viewEngineResult, object model)
{
using (StringWriter writer = new StringWriter())
{
ViewContext viewContext = new ViewContext(
controllerContext,
viewEngineResult.View,
new ViewDataDictionary(model),
new TempDataDictionary(),
writer
);
viewEngineResult.View.Render(viewContext, writer);
return writer.ToString();
}
}
#endregion
}
回答by stefan
@wh1sp3r answer works but for partial views I had to do the following minor changes:
@wh1sp3r 答案有效,但对于部分视图,我必须做以下小改动:
string html = FakeController.RenderViewToString("**Controllername**", "~/views/**Controllername**/_AsdfPartialPage.cshtml", fem);
public static string RenderViewToString(string controllerName, string viewName, object viewData)
{
using (var writer = new StringWriter())
{
var routeData = new RouteData();
routeData.Values.Add("controller", controllerName);
var fakeControllerContext = new ControllerContext(new HttpContextWrapper(new HttpContext(new HttpRequest(null, "http://localhost", null), new HttpResponse(null))), routeData, new FakeController());
var razorViewEngine = new RazorViewEngine();
//var razorViewResult = razorViewEngine.FindView(fakeControllerContext, viewName, "", false);
var razorViewResult = razorViewEngine.FindPartialView(fakeControllerContext, viewName, false);
var viewContext = new ViewContext(fakeControllerContext, razorViewResult.View, new ViewDataDictionary(viewData), new TempDataDictionary(), writer);
razorViewResult.View.Render(viewContext, writer);
return writer.ToString();
}
}
回答by Ji?í ?trnácty
To render PartialView to string use this code:
要将 PartialView 渲染为字符串,请使用以下代码:
class FakeController: ControllerBase {
protected override void ExecuteCore() { }
public static string RenderViewToString(string controllerName, string viewName, object model) {
using(var writer = new StringWriter()) {
var routeData = new RouteData();
routeData.Values.Add("controller", controllerName);
var fakeControllerContext = new ControllerContext(new HttpContextWrapper(new HttpContext(new HttpRequest(null, "http://localhost", null), new HttpResponse(null))), routeData, new FakeController());
var razorViewEngine = new RazorViewEngine();
var razorViewResult = razorViewEngine.FindPartialView(fakeControllerContext, viewName, false);
var viewContext = new ViewContext(fakeControllerContext, razorViewResult.View, new ViewDataDictionary(model), new TempDataDictionary(), writer);
razorViewResult.View.Render(viewContext, writer);
return writer.ToString();
}
}
}

