Last active
March 26, 2018 10:49
-
-
Save agrath/62313e7c0b021ebeb2277d076ca45354 to your computer and use it in GitHub Desktop.
An example of dynamically generated strong properties for Umbraco ModelsBuilder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//A PublishEventHandler catches the DataTypeService.Saved method as a developer workflow entry point; | |
//When the data type is saved this kicks off the generation and writes a model to our models folder | |
//This could be app_code if you don't use VS to build your solution, but we generate our ModelsBuilder models | |
//into a class which is then built as part of the solution | |
internal class PublishEventHandler : ApplicationEventHandler | |
{ | |
public const string FileSuffix = ".smartpropertytype.cs"; | |
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) | |
{ | |
DataTypeService.Saved += DataTypeService_Saved; | |
} | |
private void DataTypeService_Saved(IDataTypeService sender, global::Umbraco.Core.Events.SaveEventArgs<global::Umbraco.Core.Models.IDataTypeDefinition> e) | |
{ | |
if (e.SavedEntities.Any(entity => entity.PropertyEditorAlias == "CONTROLALIAS" || entity.PropertyEditorAlias == "OTHERCONTROL")) | |
{ | |
//GENERATE THE MODEL FILE (OVERWRITE .CS IF EXISTS) | |
} | |
} | |
} | |
//Our config for ModelsBuilder | |
/* | |
<add key="Umbraco.ModelsBuilder.Enable" value="true" /> | |
<add key="Umbraco.ModelsBuilder.ModelsMode" value="AppData" /> | |
<add key="Umbraco.ModelsBuilder.ModelsNamespace" value="Project.ContentModels" /> | |
<add key="Umbraco.ModelsBuilder.LanguageVersion" value="CSharp6" /> | |
<add key="Umbraco.ModelsBuilder.ModelsDirectory" value="~/../Project.ContentModels/Generated" /> | |
<add key="Umbraco.ModelsBuilder.AcceptUnsafeModelsDirectory" value="true" /> | |
*/ | |
//The normal Umbraco ModelsBuilder generates models like this, so we don't and can't alter this behaviour | |
//So we let ModelsBuilder generate its own models and write them | |
//Here is a sample of a minified generated model for homepage, this should be familiar if you've used ModelsBuilder | |
namespace Project.ContentModels | |
{ | |
/// <summary>Homepage</summary> | |
[PublishedContentModel("homepage")] | |
public partial class Homepage : PublishedContentModel, IPageHeader | |
{ | |
#pragma warning disable 0109 // new is redundant | |
public new const string ModelTypeAlias = "homepage"; | |
public new const PublishedItemType ModelItemType = PublishedItemType.Content; | |
#pragma warning restore 0109 | |
public Homepage(IPublishedContent content) | |
: base(content) | |
{ } | |
#pragma warning disable 0109 // new is redundant | |
public new static PublishedContentType GetModelContentType() | |
{ | |
return PublishedContentType.Get(ModelItemType, ModelTypeAlias); | |
} | |
#pragma warning restore 0109 | |
public static PublishedPropertyType GetModelPropertyType<TValue>(Expression<Func<Homepage, TValue>> selector) | |
{ | |
return PublishedContentModelUtility.GetModelPropertyType(GetModelContentType(), selector); | |
} | |
///<summary> | |
/// Content | |
///</summary> | |
[ImplementPropertyType("propertyAlias")] | |
public IHtmlString PropertyAlias | |
{ | |
get { return this.GetPropertyValue<IHtmlString>("propertyAlias"); } | |
} | |
} | |
} | |
//As a developer, when you are editing a data type which represents something you want a custom model for | |
//e.g. when you would normally generate a dynamic or jObject property but would really prefer a strong class | |
//you go and save the data type, then the event is caught by the handler above and this generates an additional model class | |
//file for your custom content | |
//Here's an example of one of those (faked for this gist) | |
public class StrongJsonDeserializedModel | |
{ | |
public StrongJsonDeserializedModel(string json) | |
{ | |
var that = JsonConvert.DeserializeObject<StrongJsonDeserializedModel>(json); | |
this.X = that.X; | |
this.Y = that.Y; | |
} | |
public int X {get;set;} | |
public int Y {get;set;} | |
} | |
//This is an additional Homepage partial class that is also generated by our datatype save event | |
//it implements the property propetyAlias | |
//https://our.umbraco.org/Documentation/reference/templating/Modelsbuilder/Control-Generation#implement-property-type | |
//As per Indicates that a property implements a property type with a given alias. The attribute must decorate the | |
//corresponding property type property. Use when alias and property name do not match. | |
//This will cause the property propertyAlias to not be generated, since you already implement it as StrongPropertyAlias. | |
public partial class Homepage | |
{ | |
[ImplementPropertyType("propertyAlias")] | |
public StrongJsonDeserializedModel StrongPropertyAlias { get { return new StrongJsonDeserializedModel(this.GetPropertyValue<string>("propertyAlias")); } } | |
} | |
//now from your view: | |
@inherits Umbraco.Web.Mvc.UmbracoTemplatePage<Homepage> | |
@{ | |
Layout = "Master.cshtml"; | |
} | |
//@Model.Content.StrongPropertyAlias => StrongJsonDeserializedModel | |
@Model.Content.StrongPropertyAlias.X | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment