Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Modelsbuilder modes
Models Builder can be used in different modes:
InMemory models
SourceCode models
The mode is indicated by the Umbraco:CMS:ModelsBuilder:ModelsMode
key in the configuration (appsettings.json
files).
Corresponds to the InMemoryAuto
setting value.
With InMemory models, models are generated and compiled on the fly, in memory, at runtime. They are available in views exclusively.
This is for a setup that exclusively uses the Umbraco backoffice, and do not use custom code such as controllers. Whenever a content type is modified, models are updated without restarting Umbraco (in the same way .cshtml views are recompiled).
Generation can fail for various reasons, in which case Umbraco will run without models (and front-end views fail to render). Umbraco's log file should contain all details about what prevented the generation, but it is probably faster to check the Models Builder dashboard, which should report the last error that was encountered, if any.
Models Builder maintains some files in ~/umbraco/Data/TEMP/InMemoryAuto
:
models.generated.cs
contains the generated models code
all.generated.cs
contains the compiled code (models merged with non-generated files)
models.hash
contains a hash code of the content types
all.dll.path
contains the path to the compiled DLL file containing all the models
Compiled/generated.cs{GUID}.dll
the dll containing all the generated models
models.err
contains the last generation error information, if any
The models.hash
file is used when Umbraco restarts, to figure out whether models have changed and need to be re-generated. Otherwise, the local models.generated.cs
file is reused.
Corresponds to the SourceCodeManual
and SourceCodeAuto
setting values.
With SourceCode models, models are generated in the ~/umbraco/models
directory, and that is all. It is then up to you to decide how to compile the models (e.g. by including them in a Visual Studio solution).
Generation can fail for various reasons, in which case no models are generated. Umbraco's log file should contain all details about what prevented the generation, but it is probably faster to check the Models Builder dashboard, which should report the last error that was encountered, if any.
The modelsbuilder works much in the same way whether using SourceCodeManual
or SourceCodeAuto
. The only real difference between the two are that with SourceCodeManual
you must manually trigger the generation of the models from the models builder dashboard, whereas with SourceCodeAuto
the models are automatically generated whenever content types change.
These modes are not available in the embedded version of Models Builder. See the full version of ModelsBuilder.
Modelsbuilder introduction
Models Builder is a tool that can generate a complete set of strongly-typed published content models for Umbraco. By default, a slimmed down version of Models Builder is embedded with the main Umbraco distribution.
Models can be used anywhere that content is retrieved from the content cache, i.e. in MVC views, controllers, etc. In other words, when using the Models Builder, the content cache does not return IPublishedContent
objects anymore, but strongly typed models, implementing IPublishedContent
.
For each content, media and member type in the Umbraco setup, the generator creates a *.generated.cs
file, corresponding to the type. For instance, a document type with a textstring property named Title, and a rich text editor named BodyText will look like this:
Now since this is an automatically generated file, it's a bit messy, the important part is that it has all the properties defined and strongly typed:
And:
Umbraco's content cache returns these objects natively: No need to map, convert or anything; the following code runs:
If your view inherits from UmbracoViewPage<NewsItem>
then the model is the content item itself and the syntax is @Model.Title
.
Models Builder respects the content types' inheritance tree, i.e. models inherit from each other if required, and mixins (content type compositions) are represented by interfaces.
Models Builder is a "code-after*_" solution. It only generates code from content types that already exist in Umbraco. It is not a "code-first" solution - code-first is a much more complex question.
And once you are using strongly typed models, there are some cool things that you can do.
The Models Builder is by default embedded in Umbraco. If you need more complex features than what is provided, you still need to add the full package. However, as of right now the package is not updated to be able to handle NetCore or Umbraco V9.
Check the official releases on the Models Builder GitHub repository for more details.
At the core of the strongly typed models "experience" is the IPublishedModelFactory
interface. This interface is part of the Umbraco core codebase. It is responsible for mapping the internal IPublishedContent
implementations returned by the content cache, to strongly typed models. There is a default factory shipped with Umbraco and it is possible to replace this by custom implementations. When using the default factory, models do not necessarily need to be generated by Models Builder.
Models Builder is one way to generate models for the default, built-in factory. Models can be generated automatically or straight from the Settings section of the Umbraco backoffice, for more info see builder modes.
Using interfaces with modelsbuilder
When using compositions, Models Builder generates an interface for the composed model, which enables us to not have to switch back to using Value()
for the composed properties.
A common use-case for this is if you have a separate composition for the "SEO properties" Page Title
and Page Description
.
You would usually use this composition on both your Home
and Textpage
document types. Since both Home
and Textpage
will implement the generated ISeoProperties
interface, you will still be able to use the simpler models builder syntax (e.g. Model.PageTitle
).
However, you won't be able to use the nice models builder syntax on any master template, since a master template needs to be bound to a generic IPublishedContent
. So you'd have to resort to the ever-so-slightly clumsier Model.Value("pageTitle")
syntax to render these properties. It is possible to solve this issue of master templating, by using partial views, to render the SEO specific properties.
If you create a partial and change the first line to use the interface name for the model binding, you can use the nice Models Builder syntax when rendering the properties, like this:
You can then render the partial from your Master Template with something like this (assuming the partial is named Metatags.cshtml
):
It's important to note though, that this master template will only work for content types that use the Seo Properties composition.
Modelsbuilder reference
The Models builder is a tool that can generate a complete set of strongly-typed published content models for Umbraco. Models are available in both controllers and views.
Cool things you can do with models
It's possible with Razor to define functions for rendering HTML. We can leverage our strongly typed models when doing this, and even provide overloads for different types of models. That will automatically be called for different models using dynamic
It's not recommended to create a template and doing all the rendering via razor function, but it can be nifty for rendering search results.
A thing that's important to note here is that RenderContent
is called from a codeblock, and not as @RenderContent((dynamic) Model);
the reason for this is that if you try to use the latter, razor will expect for the function to return something for it to render.
By casting the strongly typed to a dynamic when calling the RenderContent method, you tell C# to do late runtime binding. You also tell it to pick the proper RenderContent implementation depending on the actual Common Language Runtime (CLR) type of the content object. Using dynamic here is OK and will not pollute the rest of the code.
Understand and extend modelsbuilder
Models are generated as partial classes. In its most basic form, a model for content type TextPage
ends up in a TextPage.generated.cs
file and looks like:
What is important is the Header
property. The rest is (a) a constructor and (b) some static helpers to get the PublishedContentType
and the PublishedPropertyType
objects:
Content type Compositions in Umbraco allows content types to inherit properties from multiple other content types. Unlike C#, where a class can only inherit from one other class, Umbraco content types can be composed of multiple other content types.
In Umbraco v14, the traditional .NET Inheritance feature has been removed. Instead, properties are inherited through Composition, allowing for greater flexibility in managing content types.
For example, TextPage
content type could be composed of MetaInfo
(inheriting properties such as Author
and Keywords
) and PageInfo
(inheriting Title
and MainImage
) content types.
Each content type involved in a composition is generated both as a class and as an interface. Thus, the MetaInfo
content type would be generated as follows (some code has been removed and altered for simplicity's sake):
And the TextPage
model would be generated as follows (some code has been removed and altered for simplicity's sake):
In the Umbraco Backoffice, a content type can appear underneath its parent content type in the content tree.
By convention, a content type inherits properties from its parent in a compositional manner. However, this does not use traditional class inheritance but rather a compositional approach. This approach ensures content types can combine multiple sets of properties without the limitations of single inheritance.
Therefore, assuming that the AboutPage
content type is a direct child of TextPage
, it would be generated as:
Because a model is generated as a partial class, it is possible to extend it. That could be by adding a property, by dropping the following code in a TextPage.cs
file:
Models builder does not take a custom partial class into account when generating the models. This means that if a custom partial class, inherits from a base class, tries to provide a constructor with the same signature, or implements a generated property, it will cause compilation errors.
Furthermore a generated model will always be instantiated with its default constructor, so if an overloading constructor is created it will never be used.
For more complex partial classes, you'll have to use the full version of the Models Builder.
As of Umbraco 11.4, the IModelsGenerator interface has been added. If you want to customize how the models are generated, you can make your own implementation of the IModelsGenerator
interface. You can then overwrite the Umbraco implementation with dependency injection.
The interface can be accessed via Infrastructure.ModelsBuilder.Building.ModelsGenerator
.
Extending models should be used to add stateless, local features to models. It should not be used to transform content models into view models or manage trees of content.
A customer has "posts" that has two "release date" properties. One is a true date picker property and is used to specify an actual date and to order the posts. The other is a string that is used to specify dates such as "Summer 2015" or "Q1 2016". Alongside the title of the post, the customer wants to display the text date, if present, else the actual date. If none of those are present, the Umbraco update date should be used. Keep in mind that each view can contain code to deal with the situation, but it is much more efficient to extend the Post
model:
And to simplify the view as:
Because, by default, the content object is passed to views, one can be tempted to add view-related properties to the model. Some properties that do not belong to a content model would be:
A HomePage
property that would walk up the tree and return the "home page" content item
A Menu
property that would list the content items to display in a top menu
Etc.
Generally speaking, anything that is tied to the current request, or that depends on more than the modeled content, is a bad idea. There are much cleaner solutions, such as using true view model classes that would be populated by a true controller and look like:
One can also extend Umbraco's views to provide a special view helper that would give access to important elements of the website, so that views could contain code such as:
The scope and life-cycle of a model is not specified. In other words, you don't know whether the model exists only for you and for the context of the current request, or if it is cached by Umbraco and shared by all requests.
As a consequence, the following code has a major issue: the TextPage
model "caches" an instance of the HomePageDocument
model that will never be updated if the home page is re-published.
As a rule of thumb, models should never, ever reference and cache other models.
Information on configuring Templates (Views) and Partials (Partial Views)
Templating in Umbraco consists of 3 larger concepts, namely Templates (Views) and Partials (Partial Views).
Templates are used for the HTML layout of your pages.
Partials can be included in your templates for shared functionality across different page templates.
Umbraco uses ASP.Net MVC Views for implementing templates.
The WebForms (masterpages) and Dynamic Razor approaches to templating are still available in Umbraco version 7 but have been removed in Umbraco version 8.
Describes how to work with MVC views, the razor syntax and APIs available. It also describes how to create forms, has some step-by-step guides and other advanced techniques.
A tool that can generate a complete set of strongly-typed published content models for Umbraco. Models are available in controllers, views, anywhere. Runs either from the Umbraco UI, from the command line, or from Visual Studio.
How to work with MVC templates in Umbraco.
Working with MVC Views and Razor syntax in Umbraco
Documentation covering how to use Partial Views. This documentation relates to using native MVC partial views within Umbraco.
Using MVC Child Actions in Umbraco
How to query for published data in your Views
Working with MVC Views and Razor syntax in Umbraco
All Umbraco views inherit from Umbraco.Cms.Web.Common.Views.UmbracoViewPage<ContentModels.NameOfYourDocType>
along with the using statement @using ContentModels = Umbraco.Cms.Web.Common.PublishedModels;
. This exposes many properties that are available in razor. The properties on the Document Type can be accessed in a number of ways:
@Model (of type Umbraco.Web.Mvc.ContentModel
) -> the model for the view which contains the standard list of IPublishedContent properties but also gives you access to the typed current page (of type whatever type you have added in the angled brackets).
@Umbraco (of type UmbracoHelper
) -> contains many helpful methods, from rendering fields to retrieving content based on an Id and tons of other helpful methods. See UmbracoHelper Documentation
@Html (of type HtmlHelper
) -> the same HtmlHelper you know and love from Microsoft but we've added a bunch of handy extension methods like @Html.BeginUmbracoForm
@UmbracoContext (of type Umbraco.Cms.Web.Common.UmbracoContext
)
This is probably the most used method which renders the contents of a field using the alias of the content item.
If you're using the method from within a partial view then be aware that you will need to inherit the context so the method knows which type to get the desired value from. You'd do this at the top of partial view and so strongly typed properties can then be accessed in the partial view. For instance you can pass "HomePage" like this:
You will also need to pass the "Context" to the @Model.Value() method if you're looping over a selection like this where we pass the "item" variable.
Looping over a selection works in a similar way. If you have a property that contains, for instance, an IEnumberable collection, you can access the individual items using a foreach loop. Below illustrates how you might do that using "item" as a variable.
If you want to convert a type and it's possible, you can do that by typing a variable and assigning the value from your property to it. This could look like the example below.
In this example, we are looping through a list of items with the custom made type TeamMember assigned. This means we are able to access the strongly typed properties on the TeamMember item.
IMemberManager
is the gateway to everything related to members when templating your site. IMemberManager Documentation
Models Builder allows you to use strongly typed models in your views. Properties created on your document types can be accessed with this syntax:
When Models Builder resolve your properties it will also try to use value converters to convert the values of your data into more convenient models. This allows you to access nested objects as strong types instead of having to rely on dynamics and risking having a lot of potential errors when working with these.
This section will show you how to use MVC Partial Views in Umbraco.
Please note, this is documentation relating to the use of native MVC partial views
Using Partial Views in Umbraco is exactly the same as using Partial Views in a normal MVC project. There is detailed documentation on the Internet about creating and using MVC partial views
Partial views allow you to reuse components between your views (templates).
The locations to store Partial Views when rendering in the Umbraco pipeline is:
The standard MVC partial view locations will also work:
The ~/Views/Render
location is valid because the controller that performs the rendering in the Umbraco codebase is the: Umbraco.Cms.Web.Common.Controllers.RenderController
If however you are Hijacking an Umbraco route and specifying your own controller to do the execution, then your partial view location can also be:
A quick example of a content item that has a template that renders out a partial view template for each of its child documents:
The MVC template markup for the document:
The partial view (located at: ~/Views/Partials/ChildItem.cshtml
)
Normally you would create a partial view by using the @model MyModel
syntax. However, inside of Umbraco you will probably want to have access to the handy properties available on your normal Umbraco views like the Umbraco helper: @Umbraco
and the Umbraco context: @UmbracoContext
. The good news is that this is possible. Instead of using the @model MyModel
syntax, you need to inherit from the correct view class, so do this instead:
By inheriting from this view, you'll have instant access to those handy properties and have your view created with a strongly typed custom model.
Another case you might have is that you want your Partial View to be strongly typed with the same model type (IPublishedContent
) as a normal template if you are passing around instances of IPublishedContent. To do this, have your partial view inherit from Umbraco.Cms.Web.Common.Views.UmbracoViewPage
(like your normal templates). When you render your partial, a neat trick is that you can pass it an instance of IPublishedContent
. For example:
You don't normally need to cache the output of Partial views, like you don't normally need to cache the output of User Controls. However, there are times when this is necessary and so we provide caching output of partial views. This is done by using an HtmlHelper extension method:
The above will cache the output of your partial view for one hour when not running Umbraco in debug
mode. Additionally, there are a few optional parameters you can specify to this method. Here is the full method signature:
So you can specify to cache by member and/or by page and also specify additional view data to your partial view. * However*, if your view data is dynamic (meaning it could change per page request) the cached output will still be returned. This same principle applies if the model you are passing in is dynamic. Please be aware of this: if you have a different model or viewData for any page request, the result will be the cached result of the first execution. If this is not desired you can generate your own cache key to differentiate cache instances using the contextualKeyBuilder parameter
To create multiple versions based on one or more viewData parameters you can do something like this:
Or using a custom helper function:
Or even based on a property on the Model (though if Model is the current page then cacheByPage
should be used instead):
Regardless of the complexity here the contextualKeyBuilder function needs to return a single string value.
Caching is only enabled when your application has debug="false"
. When debug="true"
caching is disabled. Also, the cache of all CachedPartials is emptied on Umbraco publish events.
Explanation of how to configure models builder
The following configuration option can be set in the application settings (in the appsettings.json
file):
Umbraco.CMS.ModelsBuilder.ModelsMode
determines how Models Builder generates models. Valid values are:
Nothing
: Do not generate models.
InMemoryAuto
(default): Generate models in a dynamic in-memory assembly.
SourceCodeManual
: Generate models in ~/umbraco/models
(but do not compile them) whenever the user clicks the "Generate models" button on the Models Builder dashboard in the Settings section.
SourceCodeAuto
: Generate models in ~/umbraco/models
(but do not compile them) anytime a content type changes.
Umbraco.CMS.ModelsBuilder.ModelsNamespace
(string, default is Umbraco.Cms.Web.Common.PublishedModels
) specifies the generated models' namespace.
Umbraco.CMS.ModelsBuilder.FlagOutOfDateModels
(bool, default is true
) indicates whether out-of-date models (for example after a content type or Data Type has been modified) should be flagged.
Umbraco.CMS.ModelsBuilder.ModelsDirectory
(string, default is ~/umbraco/models
) indicates where to generate models and manage all files. Has to be a virtual directory (starting with ~/
) below the website root (see also: AcceptUnsafeModelsDirectory
below).
Umbraco.CMS.ModelsBuilder.AcceptUnsafeModelsDirectory
(bool, default is false
) indicates that the directory indicated in ModelsDirectory
is allowed to be outside the website root (e.g. ~/../../some/place
). Due to this being a potential security risk, it is not allowed by default.
Umbraco.CMS.ModelsBuilder.DebugLevel
(int, default is zero) indicates the debug level. Set to greater than zero to enable detailed logging. For internal / development use.
The example below shows an example configuration using the SourceCodeManual mode.
It is recommended to generate models in your development environment only and change the ModelsMode to Nothing
for your staging and production environments.
Models Builder ships with a dashboard in the Settings section of Umbraco's backoffice. The dashboard does three things:
Details on how Models Builder is configured
Provides a way to generate models (in SourceCodeManual mode only)
Reports the last error (if any) that would have prevented models from being properly generated
This section will describe how you can render content from other nodes besides the current page in your MVC Views
The easiest way to get some content by Id is to use the following syntax (where 1234 is the content id you'd like to query for):
You can also query for multiple content items using multiple ids:
This syntax will support an unlimited number of Ids passed to the method.
You can also retrieve content using the Guid
Id. In the example "ca4249ed-2b23-4337-b522-63cabe5587d1" is the key of the content.
You can also pass a to retrieve the content.
The same query structures apply to media:
All of these extension methods are available on Umbraco.Core.Models.IPublishedContent
so you can have strongly typed access to all of them with intellisense for both content and media. The following methods return IEnumerable<IPublishedContent>
Additionally there are other methods that will return a single IPublishedContent
With the IPublishedContent
model we support strongly typed LINQ queries out of the box so you will have intellisense for that.
The two examples below have not been verified for Umbraco 9 and 10 yet.
therefore they might not work on the latest versions of Umbraco.
With the strongly typed IPublishedContent
you can do complex queries.
Creating an HTML form to submit data with MVC in Umbraco is possible in a few steps.
If you want to create a Form:
Using view models, views, controllers, and a handy HtmlHelper extension method called BeginUmbracoForm, see the article.
Using Umbraco Forms, see the article.
In the previous versions of MVC, we used Child Actions to build reusable components/widgets consisting of both Razor markup and backend logic. The backend logic was implemented as a controller action and marked with a [ChildActionOnly] attribute. Child Actions are no longer supported in ASP.NET Core MVC. Instead, we will use the View Component feature.
View components replace the traditional Controller (SurfaceController)/Partial View relationship and instead offers a modular approach of separating your views in to several smaller units. View Components are self-contained objects that consistently render HTML from a Razor view.
View components are:
Generated from a C# class
Derived from the base class ViewComponent and
Associated with a Razor file (*.cshtml) to generate markup.
are similar to partial views but they are much more powerful compared to the partial views. View components do not use model binding, instead they work with the data provided when calling it.
View Components can be implemented in any part of the web application. There are some possibilities to duplicate code like Header, Navigation Pane, Login Panel, Menu, Shopping Cart, Footer, BlockList Items and so on. View Components behave like a web part containing both business logic and UI design. This is because they create a package which can be reused in multiple parts of the web application.
A view component code consists of two parts:
The View Component class derived from the ViewComponent
class:
Returns a Task object as IViewComponentResult
:
In this example, let's create a ViewComponent for a Product List and render it on the HomePage of the website.
Create a folder named ProductView. In this folder, create a new class named ProductViewViewComponent.cs as below:
In Views folder, create new folders at Views\Shared\Components\ProductView
. In the ProductView folder, create a new file named Default.cshtml as below:
Adding the following declaration will give access to the UmbracoHelper object inside the ViewComponent View
You can invoke a ViewComponent from anywhere (even from within a Controller or another ViewComponent). Since this is our Product List, we want it rendered on the Home page - so we’ll invoke it from our HomePage.cshtml file using:
By default, the framework searches for the Component View path in the following areas:
/Views/{Controller Name Folder}/Components/{View Component Name Folder}/{View Name}
/Views/Shared/Components/{View Component Name Folder}/{View Name}
You can read about different ways of invoking your view component in the section of the Microsoft Documentation.view=aspnetcore-5.0)