The Models Builder properties are read only so how can I set them?
The properties created by the Models Builder are all read only. How can make these properties settable?
Maybe it's a silly question but I want to be able to manipulate the values of some Models Builder object properties in my code and pass the objects around rather than creating extra variables to hold the manipulated values.
How have you got on with this. I also are trying to use a properties in code so as I don't have to duplicate them in code. Buy them=y are all read only.
You can create a partial class for the modelsbuilder object and override the properties you want to manipulate with ImplementPropertyType decoration.
You can use something like this:
public partial class DetailPage
{
[ImplementPropertyType("relatedPages")]
public IEnumerable<IPublishedContent> RelatedPages => RelatedContentComposition.GetRelatedPages(this);
}
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Web;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Web;
using Umbraco.ModelsBuilder;
using Umbraco.ModelsBuilder.Umbraco;
namespace IBDStarterKit.Models
{
///
Window Tiles
[PublishedModel("IBDWindowTilesComponent")]
public partial class IbdWindowTilesComponent : PublishedContentModel
{
// helpers
pragma warning disable 0109 // new is redundant
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder", "8.1.6")]
public new const string ModelTypeAlias = "IBD_Window_Tiles_Component";
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder", "8.1.6")]
public new const PublishedItemType ModelItemType = PublishedItemType.Content;
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder", "8.1.6")]
public new static IPublishedContentType GetModelContentType()
=> PublishedModelUtility.GetModelContentType(ModelItemType, ModelTypeAlias);
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Umbraco.ModelsBuilder", "8.1.6")]
public static IPublishedPropertyType GetModelPropertyType<TValue>(Expression<Func<Ibd_Window_Tiles_Component, TValue>> selector)
=> PublishedModelUtility.GetModelPropertyType(GetModelContentType(), selector);
public partial class Ibd_Window_Component {
[ImplementPropertyType("windowTiles")]
public IEnumerable<Ibd_Window_Tile> WindowTiles => RelatedContentComposition.GetRelatedPages(this);
}
But its not quit there RelatedContentComposition is underlined in red.
You need to add your custom implementation in that place, you just copied my custom implementation ;)
You can do something like this:
[ImplementPropertyType("windowTiles")]
public IEnumerable<Ibd_Window_Tile> WindowTiles
{
get
{
// Do custom stuff here
// This is what the basic modelsbuilder returns
return this.Value<IEnumerable<Ibd_Window_Tile>>("windowTiles");
}
}
I suggest you create a new file with the partial class in so it doesn't get overwriten when you rebuild your modelsbuilder models.
Then you can rebuild your UmbracoModels (the basic implementation in the generated models file will then disapear)
Thanks Eric I understand that and I have my partial declaration in an other file etc.
And I have done this before to add new variables to the class. But they are new variables. not modifying the old ones so the extent of my knowledge there is to do something like
public partial class Ibd_Window_Component { // Where this is my doc type
public string AdditonalString {get;set;}
}
But this is not what Im trying to do.
I want to use it like this in a controller for setting my the content of the model to pass to a partial view
So this is the code I use at present that is a direct duplication of the doctypes. Which I are trying to get away from.
Ibd_Window_Tiles Model = new Ibd_Window_Tiles();
Model.WindowHeading = "Hello";
Model.WindowTiles = new List<Ibd_Window_Tile>();
...........
Ibd_Window_Tile Tile= new Ibd_Window_Tile();
Model.WindowTiles.Appent(Tile);
etc.
the problem is that if I use the doctype version IbdWindowTiles_Componet etc then the error is that WindowHeading is read only.
Is my question is still, I know I need to put something in the // Do something here.
But I don't understand and cant find any examples of what to put here.
There must be a way of doing this without duplicating code.
Perhaps I misunderstand you, but is it correct that you don't get the tile content from Umbraco (since you are populating it in code)?
If this is the case, why not create a custom viewmodel and pass this model to the partial view?
With the override example you can return whatever you want, for example:
[ImplementPropertyType("windowTiles")]
public IEnumerable<YourCustomModel> WindowTiles
{
get
{
// Do custom stuff here
return new List<YourCustomModel> {
new YourCustomModel {
Title = "This is the title"
}
};
}
}
Thanks Erik for the conversation. Please bare with me.
So the majority of the time I want to populate the data from the CMS environment. But I also have an instance where I want to populate it from the controller on code and pass it back to the partial view.
So the at present I have a duplicate model's coded to match the doctype's (models builder model).
Then I have duplicate partial views dependant on if it is the coded model or the doctype.
So I really want to eliminate the coded model so as I can populate a doctype in code then pass it to the same partial view.
Yes you can implement your own version of the property in a partial class like you have suggested but you can't set the change the value later on in code.
What I have done is duplicate the properties with a get/set so I might have
[ImplementPropertyType("title")]
public string Title => this.Value<string>("title");
and then I'll create another in my partial class that I can change
The Models Builder properties are read only so how can I set them?
The properties created by the Models Builder are all read only. How can make these properties settable?
Maybe it's a silly question but I want to be able to manipulate the values of some Models Builder object properties in my code and pass the objects around rather than creating extra variables to hold the manipulated values.
I hope that makes sense.
Thanks,
Matt
How have you got on with this. I also are trying to use a properties in code so as I don't have to duplicate them in code. Buy them=y are all read only.
Hi Matt,
You can create a partial class for the modelsbuilder object and override the properties you want to manipulate with ImplementPropertyType decoration.
You can use something like this:
Does this help?
Erik
Hi Erik sort of just trying to relate it back to my situation.
My Modul builder deck looks like this
//------------------------------------------------------------------------------ // //------------------------------------------------------------------------------
using System; using System.Collections.Generic; using System.Linq.Expressions; using System.Web; using Umbraco.Core.Models; using Umbraco.Core.Models.PublishedContent; using Umbraco.Web; using Umbraco.ModelsBuilder; using Umbraco.ModelsBuilder.Umbraco;
namespace IBDStarterKit.Models { ///
pragma warning disable 0109 // new is redundant
pragma warning restore 0109
So I have added this declaration
But its not quit there RelatedContentComposition is underlined in red.
Hi Daniel,
You need to add your custom implementation in that place, you just copied my custom implementation ;)
You can do something like this:
I suggest you create a new file with the partial class in so it doesn't get overwriten when you rebuild your modelsbuilder models.
Then you can rebuild your UmbracoModels (the basic implementation in the generated models file will then disapear)
Thanks Eric I understand that and I have my partial declaration in an other file etc.
And I have done this before to add new variables to the class. But they are new variables. not modifying the old ones so the extent of my knowledge there is to do something like
But this is not what Im trying to do.
I want to use it like this in a controller for setting my the content of the model to pass to a partial view
So this is the code I use at present that is a direct duplication of the doctypes. Which I are trying to get away from.
etc.
the problem is that if I use the doctype version IbdWindowTiles_Componet etc then the error is that WindowHeading is read only.
Is my question is still, I know I need to put something in the // Do something here.
But I don't understand and cant find any examples of what to put here.
There must be a way of doing this without duplicating code.
Hi Daniel,
Perhaps I misunderstand you, but is it correct that you don't get the tile content from Umbraco (since you are populating it in code)?
If this is the case, why not create a custom viewmodel and pass this model to the partial view?
With the override example you can return whatever you want, for example:
Thanks Erik for the conversation. Please bare with me.
So the majority of the time I want to populate the data from the CMS environment. But I also have an instance where I want to populate it from the controller on code and pass it back to the partial view.
So the at present I have a duplicate model's coded to match the doctype's (models builder model).
Then I have duplicate partial views dependant on if it is the coded model or the doctype.
So I really want to eliminate the coded model so as I can populate a doctype in code then pass it to the same partial view.
Hello Erik,
Yes you can implement your own version of the property in a partial class like you have suggested but you can't set the change the value later on in code.
What I have done is duplicate the properties with a get/set so I might have
and then I'll create another in my partial class that I can change
is working on a reply...