DomBurf
DomBurf

Reputation: 2522

Can you use ViewComponents with Razor pages?

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

Answers (2)

Albert Laure
Albert Laure

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

Iztoksson
Iztoksson

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

Related Questions