在C#服务中将View Component的结果作为字符串变量返回

时间:2018-11-23 09:22:44

标签: c# asp.net-core asp.net-core-viewcomponent

我对.NET Core有点陌生,我目前有一个生成电子邮件并以字符串形式返回的服务,但是我有一个View组件,我通常在其中调用我的视图并将结果附加到已经存在的视图中字符串:

string result = @await Component.InvokeAsync("Widget", new { widgetZone = "stock_levels_summary_cart_price", additionalData = product.Id })
sb.AppendLine($"<td style=\"padding: 0.6em 0.4em;text-align: center;\">{result}</td>");

如何在我的服务中调用此视图组件并将结果传递到可以在我的电子邮件服务中使用的字符串中

1 个答案:

答案 0 :(得分:0)

我能够通过为视图组件创建局部视图来实现这一点:

在局部视图中,我声明了我的视图组件:

@model int

@await Component.InvokeAsync("Widget", new { widgetZone = "stock_levels_summary_cart_price", additionalData = Model})

在我的控制器中创建了如下操作:

public virtual PartialViewResult OrderDetailsStocklevel(int productId)
    {

        return PartialView("~/Views/Shared/_OrderDetailsStocklevel.cshtml", productId);
    }

然后实现了一项服务,以渲染部分视图内容并返回结果:

            using System;
            using System.IO;
            using System.Threading.Tasks;
            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;

            namespace Nop.Services.Helpers
                {

                    public interface IViewRenderHelper
                    {
                        string RenderToString(string viewName, object model, string viewPath);
                    }

                public class ViewRenderHelper : IViewRenderHelper
                {
                    private readonly IServiceProvider _serviceProvider;

                    public ViewRenderHelper(IServiceProvider serviceProvider)
                    {
                        _serviceProvider = serviceProvider;
                    }

                    public string RenderToString(string viewName, object model, string viewPath)
                    {
                        var httpContext = new DefaultHttpContext { RequestServices = _serviceProvider };
                        var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());

                        var engine = _serviceProvider.GetService(typeof(IRazorViewEngine)) as IRazorViewEngine;
                        var tempDataProvider = _serviceProvider.GetService(typeof(ITempDataProvider)) as ITempDataProvider;

                        if (engine == null)
                        {
                            throw new Exception("Can't find IRazorViewEngine");
                        }


                        var viewEngineResult = engine.FindView(actionContext, viewPath, false);

                        if (!viewEngineResult.Success)
                        {
                            throw new InvalidOperationException($"Couldn't find view '{viewName}'");
                        }

                        var viewDictionary = new ViewDataDictionary(new EmptyModelMetadataProvider(), new ModelStateDictionary())
                        {
                            Model = model
                        };


                        using (var output = new StringWriter())
                        {
                            var viewContext = new ViewContext(actionContext, viewEngineResult.View,
                                viewDictionary, new TempDataDictionary(actionContext.HttpContext, tempDataProvider),
                                output, new HtmlHelperOptions());

                            viewEngineResult.View.RenderAsync(viewContext).GetAwaiter().GetResult();

                            return output.ToString();
                        }



                    }
                }
            }

然后加载从视图组件创建的局部视图,执行以下方法:

             var stockLevelLabel = _viewRenderService.RenderToString("stocklevel", orderItem.ProductId, "_OrderDetailsStocklevel");