Reputation: 2522
I have come across what appears to be a limitation with using ViewComponent's in ASP.NET Core 2.0.
We have a ViewComponent that works absolutely perfectly when invoked from a layout page. When we invoke the same ViewComponent from a Razor page we get the following error.
The model item passed into the ViewDataDictionary is of type <viewcomponenttype> but this ViewDataDictionary instance requires a model item of type <parentpagetype>
The ViewComponent seems to expect the model type of the parent Razor page to be passed, rather than the model type defined for the ViewComponent.
I haven't come across any examples of a ViewComponent being used from a Razor page, they only seem to be used from layout pages (which don't have models).
Can someone give me a definitive yes or no to the question: can you use ViewComponent's within a Razor page, and if so, how?
Upvotes: 4
Views: 3979
Reputation: 1722
Additionally on the answer by Iztoksson, if you are well versed in using tag helpers, you may use it in invoking the ViewComponent
<div>
<vc:SampleView testVm = "new { testVm = new Models.TestVm() }"></vc:SampleView>
</div>
although you have to register the viewcomponents tag in the
ViewImports.cshtml
file and add the following line to the existing code:
@addTagHelper *, RazorPages
Upvotes: 4
Reputation: 990
Yes you can, I made a quick example with a hilarious naming.
View component class - SampleViewViewComponent :)
namespace NetCoreUI.ViewComponents
{
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
public class SampleViewViewComponent : ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync(Models.TestVm testVm)
{
testVm.TestName = "Changing name from ViewComponent.";
return View(testVm);
}
}
}
Default view for this View component:
@model NetCoreUI.Models.TestVm
<h1>This is viewcomponent.</h1>
<p>@Model.TestId</p>
<p>@Model.TestName</p>
My Razor page code with not much going on:
namespace NetCoreUI.Pages.Motorcycle
{
using Microsoft.AspNetCore.Mvc.RazorPages;
public class SampleModel : PageModel
{
public void OnGet()
{
}
}
}
And finally a Razor page view where I invoke my ViewComponent:
@page
@model NetCoreUI.Pages.Motorcycle.SampleModel
@{
ViewData["Title"] = "Sample";
}
<h2>Sample</h2>
<div>
@await Component.InvokeAsync("SampleView", new { testVm = new Models.TestVm() })
</div>
I chose to invoke my ViewComponent with a simple new TestVm() class, but this class could be subset inside SampleModel and you could invoke your View Component with that instance of the correct class - the correct class be the one your ViewComponent is referencing.
This is a really simple example, I'm not sure how your app is structured or perhaps there's a different issue.
Upvotes: 3