Search code examples
c#.net-corerazor-pages

ASP.NET Core Razor Pages, passing viewData to partial view


Let's say I want to pass in a product card to my partial view. I would like to pass the product model into the partial view as well as some non-model variables that will basically just add on classes for css styling on individual cards. I have passed in my product model and the non-model variables classList, isFeatured, and isBestSelling via the partial tag helper code below

@for (var i = 0; i < 24; i++) 
{
    var classList = new List<string>();
    var isFeatured = i == 0;
    var isBestSelling = i == 1 || i == 2;

    if (isFeatured)
    {
        classList.Add(@"border");
        classList.Add(@"border-secondary");
    } 
    else if (isBestSelling) 
    {
        classList.Add(@"border");
        classList.Add(@"border-success");
    }

    var product = Model.Products[i];

    <div class="col-12 col-tablet-6 col-laptop-4 col-desktop-3 my-3">
        <partial name="_ProductCardPartial" model="product" view-data='new ViewDataDictionary(ViewData){ { "isBestSelling", isBestSelling }, { "isFeatured", isFeatured }, { "classList", classList } }'/>
    </div>
}

How can I access that ViewData on the partial as its model is not the index page that contains the ViewData and I am not passing that in as its model. I have looked at examples from Microsoft Docs. And they are just using the new ViewData dictionary they passed in to the partial view no problem, which doesn't work for me.

I have tried initializing a new instance of the Index type (which holds the PageModel and inherited ViewData) in the partial and setting variables from the view data like so:

@{
    var data = new Index();
    bool isFeatured = (bool)data.ViewData["isFeatured"];
    bool classList = (bool)data.ViewData["classList"];
    bool isBestSelling = (bool)data.ViewData["isBestSelling"];
}

Yes I have the correct using statement to use this type. I get this error when building still

Error CS0120: An object reference is required for the non-static field, method, or property 'RazorPageBase.WriteLiteral(object?)

I have tried to just use the entire path to the Index PageModel like so:

Pages.Pages_Index.ViewData["isFeatured"]

and then I get the following error:

An object reference is required for the non-static field, method, or property 'Pages_Index.ViewData'

At this point I am not sure how I can reference the variables inside the partial view.


Solution

  • ViewData dictionary is not related to the model.

    Example:

    Index.cshtml

    @page
    @model IndexModel
    @{
        ViewData["Title"] = "Home page";
    }
    
    @foreach(var product in Model.Products)
    {
        <partial name="_ProductPartial"
                 model="product"
                 view-data='@new ViewDataDictionary(ViewData) { { "Param1", "abc" }, { "Param2", "def" } }' />
    }
    

    _ProductPartial.cshtml

    @model Product
    
    <div class="card">
        <div class="card-body">
    
            <p>@ViewData["Param1"]</p>
            <p>@ViewData["Param2"]</p>
    
            <p>@Model.Id</p>
            <p>@Model.Name</p>
    
        </div>
    </div>
    

    I created a small demo project on github . It works as expected.