The Models Builder has shipped with Umbraco for a while now and so far reactions seem to fit into three categories:
"Best thing since sliced bread, could not live without it anymore!"
"What an ugly mess. Can you disable it all by default?"
silence
Before it shipped with Umbraco, the Models Builder was mostly used by "advanced" devs, ie by people whose feedback would go "it would be nice if the generated classes could be marked with the GeneratedCodeAttribute". That type of concerns.
I'm starting this thread to try to collect feedback from "the vast majority", people who never used it before. Factual feedback, that is: apart from "lacking documentation", being "fantastic" or "a pain", practically, what issues are you encountering? Where are you wasting time? What's hard to understand / not working / not obvious / a pain?
This is a unique opportunity to rant: it does not have to be constructive, just describe your best Models Builder WTF moments.
First of all i gotta say this is an AWESOME feature, and when i understood it it started saving me a good amount of time on smaller projects.
My "war story" was that i tried just when it was hot out the oven but didnt completly understand that there where different states(pureLive, Dll etc) and when to use what. But out of the box when i started using it it crashed my application when ever i rebuild the solution. Then i spoke to Stephan about it here :
So this fixed it for me, but what i prob wanted was a documentation(i know there was blogposts which are great) but on our, and maybe also a "state" switcher on the Modelsbuilder dashboard where it said, the dll mode does this.
Also on another project i tried using it but inheriting the model, to build my own models from, but it didnt work for me i got some error when i tried inheriting it. Im sure it can be done but a small guide or how to in the doc would be awesome :)
So far I've used it on a few smaller projects to get familiar with it (I hadn't used the old Zbu.ModelsBuilder before it became part of the core).
And I really like it. It's a great timesaver to not have to update model classes manually and being able to use strongly typed models across the whole website.
I tend to use 'Dll' mode (should probably switch to 'LiveDll' now).
The one thing that is a bit annoying is how the override of model classes by adding a custom MyDocType.cs file in the App_Data\Models folder can conflict if that file is set to 'Compile' in your VS project.
I have to set it to 'Content' so it won't be included in my project DLL (which otherwise would cause a conflict with the MyDocType class existing in two assemblies). But this causes the C# IntelliSense to no longer work, and not picking up on any syntax errors. So I often end up switching the file between 'Compile' and 'Content' if I need to make any changes.
I have not been able to test it yet, but I'm really looking forward to test it out in my next project. Lacking the ability to use strongly typed models has been the only pain point in switching from EPiServer to Umbraco.
I guess a 10 min screencast would sort out a lot of confusion. Where the first minute is like: "If you don't want to use strongly typed models you just do A and B, then you never have to think about it again". The next/last part should show a simple example on how it is intended to be used... As of now, it seems that people are implementing this differently.
This tale should be viewed with the understanding I'm not a beginner but don't consider myself an advanced coder, i.e. looking for "Code First" solutions. I'm a web developer, not a "computer progammer". Coding is just something that has to be done to get the web site to work, though all sites I build are done using Visual Studio. So...
I'd heard in the general umbraco chatter that a Models Builder was available. I thought it might help with my biggest bug-bear which is syntax. There are so many ways of doing things if you look up examples on the web. XSLT, Razor, Razor dynamic, Razor strongly typed, both with or without various Property Value Converters, it's almost endless and sometimes very time consuming to work out what's needed. Even the official documentation can be ambiguous as to which version of X it's talking about. To be able to just cut through it all sounded great.
All the above aside, I just had a small site to build. I installed Umbraco via NuGet together with all the packages I knew I'd need, again via NuGet. I logged in to the Back Office and started to create the DocTypes. When I switched back to Visual Studio to work on the generated templates and create the partials I found each template had an error on the first line. This caused a lot of consternation. After much digging around I realised the templates Umbraco was now creating required handling by a new Models Builder that had just been put into Umbraco and set as default without any information I was aware of. What followed was a mad scrabble around Google and Our to find out what was going on. Because there were no clear instructions at that time, I ended up installing all sorts of stuff into the project and even a special Visual Studio Extension. Importantly, I learned how to switch it off, which is what I ended up doing just to get some work done. I'd wasted many billable hours.
Some days later, once a few more people had asked questions on Our, there was a fairly clear explaination of how to set it up. So I had another go. What I found was that it was actually simple to set up, but it only acted on Views. Most of my functionality was in Partials, so as I saw it, it was of almost no use to me. A lot of effort to save hardly any time or complexity. In one post (*2) it was mentioned about moving interfaces to new content types. I'm afraid it got way above my level of understanding. So, until there's better documentation the first thing I do now is switch it off in Web.Config before I start defining DocTypes. Mainly so I don't have to replace the top two lines of code with @inherits Umbraco.Web.Mvc.UmbracoTemplatePage.
I know it's not a popular position but I think there is a case for delaying some functionality until the documentation is ready, or at least put a cheatsheet out immediately with full docs later. Once things are advertised as being out there, you sort of think it's ready to go for the masses.
ModelBuilder can be quite powerful but right now it also imposes some restrictions.
Not sure how, but maybe if we could mark only specific DocumentTypes to be available for ModelBuilder, it would be more controllable and keeping the "old" flexibility...
I think it's great, it does what it says on the tin.
Used it on a few smaller Umbraco projects and haven't had any issues. Although other than Archetype and Nested Content i've not really used custom data types for it.
Running it in AppData and modifying/ copying models from there. Saves a bit of time that I'd have to have used to build the models manually.
I agree though that it should be obvious to the developer how to not use this feature :) although, who wouldn't want to use it.
I think the models builder is fabulous. I'm a freelancer and I've worked in many different Umbraco setups and every company seemed to be rolling their own strong-typed models, so did I in fact. But it's always been working on the outside of Umbraco, so it's great to have something more integrated and consistant.
A few observations:
As others have mentioned, it would be great to have a configurable output directory for the model classes in AppData mode. In my workflow, I tend to extend the classes with my own business logic but that means my partial classes have bad namespaces to make them merge with the classes in AppData.
Quite often I'll click "Update Models" and it will still report that the models are out of date, even if I click away from the page and return.
It would be good for models have an auto-update option.
The different modes are set in the web.config. It would be great if it could be set in the developer dashboard. It would also help if it could explain the different modes on the dashboard, especially helpful for newbies.
I see things on the dashboard like "Static mixin getters are enabled". This sounds dead cool, but what exactly is it? It's just not clear on the dashboard and there's no link to documentation to understand it.
I wonder if there's a way to hook in our own property converters?
That would be cool.
I hope that didn't sound too critical because I'm a big fan of the models builder.
Things that have made me not want to commit to it yet include:
Upgrades
Will Umbraco upgrades break it?
Would there be "out of band" upgrades if needed?
Worried my "simple site" might end up doing "Crazy Ass Shit" which model builder would struggle with so I'd have to two ways of doing everything
Is it code for code sake?
My understanding is Model Builder can do your Domain Models while something like Ditto can do your View Models but I'm still not 100% sure if thats right or not?
Ease of getting it working and debugging it.
Most know I got my fingers burnt with CodeFirst but Model Builder and Ditto are different (as discussed over many G&T's). I'd love to give it a go though.
I quite like the functionality currently given, although i'm always going for the Dll setup instead of PureLive. I like to use the models in the controllers and .cs code aswell and I like keeping control of the model generation (when they are generated). I've seen some 7.4.0 sites go ballistic on beta and live servers when PureLive was enabled.
Another thing that would really help with the adoption is if we could also save and create nodes with these models. Now i'm still looking up the property alias for a content node i'm publishing and duplicating code.
I might just be inclined to disavow most of my feedback. I (finally) read through the wiki and gave PureLive with partial interfaces in App_Data/Models a go. I actually think I'm in love with a new practice. :)
This one definitely still stands, though:
Remove client-side code from main package (make another package or just bundle client stuffs with Umbraco)
As a frontend developer just wanting to get hold of the data using the @Model.MyPropertyTypeAlias syntax I was a bit confused that it was not working out of the box - Missed that I needed to change the default UmbracoTemplatePage to UmbracoViewPage to make it work.
But I guess this will be changed to be default at a later point since we're moving toward the strongly typed way of doing things? :)
Loving how much it has progressed and looking forward to see it be refined even more based on all the feedback.
Just my 2 cents based on my sparse experience so far.
I appear to be missing out on the awesomeness of this feature. I think what is needed (or what I need anyway) is clear instructions as to how to change the working methods I use to create docTypes, templates and partials to allow the modelbuilder to do it's stuff and work in partials.
I know in a bog standard MVC site (I've not done many) you would define your own view models. What needs to be done in Umbraco MVC to get it working throughout simply and is this now being taught in the new courses?
I really like the model generator and the flexibility of the different modes that suit different types of developer. I actually wrote my own basic generator (as a proof of concept), but yours is much slicker :) I haven't yet tried it on a complex project, so will see how it works when there are lots of compositions / inherited doc types. But so far, I think it will be really great and will really change the way people work.
The only negative would be the fact that there isn't documentation on Our.
One question, why is the new modifier use so much in the generated models? I couldn't quite understand why it was needed in cases like:
public new const string ModelTypeAlias = "textPage";
and the fact you have to suppress the compiler warnings? But the inheritance tree is complex, so I'm sure there is a reason! :)
We use ZBU models builder al the time. It is such a great timesaver and FUD destroyer. To be able to change some property and to be confident that the compiler will tell you where the issues are, is really helpfull.
Absolutely love the modelsbuilder and have been using it in various projects when it was still the Zbu models builder.
One thing though. I'm developing and maintaining Umbraco projects in my VS2015 environment with both the Zbu Models Builder and Umbraco Models Builder vsix plugin. After installing the latter, the Zbu shows an error in the configuration page ("an error occurred loading this property page"). Can both vsix plugins live together?
Otherwise, I'd be forced to either upgrade older Umbraco installations to vLatest that includes the Umbraco Models Builder or setup a new development environment for older projects. Both are not favourable...
Up until today my experience of 7.4.x sites were ones that been upgraded from 7.3 and earlier. I believe that when upgrading from pre 7.4, models builder would not be turned on by default.
So my WTF moment was today when I have started with my first new 7.4.x site (7.4.3) and discovered that models builder was enabled by default. If it is still true that the documentation is lacking (your word, not mine!) then I am surprised that a feature that is not properly documented on Our would be, by default, enabled.
Also - please can you point me to where the latest documentation is? I have found your own blog but not sure that this is referring to the latest version now in Core. I really want to use it on a new project so just wondering where to start! Then maybe I will have more WTF moments to report back (assuming you still want them!)
Occasionally during dev I've stopped the application to work on something then been hit by errors where the generated model files have been deleted (I'm guessing something has triggered a rebuild of the models and I stop it half way through by accident?).
The problem is I can't then build the solution as VS moans that there are missing references. What's the way of getting out of this mess?
I understand it's bad idea to include these generated model files in your VS solution but I've inherited a project where they've done just this - is this documented somewhere?
OK - I fixed it by recovering the models from source control but I suspect I should move the solution to the DLL Method and remove these included files from the solution?
I think they went missing when I did a clean of the solution - would that make sense?
I think it would be very handy if the all the aliases of the properties are also generated in the model.
This ensures that if a property is transfered to another file the naming stays consistent. Meaning that if the name of the property is changed the code still works.
Also if the name of the property is neede in some other scenario(creating nodes, search parameters etc) they can be found in the generated Model.
So for instance the property seo would look something like below. The ImplementPropertyType works with variables.
Public const string SeoAlias = "seo";
/// <summary>Seo</summary>
[ImplementPropertyType(SeoAlias)]
public SEOChecker.MVC.MetaData Seo
{
get { return this.GetPropertyValue<SEOChecker.MVC.MetaData>(SeoAlias); }
}
Actually, you can already get the alias in a strongly-typed way:
var alias = Seo.GetModelPropertyType(x => x.MetaData).PropertyTypeAlias;
Where Seo is your model class... but that's a bit... ugly.
It leads to an interesting question. The more properties we add to models, the greater the chances that someone decides to name one of their custom properties with that same name, and we have a collision.
I'd love to group all those meta-data infos eg
var alias = Seo.???.PropertyAliases.MetaData;
But I don't know how to name ???. Using Meta is what makes most sense, only your example shows why it would be a bad idea. Collisions, again. Anything complex is ugly, anything simple is a collision risk.
Sibling metadata classes discovered through attribute or method a'la IPropertyConverterMeta.
Pref not mentioned at all in typed Model class. Like how metadata for mvc Models can be separate from Models.
So, something totally out of the model class? Looks nice.
// gets the content type alias for a model
var alias = Models.Alias<Seo>();
// gets the property alias for a model property
var alias = Models.PropertyAlias<Seo>(x => x.MetaData);
// gets the IPublishedContentType for a model class
var contentType = Models.ContentType<Seo>();
// gets the IPublishedPropertyType for a model property
var propertyType = Models.PropertyType<Seo>(x => x.MetaData);
I dug a bit around. Here's two ways I like to separate metadata. They could even co-exist as two ways of building up an in-memory graph of the metadata.
[Metadata(typeof(MyModelMetadata))]
public class MyModel : PublishedModel
{
public IHtmlString SomeProperty
{
// content.getprop<>
}
}
public class MyModelMetadata
{
[Alias("someProperty")]
[Caption("Some property")]
[Editor("my-property-editor")]
[Description("whatnot")]
public IHtmlString SomeProperty;
}
or as I'd prefer, discover the metadata without metadata attr. on the model class:
[MetadataFor(typeof(MyModel))]
public class MyModelMetadata
possibly having the option of overriding when some event?
Models.For<MyModel>()
.Caption("I override some property");
Would be super sweet if metadata factory would go through interfaces and see if those have metadata if they're lacking for concretes too. At least makes sense for compositions, but might even be used for non-content properties?
I guess I took off beyond what you guys were discussing. :P
I'm not saying you should create the "baseline" metadata manually. Sibling classes like the first example could be generated. I can't put my finger on it, but it feels nice to have as clean and dependencyless as possible model adapters. Starting to lean against only having interfaces as dependencyless, so might not be worth it though.
But wouldn't it also be cool to decorate the metadata later like with the fluent syntax?
Say you'd like to use the localized label for a property in a view. You could go @Html.LabelFor(m => m.TechnicalProperty). You could also go Html.DisplayFor(m => m.Body).
Extend to typed models for Umbraco.Forms, and we go Html.EditorFor(m => m.CustomFieldType). ;)
I'm a bit lost so I'm just going to say what would be handy for me ;-).
Maybe it is indeed better to have it separate from the Models generation because it is really about DocumentTypes.
In the past we generated constants code ( and pasted it by hand in the project). We could then use it in simple calls.
If this concurs with say, the Microsoft style of doing these kinds of things, it is surely good enough. Personaly I think it's is a bit cryptic.
Last suggestion and then I will shut up about it:
var extCodePropertyalias = Models.Alias.Product.ExternalSystem_StrangeAbrevv_code;
We want the simplest, fully-generated, solution. No metadata registering or discovery, for perfs reasons. I'll toy with the various suggestions and see which is both safe and simple.
I love ModelsBuilder, I've been using it since 2014. I've put a few sites live now which rely heavily on this feature and I can't do without it now. I must say though I've found it quite tricky to get to grips with.
My workflow has changed over time and I exclusively use it in LiveAppData mode. I want to hit save in the CMS, have my models generated which I can see in my solution, and then add any partials to extend the functionality.
Gripe 1
I don't know or can't figure out how to "override" code generation for certain types of property which just return an object of type object.
For example, if I add a media picker to my document BlogEntry , and let's say it's called BlogEntryVideo, I often end up creating a new property in my own new BlogEntry.cs partial where I add some property like BlogEntryVideoUrl that fetches the actual media Url so that I don't have to mess around in my templates with the object which is actually the string media id returned by the ModelsBuilder generated property.
So I actually spend a reasonable amount of time creating new partials for each document type where I add my nice typed properties. Often I'll add a property like PageHeadingOrNodeName which I use instead of the generated PageHeading because I want a property that will fall back on something else. I don't want to write null or empty checks in my views. It would be good if I could somehow improve this workflow.
Gripe 2
This will probably come down to my own ignorance. But Composites and the generated interfaces. I really struggle with this, and a lack of full examples or documentation for how to best use composites doesn't help. I know this is touched on in the official wiki. I'm probably being really dumb, but I still don't understand how I'm supposed to generate a nice reusable custom property for my composite. To continue my earlier example, let's say I have a composite doctype called CompositePageHeading which simply adds a PageHeading text field to a doctype. I want to add my PageHeadingOrNodeName property so that it's available everywhere. If I stick this into my own partial interface for ICompositePageHeading this will break all the models that implement this interface unless I then manually create partials for all of them and implement the property over and over.
I get around by avoiding it as much as possible, by creating a BasePage doctype that my other doctypes inherit from, and generally shove most of my stuff in there. I still use composites but just accept that I'll need to implement all of my custom properties for a composite over and over in each doctype that uses it. I don't know how to have a CompositeBasePage using interfaces as opposed to an inheritance approach, without having to manually implement a bunch of custom properties rather than just extending one class once, the BasePage.
I stick a few things in my base page like HomePage which indeed walks up the content tree. In fact I do this a lot if I need to grab some special node that I need a reference to. The wiki states:
There are much cleaner solutions, such as using true view model
classes that would be populated by a true controller
I don't get it. Again, possibly my ignorance, as I'm not familiar with MVVM. I don't want to create a controller for all of my views. I don't want to have to manually create view model classes for all of my templates - this is adding work for me isn't it? So instead the documentation suggests extending Umbraco's views. Does this mean extend RenderModel? Could use an example as I'm not 100% confident about all the different classes that a template can inherit from.
Just doing my first project with Model builders and must say once you have it going it is great!
It still seems a bit hard to find out where the latest documentation is, it would be ace if it could be added to the what I consider 'official docs' here on our.
Now in my case I managed to break the frontend almost immediately since I had a composition called Content (and content seems to be a reserved word)
So would be ace if the content type editor could prevent this from happening: http://issues.umbraco.org/issue/U4-9023 (think it will also fail if you have a property with the same alias as your doctype and there must be other cases..., so again making this as dummy proof as possible by doing a check on the doc type editor would be recommended).
Also it seems that Dll or LiveDll seems to be the preferred option when using Umbraco in VS, why not have that as a default option then when installing it through Nuget?
Totally agree with Tim that if it's in the core, it's docs should be in the core docs.
+ with BIG warnings about reserved words and any other known gotchas.
+ with some basic examples, including use with partials for non-MVC experts.
It's a year on now since we were told there would be documentation on how to use the ModelsBuilder. I can't see any in the Documentation section. Having just completed the 4 to 7 Bridging Course I was keen to use ModelsBuilder on a multi-project solution in VS. Once again, I've wasted another whole day and got nowhere. From the forum I can see this is wasting many, many man-days. It's REALLY painful.
Models Builder Gripes
The Models Builder has shipped with Umbraco for a while now and so far reactions seem to fit into three categories:
Before it shipped with Umbraco, the Models Builder was mostly used by "advanced" devs, ie by people whose feedback would go "it would be nice if the generated classes could be marked with the
GeneratedCodeAttribute
". That type of concerns.I'm starting this thread to try to collect feedback from "the vast majority", people who never used it before. Factual feedback, that is: apart from "lacking documentation", being "fantastic" or "a pain", practically, what issues are you encountering? Where are you wasting time? What's hard to understand / not working / not obvious / a pain?
This is a unique opportunity to rant: it does not have to be constructive, just describe your best Models Builder WTF moments.
Thanks!
Stephan
First of all i gotta say this is an AWESOME feature, and when i understood it it started saving me a good amount of time on smaller projects.
My "war story" was that i tried just when it was hot out the oven but didnt completly understand that there where different states(pureLive, Dll etc) and when to use what. But out of the box when i started using it it crashed my application when ever i rebuild the solution. Then i spoke to Stephan about it here :
https://our.umbraco.org/forum/developers/razor/75519-modelsbuilder-the-type-exists-in-both-webdll-and-temporary
So this fixed it for me, but what i prob wanted was a documentation(i know there was blogposts which are great) but on our, and maybe also a "state" switcher on the Modelsbuilder dashboard where it said, the dll mode does this.
Also on another project i tried using it but inheriting the model, to build my own models from, but it didnt work for me i got some error when i tried inheriting it. Im sure it can be done but a small guide or how to in the doc would be awesome :)
PS. AWESOME FEATURE!
So far I've used it on a few smaller projects to get familiar with it (I hadn't used the old Zbu.ModelsBuilder before it became part of the core).
And I really like it. It's a great timesaver to not have to update model classes manually and being able to use strongly typed models across the whole website.
I tend to use 'Dll' mode (should probably switch to 'LiveDll' now).
The one thing that is a bit annoying is how the override of model classes by adding a custom MyDocType.cs file in the App_Data\Models folder can conflict if that file is set to 'Compile' in your VS project.
I have to set it to 'Content' so it won't be included in my project DLL (which otherwise would cause a conflict with the MyDocType class existing in two assemblies). But this causes the C# IntelliSense to no longer work, and not picking up on any syntax errors. So I often end up switching the file between 'Compile' and 'Content' if I need to make any changes.
How do other people tend to deal with this issue?
I have not been able to test it yet, but I'm really looking forward to test it out in my next project. Lacking the ability to use strongly typed models has been the only pain point in switching from EPiServer to Umbraco.
I guess a 10 min screencast would sort out a lot of confusion. Where the first minute is like: "If you don't want to use strongly typed models you just do A and B, then you never have to think about it again". The next/last part should show a simple example on how it is intended to be used... As of now, it seems that people are implementing this differently.
Models builder - My Experience
This tale should be viewed with the understanding I'm not a beginner but don't consider myself an advanced coder, i.e. looking for "Code First" solutions. I'm a web developer, not a "computer progammer". Coding is just something that has to be done to get the web site to work, though all sites I build are done using Visual Studio. So...
I'd heard in the general umbraco chatter that a Models Builder was available. I thought it might help with my biggest bug-bear which is syntax. There are so many ways of doing things if you look up examples on the web. XSLT, Razor, Razor dynamic, Razor strongly typed, both with or without various Property Value Converters, it's almost endless and sometimes very time consuming to work out what's needed. Even the official documentation can be ambiguous as to which version of X it's talking about. To be able to just cut through it all sounded great.
All the above aside, I just had a small site to build. I installed Umbraco via NuGet together with all the packages I knew I'd need, again via NuGet. I logged in to the Back Office and started to create the DocTypes. When I switched back to Visual Studio to work on the generated templates and create the partials I found each template had an error on the first line. This caused a lot of consternation. After much digging around I realised the templates Umbraco was now creating required handling by a new Models Builder that had just been put into Umbraco and set as default without any information I was aware of. What followed was a mad scrabble around Google and Our to find out what was going on. Because there were no clear instructions at that time, I ended up installing all sorts of stuff into the project and even a special Visual Studio Extension. Importantly, I learned how to switch it off, which is what I ended up doing just to get some work done. I'd wasted many billable hours.
Some days later, once a few more people had asked questions on Our, there was a fairly clear explaination of how to set it up. So I had another go. What I found was that it was actually simple to set up, but it only acted on Views. Most of my functionality was in Partials, so as I saw it, it was of almost no use to me. A lot of effort to save hardly any time or complexity. In one post (*2) it was mentioned about moving interfaces to new content types. I'm afraid it got way above my level of understanding. So, until there's better documentation the first thing I do now is switch it off in Web.Config before I start defining DocTypes. Mainly so I don't have to replace the top two lines of code with @inherits Umbraco.Web.Mvc.UmbracoTemplatePage.
I know it's not a popular position but I think there is a case for delaying some functionality until the documentation is ready, or at least put a cheatsheet out immediately with full docs later. Once things are advertised as being out there, you sort of think it's ready to go for the masses.
Related Our posts :
1) https://our.umbraco.org/forum/umbraco-as-a-service/76655-best-practice-for-uaas-visual-studio-set-up-and-modelsbuilder 2) https://our.umbraco.org/forum/umbraco-7/using-umbraco-7/75079-74-models-builder
None of the above for me at this moment ...
If something like discussed in https://our.umbraco.org/projects/developer-tools/1-1-multilingual-example/ could also be done without ModelBuilder, it would make ModelBuilder less necessary.
ModelBuilder can be quite powerful but right now it also imposes some restrictions. Not sure how, but maybe if we could mark only specific DocumentTypes to be available for ModelBuilder, it would be more controllable and keeping the "old" flexibility...
I think it's great, it does what it says on the tin.
Used it on a few smaller Umbraco projects and haven't had any issues. Although other than Archetype and Nested Content i've not really used custom data types for it.
Running it in AppData and modifying/ copying models from there. Saves a bit of time that I'd have to have used to build the models manually.
I agree though that it should be obvious to the developer how to not use this feature :) although, who wouldn't want to use it.
Cheers
Just a few cents from a (for now) non-user:
I think the models builder is fabulous. I'm a freelancer and I've worked in many different Umbraco setups and every company seemed to be rolling their own strong-typed models, so did I in fact. But it's always been working on the outside of Umbraco, so it's great to have something more integrated and consistant.
A few observations:
That would be cool.
I hope that didn't sound too critical because I'm a big fan of the models builder.
Things that have made me not want to commit to it yet include:
Most know I got my fingers burnt with CodeFirst but Model Builder and Ditto are different (as discussed over many G&T's). I'd love to give it a go though.
Pete
I quite like the functionality currently given, although i'm always going for the Dll setup instead of PureLive. I like to use the models in the controllers and .cs code aswell and I like keeping control of the model generation (when they are generated). I've seen some 7.4.0 sites go ballistic on beta and live servers when PureLive was enabled.
Another thing that would really help with the adoption is if we could also save and create nodes with these models. Now i'm still looking up the property alias for a content node i'm publishing and duplicating code.
@Timo Is this what you mean? My doctype is "Documentation"
@Sebastiaan,
It helps, but isn't the most beautiful setup. What I mean is something like:
var doc = new Documentation(parentId, docName);
doc.BodyText = "text";
doc.SaveAndPublish();
Strongly typed content creation. Or maybe a ModelsBuilder variant that depends on IContent instead of IPublishedContent.
Nice! I was looking for that for quite some time . Thanks!
I might just be inclined to disavow most of my feedback. I (finally) read through the wiki and gave
PureLive
with partial interfaces inApp_Data/Models
a go. I actually think I'm in love with a new practice. :)This one definitely still stands, though:
As a frontend developer just wanting to get hold of the data using the
@Model.MyPropertyTypeAlias
syntax I was a bit confused that it was not working out of the box - Missed that I needed to change the default UmbracoTemplatePage to UmbracoViewPage to make it work.But I guess this will be changed to be default at a later point since we're moving toward the strongly typed way of doing things? :)
Loving how much it has progressed and looking forward to see it be refined even more based on all the feedback.
Just my 2 cents based on my sparse experience so far.
/Jan
I appear to be missing out on the awesomeness of this feature. I think what is needed (or what I need anyway) is clear instructions as to how to change the working methods I use to create docTypes, templates and partials to allow the modelbuilder to do it's stuff and work in partials.
I know in a bog standard MVC site (I've not done many) you would define your own view models. What needs to be done in Umbraco MVC to get it working throughout simply and is this now being taught in the new courses?
Thanks
You can still use the strongly typed models in partials. Just ensure your partial inherits from the model it wants to use:
And then when you call the partial pass in your model:
(Where
Model
is the instance ofYourModel
).I really like the model generator and the flexibility of the different modes that suit different types of developer. I actually wrote my own basic generator (as a proof of concept), but yours is much slicker :) I haven't yet tried it on a complex project, so will see how it works when there are lots of compositions / inherited doc types. But so far, I think it will be really great and will really change the way people work.
The only negative would be the fact that there isn't documentation on Our.
One question, why is the
new
modifier use so much in the generated models? I couldn't quite understand why it was needed in cases like:and the fact you have to suppress the compiler warnings? But the inheritance tree is complex, so I'm sure there is a reason! :)
We use ZBU models builder al the time. It is such a great timesaver and FUD destroyer. To be able to change some property and to be confident that the compiler will tell you where the issues are, is really helpfull.
Absolutely love the modelsbuilder and have been using it in various projects when it was still the Zbu models builder.
One thing though. I'm developing and maintaining Umbraco projects in my VS2015 environment with both the Zbu Models Builder and Umbraco Models Builder vsix plugin. After installing the latter, the Zbu shows an error in the configuration page ("an error occurred loading this property page"). Can both vsix plugins live together? Otherwise, I'd be forced to either upgrade older Umbraco installations to vLatest that includes the Umbraco Models Builder or setup a new development environment for older projects. Both are not favourable...
I can't get the Umbraco Models Builder to connect and generate models for Umbraco < 7.4.0 projects. An HTTP Error 404.0 - Not Found is thrown as it tries to connect to http://www.my-pre-740-umbraco-project.local:80/Umbraco/BackOffice/ModelsBuilder/ModelsBuilderApi/ValidateClientVersion
Hi Marcel,
Both versions of the plugin can live side by side.
If you are using Umbraco 7.4+ you will need to use the Umbraco models builder plugin.
For versions lower than 7.4 you will need to disable the Umbraco Models Builder plugin to get the old Zbu models builder pluging working again.
In VS 2012 you can do this like this :
Go to Tools > Extensions and update
In your Installed Extensions find the Umbraco ModelsBuilder Custom Tool and disable it.
I assume the process in VS 2015 is the same.
Dave
Dave, hero of the day! Glad to have both model builder plugins working! H5YR :-)
Up until today my experience of 7.4.x sites were ones that been upgraded from 7.3 and earlier. I believe that when upgrading from pre 7.4, models builder would not be turned on by default.
So my WTF moment was today when I have started with my first new 7.4.x site (7.4.3) and discovered that models builder was enabled by default. If it is still true that the documentation is lacking (your word, not mine!) then I am surprised that a feature that is not properly documented on Our would be, by default, enabled.
Also - please can you point me to where the latest documentation is? I have found your own blog but not sure that this is referring to the latest version now in Core. I really want to use it on a new project so just wondering where to start! Then maybe I will have more WTF moments to report back (assuming you still want them!)
Thanks Lotte
Current documentation is available at https://github.com/zpqrtbnk/Zbu.ModelsBuilder/wiki (see "version 3"). Sorry for the WTF.
Thanks Stephan, that is indeed the page I was looking for! Shall now get started.
Occasionally during dev I've stopped the application to work on something then been hit by errors where the generated model files have been deleted (I'm guessing something has triggered a rebuild of the models and I stop it half way through by accident?).
The problem is I can't then build the solution as VS moans that there are missing references. What's the way of getting out of this mess?
I understand it's bad idea to include these generated model files in your VS solution but I've inherited a project where they've done just this - is this documented somewhere?
Steve
OK - I fixed it by recovering the models from source control but I suspect I should move the solution to the DLL Method and remove these included files from the solution?
I think they went missing when I did a clean of the solution - would that make sense?
I think it would be very handy if the all the aliases of the properties are also generated in the model.
This ensures that if a property is transfered to another file the naming stays consistent. Meaning that if the name of the property is changed the code still works. Also if the name of the property is neede in some other scenario(creating nodes, search parameters etc) they can be found in the generated Model. So for instance the property seo would look something like below. The ImplementPropertyType works with variables.
Actually, you can already get the alias in a strongly-typed way:
Where
Seo
is your model class... but that's a bit... ugly.It leads to an interesting question. The more properties we add to models, the greater the chances that someone decides to name one of their custom properties with that same name, and we have a collision.
I'd love to group all those meta-data infos eg
But I don't know how to name
???
. UsingMeta
is what makes most sense, only your example shows why it would be a bad idea. Collisions, again. Anything complex is ugly, anything simple is a collision risk.Thoughts?
ModelData
? Other ideas?Sibling metadata classes discovered through attribute or method a'la IPropertyConverterMeta. Pref not mentioned at all in typed Model class. Like how metadata for mvc Models can be separate from Models.
On phone, so difficult to add code. 😉
So, something totally out of the model class? Looks nice.
I like that approach, much cleaner. Thoughts?
Exactly. 😊
I'll see if I can dig up some code later.
I dug a bit around. Here's two ways I like to separate metadata. They could even co-exist as two ways of building up an in-memory graph of the metadata.
Entity Framework does it with "sibling" classes:
https://msdn.microsoft.com/en-us/library/ee707339(v=vs.91).ASPX
MVC has had something of the same, but also a fluent way to go about it. (When thinking about it, I think both may have both actually)
There's a pretty good walkthrough in the Professional ASP.NET MVC 5 book.
https://books.google.no/books?id=FaQLBAAAQBAJ&pg=PA437&lpg=PA437&dq=mvc+fluent+metadata&source=bl&ots=kHuEKHqldO&sig=Juj0MaX3bEo5hrCs-iV5vzxPk&hl=en&sa=X&ved=0ahUKEwis-Pqk_OHNAhXiDpoKHfOAADYQ6AEIQzAG#v=onepage&q=mvc%20fluent%20metadata&f=false
So we could either go
or as I'd prefer, discover the metadata without metadata attr. on the model class:
Or we could go completely fluent with it:
possibly having the option of overriding when some event?
Would be super sweet if metadata factory would go through interfaces and see if those have metadata if they're lacking for concretes too. At least makes sense for compositions, but might even be used for non-content properties?
And then querying exactly as you did above.
Uh... so you'd programmatically define metadata? I though we'd just generate the static
Models
class as part of the models generation?I guess I took off beyond what you guys were discussing. :P
I'm not saying you should create the "baseline" metadata manually. Sibling classes like the first example could be generated. I can't put my finger on it, but it feels nice to have as clean and dependencyless as possible model adapters. Starting to lean against only having interfaces as dependencyless, so might not be worth it though.
But wouldn't it also be cool to decorate the metadata later like with the fluent syntax?
Say you'd like to use the localized label for a property in a view. You could go
@Html.LabelFor(m => m.TechnicalProperty)
. You could also goHtml.DisplayFor(m => m.Body)
.Extend to typed models for Umbraco.Forms, and we go
Html.EditorFor(m => m.CustomFieldType)
. ;)I'm a bit lost so I'm just going to say what would be handy for me ;-). Maybe it is indeed better to have it separate from the Models generation because it is really about DocumentTypes.
In the past we generated constants code ( and pasted it by hand in the project). We could then use it in simple calls.
var title = websitenode.GetPropertyValue
Or in the RenderMacro call to ezSearch
This results in easy readable and safe code which is very important if you want to transfer the right data from the cms to the webpage ;-)
Too bad you won't get automatic renaming. At least you'll have compiler errors when names change. :)
In any case, what's been discussed leads to your statement being something like this instead. Good enough?
If this concurs with say, the Microsoft style of doing these kinds of things, it is surely good enough. Personaly I think it's is a bit cryptic. Last suggestion and then I will shut up about it:
If there were generated copies of the models where all properties were readonly strings, we could have:
I guess ModelsBuilder would have to do something along the lines of:
Where SeoMetadata is the generated copy with consts:
(The consts could possibly be decorated with more metadata? :D)
Thoughts? (@Stephen?)
... thinking about it ...
We want the simplest, fully-generated, solution. No metadata registering or discovery, for perfs reasons. I'll toy with the various suggestions and see which is both safe and simple.
I love ModelsBuilder, I've been using it since 2014. I've put a few sites live now which rely heavily on this feature and I can't do without it now. I must say though I've found it quite tricky to get to grips with.
My workflow has changed over time and I exclusively use it in LiveAppData mode. I want to hit save in the CMS, have my models generated which I can see in my solution, and then add any partials to extend the functionality.
Gripe 1
I don't know or can't figure out how to "override" code generation for certain types of property which just return an object of type
object
.For example, if I add a media picker to my document
BlogEntry
, and let's say it's calledBlogEntryVideo
, I often end up creating a new property in my own newBlogEntry.cs
partial where I add some property likeBlogEntryVideoUrl
that fetches the actual media Url so that I don't have to mess around in my templates with theobject
which is actually the string media id returned by the ModelsBuilder generated property.So I actually spend a reasonable amount of time creating new partials for each document type where I add my nice typed properties. Often I'll add a property like
PageHeadingOrNodeName
which I use instead of the generatedPageHeading
because I want a property that will fall back on something else. I don't want to write null or empty checks in my views. It would be good if I could somehow improve this workflow.Gripe 2
This will probably come down to my own ignorance. But Composites and the generated interfaces. I really struggle with this, and a lack of full examples or documentation for how to best use composites doesn't help. I know this is touched on in the official wiki. I'm probably being really dumb, but I still don't understand how I'm supposed to generate a nice reusable custom property for my composite. To continue my earlier example, let's say I have a composite doctype called
CompositePageHeading
which simply adds aPageHeading
text field to a doctype. I want to add myPageHeadingOrNodeName
property so that it's available everywhere. If I stick this into my own partial interface forICompositePageHeading
this will break all the models that implement this interface unless I then manually create partials for all of them and implement the property over and over.I get around by avoiding it as much as possible, by creating a
BasePage
doctype that my other doctypes inherit from, and generally shove most of my stuff in there. I still use composites but just accept that I'll need to implement all of my custom properties for a composite over and over in each doctype that uses it. I don't know how to have aCompositeBasePage
using interfaces as opposed to an inheritance approach, without having to manually implement a bunch of custom properties rather than just extending one class once, theBasePage
.Gripe 3
I'm currently doing a bit of the "bad" and the "ugly" listed on the official wiki: https://github.com/zpqrtbnk/Zbu.ModelsBuilder/wiki/Understand-And-Extend
I stick a few things in my base page like
HomePage
which indeed walks up the content tree. In fact I do this a lot if I need to grab some special node that I need a reference to. The wiki states:I don't get it. Again, possibly my ignorance, as I'm not familiar with MVVM. I don't want to create a controller for all of my views. I don't want to have to manually create view model classes for all of my templates - this is adding work for me isn't it? So instead the documentation suggests extending Umbraco's views. Does this mean extend RenderModel? Could use an example as I'm not 100% confident about all the different classes that a template can inherit from.
Comment author was deleted
Just doing my first project with Model builders and must say once you have it going it is great!
It still seems a bit hard to find out where the latest documentation is, it would be ace if it could be added to the what I consider 'official docs' here on our.
Now in my case I managed to break the frontend almost immediately since I had a composition called Content (and content seems to be a reserved word)
So would be ace if the content type editor could prevent this from happening: http://issues.umbraco.org/issue/U4-9023 (think it will also fail if you have a property with the same alias as your doctype and there must be other cases..., so again making this as dummy proof as possible by doing a check on the doc type editor would be recommended).
Also it seems that Dll or LiveDll seems to be the preferred option when using Umbraco in VS, why not have that as a default option then when installing it through Nuget?
Totally agree with Tim that if it's in the core, it's docs should be in the core docs. + with BIG warnings about reserved words and any other known gotchas. + with some basic examples, including use with partials for non-MVC experts.
It's a year on now since we were told there would be documentation on how to use the ModelsBuilder. I can't see any in the Documentation section. Having just completed the 4 to 7 Bridging Course I was keen to use ModelsBuilder on a multi-project solution in VS. Once again, I've wasted another whole day and got nowhere. From the forum I can see this is wasting many, many man-days. It's REALLY painful.
https://our.umbraco.org/forum/extending-umbraco-and-using-the-api//83627-modelsbuilder-vs-setup-for-multiple-projects
is working on a reply...