我想输出两个不同的视图(一个作为将作为电子邮件发送的字符串),另一个是显示给用户的页面。
这在 ASP.NET MVC beta 中可行吗?
我尝试了多个示例:
1. ASP.NET MVC Beta 中的 RenderPartial 到 String
如果我使用此示例,我会收到“发送 HTTP 标头后无法重定向。”。
2. MVC 框架:捕获视图的输出
如果我使用它,我似乎无法执行redirectToAction,因为它试图呈现一个可能不存在的视图。如果我确实返回视图,它就会完全混乱并且看起来根本不正确。
有没有人对我遇到的这些问题有任何想法/解决方案,或者对更好的问题有任何建议?
非常感谢!
下面是一个例子。我想要做的是创建 GetViewForEmail 方法 :
public ActionResult OrderResult(string ref) { //Get the order Order order = OrderService.GetOrder(ref); //The email helper would do the meat and veg by getting the view as a string //Pass the control name (OrderResultEmail) and the model (order) string emailView = GetViewForEmail("OrderResultEmail", order); //Email the order out EmailHelper(order, emailView); return View("OrderResult", order); }
Tim Scott 接受的回答(我做了一些修改和格式化):
public virtual string RenderViewToString( ControllerContext controllerContext, string viewPath, string masterPath, ViewDataDictionary viewData, TempDataDictionary tempData) { Stream filter = null; ViewPage viewPage = new ViewPage(); //Right, create our view viewPage.ViewContext = new ViewContext(controllerContext, new WebFormView(viewPath, masterPath), viewData, tempData); //Get the response context, flush it and get the response filter. var response = viewPage.ViewContext.HttpContext.Response; response.Flush(); var oldFilter = response.Filter; try { //Put a new filter into the response filter = new MemoryStream(); response.Filter = filter; //Now render the view into the memorystream and flush the response viewPage.ViewContext.View.Render(viewPage.ViewContext, viewPage.ViewContext.HttpContext.Response.Output); response.Flush(); //Now read the rendered view. filter.Position = 0; var reader = new StreamReader(filter, response.ContentEncoding); return reader.ReadToEnd(); } finally { //Clean up. if (filter != null) { filter.Dispose(); } //Now replace the response filter response.Filter = oldFilter; } }
示例用法
假设控制器调用以获取订单确认电子邮件,并传递 Site.Master 位置。
string myString = RenderViewToString(this.ControllerContext, "~/Views/Order/OrderResultEmail.aspx", "~/Views/Shared/Site.Master", this.ViewData, this.TempData);
这是我想出的,它对我有用。我将以下方法添加到我的控制器基类中。(您总是可以在其他地方制作这些静态方法,我想这些方法接受控制器作为参数)
MVC2 .ascx 风格
protected string RenderViewToString<T>(string viewPath, T model) { ViewData.Model = model; using (var writer = new StringWriter()) { var view = new WebFormView(ControllerContext, viewPath); var vdd = new ViewDataDictionary<T>(model); var viewCxt = new ViewContext(ControllerContext, view, vdd, new TempDataDictionary(), writer); viewCxt.View.Render(viewCxt, writer); return writer.ToString(); } }
剃刀 .cshtml 样式
public string RenderRazorViewToString(string viewName, object model) { ViewData.Model = model; using (var sw = new StringWriter()) { var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName); var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw); viewResult.View.Render(viewContext, sw); viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View); return sw.GetStringBuilder().ToString(); } }
编辑:添加 Razor 代码。