Rendering a view to a string in MVC, then redirecting — workarounds?

后端 未结 3 1798
轻奢々
轻奢々 2021-01-14 03:14

I can\'t render a view to a string and then redirect, despite this answer from Feb (after version 1.0, I think) that claims it\'s possible. I thought I was doing something w

3条回答
  •  南方客
    南方客 (楼主)
    2021-01-14 03:49

    public Action SendEmail(int id)
    {
      //Let's say that id is the db id of an order that a customer has just placed.
    
      //Go get that model from the db.
      MyModel model = new Model(id);
    
      //Now send that email. Don't forget the model and controller context.
      SendEmail(model, this.ControllerContext);
    
      //Render (or redirect!)
      return RedirectToAction("Wherever");
    }
    
    private static void SendEmail(MyModel model, ControllerContext controllerContext)
    {
      //Recreate the viewdata
      ViewDataDictionary viewData = controllerContext.Controller.ViewData;
      viewData["Order"] = model;
      string renderedView = "";
      CustomRenderers customRenderers = new CustomRenderers();
    
      //Now render the view to string
      //ControllerContext, ViewPath, MasterPath, ViewDataDictionary, TempDataDictionary
      //As you can see, we're not passing a master page, and the tempdata is in this instance.
      renderedView = RenderViewToString(controllerContext, "~/Views/Orders/Email.aspx", "", viewData, null);
    
      //Now send your email with the string as the body.
      //Not writing that, as the purpose is just to show the rendering. :)
    }
    
    
    //Elsewhere...
    public class CustomRenderers
    {
      public virtual string RenderViewToString(ControllerContext controllerContext, string viewPath, string masterPath, ViewDataDictionary viewData, TempDataDictionary tempData)
      {
        if (tempData == null)
        {
        tempData = new TempDataDictionary();
        }
    
        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;
        }
      }
    }
    

    In your Orders/Email.aspx view, make sure you refer to everything from the ViewData, rather than the model. you can do this:

    <% MyModel model = (MyModel)ViewData["Order"] %>
    

提交回复
热议问题