为了账号安全,请及时绑定邮箱和手机立即绑定

在 ASP.NET Core 2.2 中将部分视图呈现为 HTML 字符串

在 ASP.NET Core 2.2 中将部分视图呈现为 HTML 字符串

C#
慕标琳琳 2022-09-04 16:30:58
我正在尝试使用AJAX调用我的控制器,并将带有模型的分部视图作为字符串返回,以便我可以将其注入到我的HTML中。我以前在MVC5中使用控制器接口执行此操作,但我似乎找不到有关如何在 Asp.Net Core 2.2中为部分视图执行此操作的任何信息。我已经找到了如何将视图呈现为字符串的示例,但我无法修改它们以用于分部视图。控制器操作:    public JsonResult GetUpsertPartialView(MessageBoard messageBoard)    {        Dictionary<string, string> result = new Dictionary<string, string>();        string errorState = "0";        string errorMessage = "";        try        {            result["view"] = ""; // My call to render the Partial View would go here.        }        catch (Exception)        {            errorState = "1";            errorMessage = "An error was encountered while constructing the View.";        }        result["errorState"] = errorState;        result["errorMessage"] = errorMessage;        return Json(result);    }AJAX Call:   $.ajax({      type: "GET",      url: "../Home/GetUpsertPartialView/",      data: messageBoardData,      contentType: 'application/json; charset=utf-8',      success: function (data) {         console.log(data);         $("#messageBoardModalBody").val(data.view);         $("#messageBoardModal").modal("show");      }   });我已确认我的控制器被命中,参数已正确传递,并且我正在从操作接收到我的AJAX调用的正确数据。我唯一缺少的是将分部视图直接呈现为字符串的功能。如果在 Asp.net Core中还有另一种方法可以做到这一点,我对其他选择持开放态度。注意:我这样做只是为了学习 Asp.Net 核心。如果需要更多信息,请告诉我。
查看完整描述

4 回答

?
HUWWW

TA贡献1874条经验 获得超12个赞

控制器扩展实现


    public static class ControllerExtensions

{

    /// <summary>

    /// Render a partial view to string.

    /// </summary>

    public static async Task<string> RenderViewToStringAsync(this Controller controller, string viewNamePath, object model = null)

    {

        if (string.IsNullOrEmpty(viewNamePath))

            viewNamePath = controller.ControllerContext.ActionDescriptor.ActionName;


        controller.ViewData.Model = model;


        using (StringWriter writer = new StringWriter())

        {

            try

            {

                var view = FindView(controller, viewNamePath);


                ViewContext viewContext = new ViewContext(

                    controller.ControllerContext,

                    view,

                    controller.ViewData,

                    controller.TempData,

                    writer,

                    new HtmlHelperOptions()

                );


                await view.RenderAsync(viewContext);


                return writer.GetStringBuilder().ToString();

            }

            catch (Exception exc)

            {

                return $"Failed - {exc.Message}";

            }

        }

    }


    private static IView FindView(Controller controller, string viewNamePath)

    {

        IViewEngine viewEngine = controller.HttpContext.RequestServices.GetService(typeof(ICompositeViewEngine)) as ICompositeViewEngine;


        ViewEngineResult viewResult = null;


        if (viewNamePath.EndsWith(".cshtml"))

            viewResult = viewEngine.GetView(viewNamePath, viewNamePath, false);

        else

            viewResult = viewEngine.FindView(controller.ControllerContext, viewNamePath, false);


        if (!viewResult.Success)

        {

            var endPointDisplay = controller.HttpContext.GetEndpoint().DisplayName;


            if (endPointDisplay.Contains(".Areas."))

            {

                //search in Areas

                var areaName = endPointDisplay.Substring(endPointDisplay.IndexOf(".Areas.") + ".Areas.".Length);

                areaName = areaName.Substring(0, areaName.IndexOf(".Controllers."));


                viewNamePath = $"~/Areas/{areaName}/views/{controller.HttpContext.Request.RouteValues["controller"]}/{controller.HttpContext.Request.RouteValues["action"]}.cshtml";


                viewResult = viewEngine.GetView(viewNamePath, viewNamePath, false);

            }


            if (!viewResult.Success)

                throw new Exception($"A view with the name '{viewNamePath}' could not be found");


        }


        return viewResult.View;

    }


}

控制器操作中的用法:


var html = await this.RenderViewToStringAsync("actionName" , model);


查看完整回答
反对 回复 2022-09-04
?
潇湘沐

TA贡献1816条经验 获得超6个赞

可以使用服务从任何位置(控制器,页面模型等)获取部分视图(或多个):


这个答案的起源,他值得称赞(我在这里添加它,因为我需要这样的东西,我花了很长时间才找到它)


定义依赖关系插入的接口

public interface IViewRenderService

{

    Task<string> RenderToStringAsync(string viewName, object model);

}

服务的实现

public class ViewRenderService : IViewRenderService

{

    private readonly IRazorViewEngine _razorViewEngine;

    private readonly ITempDataProvider _tempDataProvider;

    private readonly IServiceProvider _serviceProvider;


    public ViewRenderService(IRazorViewEngine razorViewEngine,

        ITempDataProvider tempDataProvider,

        IServiceProvider serviceProvider)

    {

        _razorViewEngine = razorViewEngine;

        _tempDataProvider = tempDataProvider;

        _serviceProvider = serviceProvider;

    }


    public async Task<string> RenderToStringAsync(string viewName, object model)

    {

        var httpContext = new DefaultHttpContext { RequestServices = _serviceProvider };

        var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());


        using (var sw = new StringWriter())

        {

            var viewResult = _razorViewEngine.FindView(actionContext, viewName, false);


            if (viewResult.View == null)

            {

                throw new ArgumentNullException($"{viewName} does not match any available view");

            }


            var viewDictionary = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())

            {

                Model = model

            };


            var viewContext = new ViewContext(

                actionContext,

                viewResult.View,

                viewDictionary,

                new TempDataDictionary(actionContext.HttpContext, _tempDataProvider),

                sw,

                new HtmlHelperOptions()

            );


            await viewResult.View.RenderAsync(viewContext);

            return sw.ToString();

        }

    }

}

在函数中添加类:ConfigureServices

services.AddScoped<IViewRenderService, ViewRenderService>();

最后,使用服务

string html = await m_RenderService.RenderToStringAsync("<NameOfPartial>", new Model());



查看完整回答
反对 回复 2022-09-04
?
元芳怎么了

TA贡献1798条经验 获得超7个赞

为什么 Json 结果带有 html 字符串?您可以直接返回分部视图以返回 html。


public IActionResult GetUpsertPartialView(MessageBoard messageBoard)

{


    return PartialView("someviewname", messageBoard);

}


查看完整回答
反对 回复 2022-09-04
?
忽然笑

TA贡献1806条经验 获得超5个赞

扩展Aharon的答案,它解决了OP的“纯”标题问题,即如何将部分呈现为字符串,我在下面添加了我自己的解决方案。我的是直接从控制器操作中执行此操作。


当然,OP不应该在他们的用例中使用它,因为例外的答案是正确的。


该方法是您自己的。CreateViewModelAsync


// SomeController.cs


public SomeController(

    IHtmlGenerator htmlGenerator, ICompositeViewEngine viewEngine,

    IModelMetadataProvider metadataProvider, IViewBufferScope bufferScope,

    HtmlEncoder htmlEncoder, UrlEncoder urlEncoder,

    ModelExpressionProvider modelExpressionProvider)            

{

    this.viewEngine = viewEngine;

    this.cardHtmlHelper = new HtmlHelper<TimesheetCardModel>(

        htmlGenerator, viewEngine, metadataProvider, bufferScope,

        htmlEncoder, urlEncoder, modelExpressionProvider);

}


[HttpGet]

[Route("test", Name = "TestRoute")]

public async Task<IActionResult> GetTest()

{

    // Example renders a partial view as HTML using MotherModel.Children.First() as

    // the model for the partial.


    MotherModel viewModel = await this.CreateViewModelAsync();


    const string viewName = "_MyPartial";


    var foundView = this.viewEngine.FindView(this.ControllerContext, viewName, false);

    var viewData = new ViewDataDictionary<FirstChildModel>(this.ViewData);

    

    var textWriter = new StringWriter();

    var viewContext = new ViewContext(this.ControllerContext, foundView.View, viewData, this.TempData, textWriter, new HtmlHelperOptions());

    

    this.cardHtmlHelper.Contextualize(viewContext);


    var htmlContent = await this.cardHtmlHelper.PartialAsync(viewName, pageModel.Children.First(), viewData);


    htmlContent.WriteTo(textWriter, HtmlEncoder.Default);


    var html = textWriter.ToString();


    ...

}


查看完整回答
反对 回复 2022-09-04
  • 4 回答
  • 0 关注
  • 65 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信