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

后端 未结 15 2770
挽巷
挽巷 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:17

    This works for me:

    public virtual string RenderView(ViewContext viewContext)
    {
        var response = viewContext.HttpContext.Response;
        response.Flush();
        var oldFilter = response.Filter;
        Stream filter = null;
        try
        {
            filter = new MemoryStream();
            response.Filter = filter;
            viewContext.View.Render(viewContext, viewContext.HttpContext.Response.Output);
            response.Flush();
            filter.Position = 0;
            var reader = new StreamReader(filter, response.ContentEncoding);
            return reader.ReadToEnd();
        }
        finally
        {
            if (filter != null)
            {
                filter.Dispose();
            }
            response.Filter = oldFilter;
        }
    }
    
    0 讨论(0)
  • 2020-11-21 05:17

    I am using MVC 1.0 RTM and none of the above solutions worked for me. But this one did:

    Public Function RenderView(ByVal viewContext As ViewContext) As String
    
        Dim html As String = ""
    
        Dim response As HttpResponse = HttpContext.Current.Response
    
        Using tempWriter As New System.IO.StringWriter()
    
            Dim privateMethod As MethodInfo = response.GetType().GetMethod("SwitchWriter", BindingFlags.NonPublic Or BindingFlags.Instance)
    
            Dim currentWriter As Object = privateMethod.Invoke(response, BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.InvokeMethod, Nothing, New Object() {tempWriter}, Nothing)
    
            Try
                viewContext.View.Render(viewContext, Nothing)
                html = tempWriter.ToString()
            Finally
                privateMethod.Invoke(response, BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.InvokeMethod, Nothing, New Object() {currentWriter}, Nothing)
            End Try
    
        End Using
    
        Return html
    
    End Function
    
    0 讨论(0)
  • 2020-11-21 05:18

    I found a better way to render razor view page when I got error with the methods above, this solution for both web form environment and mvc environment. No controller is needed.

    Here is the code example, in this example I simulated a mvc action with an async http handler:

        /// <summary>
        /// Enables processing of HTTP Web requests asynchronously by a custom HttpHandler that implements the IHttpHandler interface.
        /// </summary>
        /// <param name="context">An HttpContext object that provides references to the intrinsic server objects.</param>
        /// <returns>The task to complete the http request.</returns>
        protected override async Task ProcessRequestAsync(HttpContext context)
        {
            if (this._view == null)
            {
                this.OnError(context, new FileNotFoundException("Can not find the mvc view file.".Localize()));
                return;
            }
            object model = await this.LoadModelAsync(context);
            WebPageBase page = WebPageBase.CreateInstanceFromVirtualPath(this._view.VirtualPath);
            using (StringWriter sw = new StringWriter())
            {
                page.ExecutePageHierarchy(new WebPageContext(new HttpContextWrapper(context), page, model), sw);
                await context.Response.Output.WriteAsync(sw.GetStringBuilder().ToString());
            }
        }
    
    0 讨论(0)
提交回复
热议问题