Как вызвать View Component из контроллера

Можно ли вызвать компонент View из контроллера и отобразить его в строку? Я действительно ищу пример кода для этого. Любая помощь будет высоко ценится.

6 ответов

Решение

Вы можете сделать это, но вы должны применить следующую вещь, так как она визуализируется DefaultViewComponentHelper.

Вы должны создать экземпляр этого и создать то, что вам нужно IViewComponentSelector и IViewComponentInvokerFactory.

Для этого я сделал следующее.

public class HomeController : Controller
    {
        Microsoft.AspNet.Mvc.DefaultViewComponentHelper helper = null;
        Microsoft.AspNet.Mvc.Razor.RazorView razorView = null;
        public HomeController(IViewComponentSelector selector,IViewComponentInvokerFactory factory,IRazorPageFactory razorPageFactory,IRazorPageActivator pageActivator,IViewStartProvider viewStartProvider)
        {
            helper = new DefaultViewComponentHelper(selector, factory);
            razorView = new Microsoft.AspNet.Mvc.Razor.RazorView(razorPageFactory, pageActivator, viewStartProvider);           
        }
        public IActionResult Index()
        {                  
            ViewContext context = new ViewContext(ActionContext, razorView, ViewData, null);
            helper.Contextualize(context);
            string st1 = helper.Invoke("My", null).ToString();
            return View();
        }
}

Вот мой образец View View.

 public class MyViewComponent : ViewComponent
    {     

        public MyViewComponent()
        {

        }

        public IViewComponentResult Invoke()
        {
            return Content("This is test");
        }
    }

Начиная с бета7, теперь можно возвращать ViewComponent непосредственно из контроллера. Проверьте MVC/Razor раздел объявления

Новый ViewComponentResult в MVC позволяет легко возвращать результат ViewComponent из действия. Это позволяет вам легко представить логику ViewComponent в качестве отдельной конечной точки.

Так что теперь код для возврата компонента примера представления просто должен быть:

public class HomeController : Controller
{
    public IActionResult Index()
    {
        return ViewComponent("My");
    }
}

Пожалуйста, обратитесь к примеру из официальной статьи ASP.NET на ViewComponent

В их примере компонент вида вызывается непосредственно из контроллера следующим образом:

public IActionResult IndexVC()
{
    return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
}

Вот вспомогательный тег, который я создал для встраивания компонентов через синтаксис HTML. Вызов из TagHelper, подобный этому, должен точно соответствовать вызову из контроллера.

ViewComponent Tag Helper

using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewComponents;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;


namespace TagHelperSamples.Web
{
    [HtmlTargetElement("component")]
    public class ComponentTagHelper : TagHelper
    {
        private DefaultViewComponentHelper _componentHelper;

        [HtmlAttributeName("name")]
        public string Name { get; set; }

        [HtmlAttributeName("params")]
        public object Params { get; set; }

        [ViewContextAttribute] // inform razor to inject
        public ViewContext ViewContext { get; set; }

        public ComponentTagHelper(IViewComponentHelper componentHelper)
        {
            _componentHelper = componentHelper as DefaultViewComponentHelper;
        }

        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {       
            _componentHelper.Contextualize(ViewContext);

            output.Content.AppendHtml(
                await _componentHelper.InvokeAsync(Name, Params)
            );
        }
    }
}

использование

<component name="RecentComments" params="new { take: 5, random: true }"></component>

Код из ответа dotnetstep обновлен для MVC 6.0.0-beta4 (VS2015 RC):

public class HomeController : Controller
    {
        Microsoft.AspNet.Mvc.ViewComponents.DefaultViewComponentHelper helper = null;

        public HomeController(IViewComponentDescriptorCollectionProvider descriptorProvider, IViewComponentSelector selector, IViewComponentInvokerFactory invokerFactory)
        {
            helper = new DefaultViewComponentHelper(descriptorProvider, selector, invokerFactory);
        }
        public IActionResult Index()
        {                  
            ViewContext context = new ViewContext(ActionContext, null, ViewData, null, null);
            helper.Contextualize(context);
            string st1 = helper.Invoke("My", null).ToString();
            return View();
        }
}

На основе https://gist.github.com/pauldotknopf/b424e9b8b03d31d67f3cce59f09ab17f

      public class HomeController : Controller
{
    public async Task<string> RenderViewComponent(string viewComponent, object args)
    {
    var sp = HttpContext.RequestServices;
        
    var helper = new DefaultViewComponentHelper(
        sp.GetRequiredService<IViewComponentDescriptorCollectionProvider>(),
        HtmlEncoder.Default,
        sp.GetRequiredService<IViewComponentSelector>(),
        sp.GetRequiredService<IViewComponentInvokerFactory>(),
        sp.GetRequiredService<IViewBufferScope>());
    
    using (var writer = new StringWriter())
    {
        var context = new ViewContext(ControllerContext, NullView.Instance, ViewData, TempData, writer, new HtmlHelperOptions());
        helper.Contextualize(context);
        var result = await helper.InvokeAsync(viewComponent, args);
        result.WriteTo(writer, HtmlEncoder.Default);
        await writer.FlushAsync();
        return writer.ToString();
    }
}
}

и

      public class NullView : IView
{
    public static readonly NullView Instance = new();

    public string Path => string.Empty;

    public Task RenderAsync(ViewContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        return Task.CompletedTask;
    }
}
Другие вопросы по тегам