Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • John 7 posts 108 karma points
    16 days ago
    John
    0

    Definitions not found on partial views

    This is my first Umbraco site, and I'm not experienced with MVC, so bear with me.

    I'm having trouble accessing composition property values in my partial views. I have a Master Template that calls a partial view called _header.cshtml. Here is the code for that partial view.

    @inherits UmbracoViewPage<IHeaderProperties>
    
    <img src="@Model.PageHeaderImage.Url()" alt="@Model.pageHeaderImageAltText" class="img-fluid"  />
    <h1>@Model.Title is the header title</h1>
    

    The Master Template calls this via:

    @await Html.PartialAsync("~/Views/Partials/_header.cshtml")
    

    No worries there. However, while @Model.PageHeaderImage.Url() is found and renders beautifully, @Model.pageHeaderImageAltText throws a message saying,

    'IHeaderProperties' does not contain a definition for 'pageHeaderImageAltText'...

    The same holds true for other properties in the Document Types > Compositions > Header Properties that I've created - but strangely, not all of them.

    There has to be a basic thing I'm missing here. Why would I be able to access some of the properties in a composition, but not all of them?

  • Marc Goodson 2097 posts 13921 karma points MVP 8x c-trib
    16 days ago
    Marc Goodson
    100

    Hi John

    When you render a partial view like you have,

    @await Html.PartialAsync("~/Views/Partials/_header.cshtml")

    and don't specify the Model to use with the Partial

    eg

    @await Html.PartialAsync("~/Views/Partials/_header.cshtml", someModelHere)

    Then it will default to use the same model as the view which called it.

    Here your Master Template is typed to use IHeaderProperties and my guess is this is an interface generated by a composition?

    and the error is saying that this interface does not include a property called 'pageHeaderImageAltText'

    is that property defined on the Header Properties composition?

    (it feels like it would be?)

    If so then it sounds like your generated IHeaderProperties modelsbuilder interface might be 'out of date' - and you might need to visit the settings section of the site and click generate models, on the modelsbuilder tab. depending which 'modelsbuilder mode' you are running in, you then might need to rebuild the solution in Visual Studio for the properties to be available in the interface. (if it's a manually created interface, you just need to add the properties there).

    If that's the case then the pageHeaderImageAltText will almost definitely have an upper case p, Model.PageHeaderImageAltText...

    ... finally if the property isn't on the Header Properties Composition, this is why it is not part of the interface!

    But wherever you are in a view you should always be able to access the underlying IPublishedContent object associated with the request eg

    @{
    var currentPage = Umbraco.AssignedContentItem;
    }
    @currentPage.Value<string>("pageHeaderImageAltText");
    

    would be a non strongly typed way of accessing things, or depending on which composition it is defined on, that will have an associated interface/model to use, but that doesn't sound like it is the case!

    hope that helps!

    regards

    Marc

  • John 7 posts 108 karma points
    15 days ago
    John
    1

    I really appreciate your reply, Marc! Just prior to your reply, I got this code to work for me in the _header.cshtml partial view.

    @inherits UmbracoViewPage<IHeaderProperties>
    @ {
         var alt = Model.Value<string>("pageHeaderImageAltText");
         <img src="@Model.PageHeaderImage.Url()" alt="@alt" class="img-fluid"  />
    } 
    

    The code you posted also worked. I needed to assign it to a value that was then accessed inside the code block.

    @inherits UmbracoViewPage<IHeaderProperties>
    @{
      @* Successful Test Code *@
      var currentPage = Umbraco.AssignedContentItem;
      var alt = currentPage.Value<string>("pageHeaderImageAltText");
      <img src="@Model.PageHeaderImage.Url()" alt="@alt" class="img-fluid"  />
    }
    

    This was exceptionally useful advice!

    While this issue is solved for me, I’m curious about value I would pass for the Model in the PartialAsync() method. All of the ones I tried failed. What would be an example?

  • Danine Noble 57 posts 242 karma points
    15 days ago
    Danine Noble
    1

    The model you pass into the partial view call must match the content type for what your cshtml model is set to inherit. So in this example it's IHeaderProperties.

    It could be handy in some cases (maybe this one) to inherit something more generic and then check for more specific types to action on. For example, if the model you need to pass into the _header.cshtml is potentially various page types you could do something like this:

    @inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage<ContentModels.IPublishedContent>
    @using ContentModels = Umbraco.Cms.Core.Models.PublishedContent;
    @{
        // IPublishedContent is a catch-all type for all published content models
        // IPublishedElement being another but for element types specifically (ie: block list elements)
    
        if (Model is not IHeaderProperties header)
        {
            // this checks that the Model has the IHeaderProperties composition
            // if not, you can log a message here
            return;
        }
    
        // If it succeeds, you can use the output 'header' variable 
        // in place of 'Model' going forward as a strongly-typed IHeaderProperties model
    }
    

    Or, depending on where you wanna manage the model casting, you could essentially do that 'Model is this' check before the Partial View method. Something like:

    var headerModel = Model as IHeaderProperties;
    // check for null, then pass to view as Marc exampled previously :3
    
Please Sign in or register to post replies

Write your reply to:

Draft