Как вызвать 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;
}
}