How to render an ASP.NET MVC view as a string?

后端 未结 15 2968
挽巷
挽巷 2020-11-21 04:40

I want to output two different views (one as a string that will be sent as an email), and the other the page displayed to a user.

Is this possible in ASP.NET MVC bet

15条回答
  •  滥情空心
    2020-11-21 05:08

    I found a new solution that renders a view to string without having to mess with the Response stream of the current HttpContext (which doesn't allow you to change the response's ContentType or other headers).

    Basically, all you do is create a fake HttpContext for the view to render itself:

    /// Renders a view to string.
    public static string RenderViewToString(this Controller controller,
                                            string viewName, object viewData) {
        //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(HttpContext.Current.Request, fakeResponse);
        var fakeControllerContext = new ControllerContext(
            new HttpContextWrapper(fakeContext),
            controller.ControllerContext.RouteData,
            controller.ControllerContext.Controller);
    
        var oldContext = HttpContext.Current;
        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()),
            new ViewPage());
        html.RenderPartial(viewName, viewData);
    
        //Restore context
        HttpContext.Current = oldContext;    
    
        //Flush memory and return output
        memWriter.Flush();
        return sb.ToString();
    }
    
    /// Fake IView implementation used to instantiate an HtmlHelper.
    public class FakeView : IView {
        #region IView Members
    
        public void Render(ViewContext viewContext, System.IO.TextWriter writer) {
            throw new NotImplementedException();
        }
    
        #endregion
    }
    

    This works on ASP.NET MVC 1.0, together with ContentResult, JsonResult, etc. (changing Headers on the original HttpResponse doesn't throw the "Server cannot set content type after HTTP headers have been sent" exception).

    Update: in ASP.NET MVC 2.0 RC, the code changes a bit because we have to pass in the StringWriter used to write the view into the ViewContext:

    //...
    
    //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);
    
    //...
    

提交回复
热议问题