Copied to clipboard

Flag this post as spam?

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


  • Tue Marquardsen 2 posts 82 karma points
    Mar 29, 2020 @ 10:43
    Tue Marquardsen
    0

    CustomViewModel does not contain fields from CMS

    Hello

    I am trying to start up a MVC Umbraco site with custom controllers and therefore also custom view models. I followed the guide online, and mostly that was easy, but when I start accessing the fields defined in CMS pages i get errors.

    My model:

    public class CustomHomeViewModel : ContentModel
    {        
        public CustomHomeViewModel(IPublishedContent content) : base(content) { }        
        public string MyProperty1 { get; set; }            
    }
    

    My controller:

    public class HomeController : Umbraco.Web.Mvc.RenderMvcController
    {        
        public readonly ILog _logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
    
        public override ActionResult Index(ContentModel model)
        {
            var myCustomModel = new CustomHomeViewModel(model.Content);            
            myCustomModel.MyProperty1 = "TEST";
            return CurrentTemplate(myCustomModel);            
        }
    }
    

    My view:

    enter image description here

    I can call and get the field values as here:

    @Model.Content.Value("HeroBackgroundImage") 
    

    But then i loose the object type if its an Image or so and I want to get the Url.

    I want to define a page with fields and such in the CMS and add extra fields in the controller, and render them in the view.

    How is this supposed to be done properly. Hope someone can help...

  • Marc Goodson 2141 posts 14344 karma points MVP 8x c-trib
    Mar 30, 2020 @ 06:33
    Marc Goodson
    100

    Hi Tue

    Umbraco has several approaches for writing out the values of properties inside a view, and these have been simplified in V8.

    The two main ways now are using IPublishedContent.

    eg

    @inherits UmbracoViewPage
            @(
            var pageTitle = Model.Value<string>("title");
            var heroBackgroundImage = Model.Value<IPublishedContent>("HeroBackgroundImage");
            }
            <div style="background-image: @heroBackgroundImage.Url">
        <h1>@pageTitle</h1>
    </div>
    

    Notice by specifying the 'type of content' your property value is represented by how Umbraco converts it for you to be that useful type, eg in the scenario where your HeroBackgroundImage is actually storing the id of an image, requesting it this way, Umbraco retrieves the image as IPublishedContent ready to use...

    Also note there is no specific model specified, just UmbracoViewPage - this makes the underlying Model of type ContentModel... except....

    Modelsbuilder

    To make the syntax slightly nicer in views, a third party plugin called Modelsbuilder was added to the core of Umbraco, this 'generates' POCO c# classes that represent each Document Type, and the properties of these classes are 'wrappers' for the Model.Value

    public IPublishedContent HeroBackgroundImage { get { return Model.Value<IPublishedContent>("heroBackgroundImage");}}
    

    and enables you to specify the type of Modelsbuilder generated content at the top of the view, and write out the properties with nice syntax

    @inherits UmbracoViewPage<HomePage>
           @(
                }
                <div style="background-image: @Model.HeroBackgroundImage.Url">
            <h1>@Model.Title</h1>
        </div>
    

    which is less to write in terms of syntax, but slightly hides how the content is being read from Umbraco... hence it can be confusing when you are trying to work out what is going on and how to extend!

    Anyway the Modelsbuilder approach by default generates the Models into memory, this is called PureLive mode - there are settings for the mode in the web.config appsettings...

    This is the simplest approach, every time you change a doc type, the Pure Live models regenerate on the fly...

    however in PureLive mode you can't refer to these Models in VisualStudio, they don't exist when the project is compiling...

    But you can run 'ModelsBuilder' in appdata mode, this generates the c# POCO classes into the App_data folder, you can include these files in Visual Studio, and benefit from intellisense, they are generated as Partial Classes so you can extend them with another Partial Class of the same name, or inherit from them and extend...

    https://our.umbraco.com/documentation/reference/templating/modelsbuilder/Understand-And-Extend

    Therefore if you make your CustomViewModel inherit from the generated Modelsbuilder model, you can extend with the additional property, as you have in your Controlller, but benefit from the existing properties being generated by Modelsbuilder.

    Is this the best approach? a lot will depend on the complexity of your site, whether you are regularly moving changes between environments and your feelings about using generated code...

    But hopefully this answer explains why it is you are 'losing' the properties you thought you had when inheriting from ContentModel...

    So you can either inherit from the Modelsbuilder class, and possibly change the Modelsbuilder mode to enable you to do so or just use the more verbose Model.Value<T>("propertyAlias") syntax in your views for writing out Umbraco properties...

    regards

    Marc

  • Tue Marquardsen 2 posts 82 karma points
    Mar 30, 2020 @ 07:21
    Tue Marquardsen
    0

    Thank you very much! That just saved my day, after having spend loads of time trying to figure that out on my own.

Please Sign in or register to post replies

Write your reply to:

Draft