如何保存渲染视图的HTML?

时间:2018-11-14 07:34:23

标签: c# html asp.net-core

基本上,用户进入页面,生成报告并决定是否保存该报告。

如果是,那么我必须将此html保存为静态html文件。

这真是太好了,

public IActionResult GetReport()
{
    (...)
    string html = View(model).ToString();
    save_to_database(html);
    return View(model);
}

但是,我设法找到的唯一解决方案是在该页面上放置按钮 像这样执行JavaScript:

var html = new XMLSerializer().serializeToString(document); 

sendHTMLViaAPI(html);

并通过邮寄将该html发送到API。

所以,我很好奇是否有C#方式可以做到这一点?在Controller的方法中。

还:那有潜在危险吗?例如。会话内容可以保存在该html文件中,或者用户可以通过API发送非HTML文件的内容...

2 个答案:

答案 0 :(得分:2)

如果我理解您的意思是正确的,那么此解决方案可能就是您想要的:

[HttpPost]
public IActionResult GetHTML()
{
    var model = new ModelClass() { Content = "Hi!" };

    // or
    // return PartialView("GetHTML", model);
    return PartialView(nameof(GetHTML), model);
}

在文件GetHTML.cshtml中:

@model ModelClass 
<div>
    Content: @Model.Content
</div>

在客户端,当用户想要以字符串形式获取HTML时,您可以尝试使用jquery来获取它:

$.post('/home/gethtml').done(function (html) {
    // html is a string here..

    // <div>
    //     Content: Hi!
    // </div>

    $('body').append(html);
});

或创建您的自定义服务:

ViewRender.cs

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Routing;
using System;
using System.IO;

public class ViewRender : IViewRender
{
    private IRazorViewEngine _viewEngine;

    private ITempDataProvider _tempDataProvider;

    private IServiceProvider _serviceProvider;

    public ViewRender(
        IRazorViewEngine viewEngine, 
        ITempDataProvider tempDataProvider, 
        IServiceProvider serviceProvider)
    {
        _viewEngine = viewEngine;
        _tempDataProvider = tempDataProvider;
        _serviceProvider = serviceProvider;
    }

    public string Render(string name)
    {
        var actionContext = GetActionContext();

        var viewEngineResult = _viewEngine.FindView(actionContext, name, false);

        if (!viewEngineResult.Success)
        {
            throw new InvalidOperationException(string.Format("Couldn't find view '{0}'", name));
        }

        var view = viewEngineResult.View;

        using (var output = new StringWriter())
        {
            var viewContext = new ViewContext(
                actionContext, 
                view, 
                new ViewDataDictionary<string>(
                    metadataProvider: new EmptyModelMetadataProvider(), 
                    modelState: new ModelStateDictionary())
                {
                    Model = null
                }, 
                new TempDataDictionary(actionContext.HttpContext, _tempDataProvider), 
                output, 
                new HtmlHelperOptions());

            view.RenderAsync(viewContext).GetAwaiter().GetResult();

            return output.ToString();
        }
    }

    public string Render<TModel>(string name, TModel model)
    {
        var actionContext = GetActionContext();

        var viewEngineResult = _viewEngine.FindView(actionContext, name, false);

        if (!viewEngineResult.Success)
        {
            throw new InvalidOperationException(string.Format("Couldn't find view '{0}'", name));
        }

        var view = viewEngineResult.View;

        using (var output = new StringWriter())
        {
            var viewContext = new ViewContext(
                actionContext, 
                view, 
                new ViewDataDictionary<TModel>(
                    metadataProvider: new EmptyModelMetadataProvider(), 
                    modelState: new ModelStateDictionary())
                {
                    Model = model
                }, 
                new TempDataDictionary(actionContext.HttpContext, _tempDataProvider), 
                output,                     
                new HtmlHelperOptions());

            view.RenderAsync(viewContext).GetAwaiter().GetResult();

            return output.ToString();
        }
    }

    private ActionContext GetActionContext()
    {
        var httpContext = new DefaultHttpContext();

        httpContext.RequestServices = _serviceProvider;

        return new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
    }
}

IViewRender.cs

public interface IViewRender
{
    string Render(string name);

    string Render<TModel>(string name, TModel model);
}

Startup.cs

services.AddTransient<IViewRender, ViewRender>();

用法:

public class HomeController : Controller
{
    private readonly IViewRender _viewRender { get; set; }

    public HomeController(IViewRender viewRender)
    {
        _viewRender = viewRender;
    }

    public IActionResult GetHTML()
    {
        string htmlWithoutModel = _viewRender.Render("Home/GetHTML");

        var model = new ModelClass() { Content = "Hi!" };

        string htmlWithModel = _viewRender.Render<ModelClass>("Home/GetHTML", model);

        //...
    }
}

答案 1 :(得分:0)

Return View as String in .NET Core

该网址的回复副本^

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using System.IO;
using System.Threading.Tasks;

namespace CC.Web.Helpers
{
    public static class ControllerExtensions
    {
        public static async Task<string> RenderViewAsync<TModel>(this Controller controller, string viewName, TModel model, bool partial = false)
        {
            if (string.IsNullOrEmpty(viewName))
            {
                viewName = controller.ControllerContext.ActionDescriptor.ActionName;
            }

            controller.ViewData.Model = model;

            using (var writer = new StringWriter())
            {
                IViewEngine viewEngine = controller.HttpContext.RequestServices.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine;
                ViewEngineResult viewResult = viewEngine.FindView(controller.ControllerContext, viewName, !partial);

                if (viewResult.Success == false)
                {
                    return $"A view with the name {viewName} could not be found";
                }

                ViewContext viewContext = new ViewContext(
                    controller.ControllerContext,
                    viewResult.View,
                    controller.ViewData,
                    controller.TempData,
                    writer,
                    new HtmlHelperOptions()
                );

                await viewResult.View.RenderAsync(viewContext);

                return writer.GetStringBuilder().ToString();
            }
        }
    }
}

然后只需执行以下操作:

viewHtml = await this.RenderViewAsync("Report", model);

或者对于PartialView:

partialViewHtml = await this.RenderViewAsync("Report", model, true);