Как я могу сохранить HTML визуализированного представления? - PullRequest
0 голосов
/ 14 ноября 2018

В основном, пользователь заходит на страницу, генерирует отчет и решает, сохранить его или нет.

Если да, то я должен сохранить этот 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 # -ish-способы сделать это? в методе контроллера.

Также: это потенциально опасно? Например. вещи сеанса могут быть сохранены в этом html-файле, или пользователь может отправлять содержимое не-HTML-файла через API ...

Ответы [ 2 ]

0 голосов
/ 17 апреля 2019

Возврат вида в виде строки в .NET Core

Копия ответа с этого URL ^

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);
0 голосов
/ 14 ноября 2018

Если я понимаю, что вы имели в виду правильно, это решение может быть тем, что вы ищете:

[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);

        //...
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...