<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Blog posts by Peter Löfman</title><link href="http://world.optimizely.com" /><updated>2016-10-22T08:40:07.7270000Z</updated><id>https://world.optimizely.com/blogs/peter-lofman/</id> <generator uri="http://world.optimizely.com" version="2.0">Optimizely World</generator> <entry><title>Force Property Type Reset</title><link href="https://world.optimizely.com/blogs/peter-lofman/dates/2016/10/force-property-type-reset/" /><id>&lt;p&gt;During the development phase of a project it is, at least for me, rather common to change property names and property types when refactoring or otherwise improving the code. This can create a clutter of properties on a content type that are not being used as well as property type mismatch since &lt;a href=&quot;/link/812ea3b3442e42d4bcf2449ee66f8375.aspx&quot;&gt;Episerver can ony handle some property type cconversions automatically&lt;/a&gt;. Episerver cannot for instance automatically convert a property that used to be a string to an int, which is very much understandable. And if you read up on &lt;a href=&quot;/link/812ea3b3442e42d4bcf2449ee66f8375.aspx&quot;&gt;refactoring content type classes&lt;/a&gt; Episerver states that: &quot;&lt;span&gt;If you need a change of [property] type and any data loss is acceptable, you can change the type of the property in admin mode, but you must temporarily remove the property from the code.&quot;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Having to go into admin mode and temporarily remove property&amp;nbsp;from code is too bothersome for me so instead of doing something that would take a minute or two I spent a couple of hours trying to write some code that will do this automatically, and here is what I came up with.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;First a created an atribute (I really did this last but it sounds better like this) to be placed on the property that you have changed the type of and which cannot be converted automatically, for instance a string to an int.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[AttributeUsage(AttributeTargets.Property)]
public class ForceResetPropertyTypeAttribute : Attribute
{
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And you place it on a property like this. And, please be aware that all previous data will be lost since we will delete the property and then add it again with the new type.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;// I used to be a string but have been changed to an int
[ForceResetPropertyType]
[Display(GroupName = SystemTabNames.Content, Order = 100)]
public virtual int BackgroundColor { get; set; }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next a made an &lt;a href=&quot;/link/b3c10fa7ea5a492bafd245ced7ddc939.aspx&quot;&gt;initialization module&lt;/a&gt;&amp;nbsp;that (1) deletes all properties that are&amp;nbsp;missing in code and (2) scans each content type model for the attribute ForceResetPropertyTypeAttribute I create before, and simply deletes the property with all its data from Episerver and then re-adds it with the new property definition.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class ResetContentTypeslInitialization : IInitializableModule
{
    public void Initialize(InitializationEngine context)
    {
        var contentTypeRepository = ServiceLocator.Current.GetInstance&amp;lt;IContentTypeRepository&amp;gt;();
        var propertyDefinitionRepository = ServiceLocator.Current.GetInstance&amp;lt;IPropertyDefinitionRepository&amp;gt;();
        var contentTypeModelRepository = ServiceLocator.Current.GetInstance&amp;lt;ContentTypeModelRepository&amp;gt;();
        var propertyDefinitionSynchronizer =
            (PropertyDefinitionSynchronizer)ServiceLocator.Current.GetInstance&amp;lt;IPropertyDefinitionTypeResolver&amp;gt;();

        // foreach (var contentType in contentTypeRepository.List()) - takes all content types 
        // and not just yours and will actually remove to much
        foreach (
            var contentType in
                contentTypeRepository.List()
                    .Where(ct =&amp;gt; !string.IsNullOrEmpty(ct.ModelTypeString)
                        &amp;amp;&amp;amp; ct.ModelTypeString.StartsWith(&quot;Your.Assembly.Containing.The.Content.Types&quot;)))
        {
            // First we delete all properties that do not exist in code - probably due to renaming them
            var propertyDefinitionsThatDoNotExistInCode =
                contentType.PropertyDefinitions.Where(
                    propertyDefinition =&amp;gt; IsMissingModelProperty(propertyDefinition, contentTypeModelRepository));

            foreach (var propertyDefinition in propertyDefinitionsThatDoNotExistInCode)
            {
                propertyDefinitionRepository.Delete(propertyDefinition);
            }

            var modelType = contentType.ModelType;

            if (modelType == null) continue;

            // Next we want to check if there are any content types that have a property with the 
            // ForceResetPropertyTypeAttribute placed on them, and if so delete and re-add the property
            // definition.
            foreach (var propertyInfo in modelType.GetProperties())
            {
                var forceResetPropertyTypeAttribute =
                    propertyInfo.GetCustomAttribute&amp;lt;ForceResetPropertyTypeAttribute&amp;gt;();

                if (forceResetPropertyTypeAttribute == null) continue;

                var propertyName = propertyInfo.Name;

                var contentTypeModel = contentTypeModelRepository.GetContentTypeModel(modelType);
                var propertyDefinition = contentType.PropertyDefinitions.Single(pd =&amp;gt; pd.Name.Equals(propertyName));
                var propertyDefinitionModel =
                    contentTypeModel.PropertyDefinitionModels.Single(p =&amp;gt; p.Name.Equals(propertyName));

                // We check the current property definition type to see if perhaps we have already made the conversion.
                // We do not want to remove data on an already converted property
                var propertyDefinitionType = propertyDefinitionSynchronizer.ResolveType(propertyDefinitionModel);
                   
                if (propertyDefinition.Type.DefinitionType == propertyDefinitionType.DefinitionType) continue;

                // And finally here we delete the property definition and then re-adds it according to the new information
                // Please be aware that this will delete all the data as well.
                propertyDefinitionRepository.Delete(propertyDefinition);
                propertyDefinitionSynchronizer.CreatePropertyDefinition(propertyDefinitionModel, contentType.ID);
            }
        }
    }

    private static bool IsMissingModelProperty(
        PropertyDefinition propertyDefinition,
        ContentTypeModelRepository contentTypeModelRepository)
    {
        if (propertyDefinition == null) return false;

        if (!propertyDefinition.ExistsOnModel) return true;

        return contentTypeModelRepository.GetPropertyModel(propertyDefinition.ContentTypeID, propertyDefinition)
                == null;
    }

    public void Uninitialize(InitializationEngine context)
    {
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;[Pasting files is not allowed]&lt;/span&gt;&lt;span&gt;[Pasting files is not allowed]&lt;/span&gt;&lt;/p&gt;</id><updated>2016-10-22T08:40:07.7270000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Property Validations</title><link href="https://world.optimizely.com/blogs/peter-lofman/dates/2016/9/property-validations/" /><id>&lt;p&gt;Inspiration for this blog post comes from the blog post on &lt;a href=&quot;/link/e5beed92a6744aa0b223180c1d9905a0.aspx&quot;&gt;page validations&lt;/a&gt;&amp;nbsp;and I wanted to spin a little further on this subject by creating a flexible validation atttribute you can place on the property to validate.&lt;/p&gt;
&lt;p&gt;I wanted to use lamba expression but didn&#39;t realize that &lt;a href=&quot;http://stackoverflow.com/questions/4411122/c-sharp-method-attribute-cannot-contain-a-lambda-expression&quot;&gt;you cannot do that&lt;/a&gt;, so I then started trying other means of getting the flexibility I wanted to achieve befaore finding a wonderful little blog post on how to &lt;a href=&quot;http://www.codeproject.com/Articles/11939/Evaluate-C-Code-Eval-Function&quot;&gt;evaluate c# code&lt;/a&gt;. This makes it possible to write a string lambda expression and then compile this into to valid code you can use.&lt;/p&gt;
&lt;p&gt;Anyway, enough history on the origins of this blog post let&#39;s dive into how to make property validation flexible and versatile.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Examples of the ValidateAttribute&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;My thinking was that you should be able to create multiple validation rules for each property with different levels of severity. And, you should also be able to use the current PageData instance&amp;nbsp;in order to compare with other properties on the same PageData instance.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;[Validate(
    &quot;(str, pageData) =&amp;gt; str != null || pageData.MetaDescription != null&quot;, 
    ValidationErrorSeverity.Error, 
    &quot;MyTitle is empty.&quot;)]
[Validate(
    &quot;str =&amp;gt; str == null || str.Length &amp;gt; 10&quot;,
    ValidationErrorSeverity.Info, 
    &quot;MyTitle is a bit short - should be at least 10 characters.&quot;)]
[Display(GroupName = SystemTabNames.Content, Order = 1000)]
public virtual string MyTitle { get; set; }

[Validate(
    &quot;dateTime =&amp;gt; dateTime &amp;gt;= new DateTime(2016, 10, 01)&quot;, 
    ValidationErrorSeverity.Error,
    &quot;MyDateTime must be greater than or equal to 20016-10-01&quot;)]
[Display(GroupName = SystemTabNames.Content, Order = 2000)]
public virtual DateTime MyDateTime { get; set; }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are three properties of the ValidateAttribute: Expression, Severity, and Message.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The expression can be of two types:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;Func&amp;lt;dynamic, bool&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;Func&amp;lt;dynamic, dynamic, bool&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first simple takes the value of the property and validates against it and the latter also takes the PageData&amp;nbsp;instance into account.&lt;/p&gt;
&lt;p&gt;Next we need a class that implements IValidate&amp;lt;PageData&amp;gt; in order to look through all the properties on the current PageData instance&amp;nbsp;and validate against any possible ValidateAttributes and that&#39;s really it.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The two classes needed are the ones that follow.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ValidateAttribute&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;using System;
using EPiServer.Validation;

/// &amp;lt;summary&amp;gt;
/// Validates a string expression against a PageData instance.
/// &amp;lt;example&amp;gt;propertyValue =&amp;gt; propertyValue != null&amp;lt;/example&amp;gt;
/// &amp;lt;example&amp;gt;(propertyValue, pageData) =&amp;gt; propertyValue != null || pageData.AnotherProperty != null&amp;lt;/example&amp;gt;
/// &amp;lt;/summary&amp;gt;
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ValidateAttribute : Attribute
{
    /// &amp;lt;summary&amp;gt;
    /// The validation expression, of &amp;lt;see cref=&quot;Func{dynamic,Boolean}&quot;/&amp;gt;.
    /// &amp;lt;/summary&amp;gt;
    public string ValidationExpression { get; set; }

    /// &amp;lt;summary&amp;gt;
    /// The Severity if failing the validation.
    /// &amp;lt;/summary&amp;gt;
    public ValidationErrorSeverity Severity { get; set; }

    /// &amp;lt;summary&amp;gt;
    /// The message to be displayed if the validation fails.
    /// &amp;lt;/summary&amp;gt;
    public string Message { get; set; }

    /// &amp;lt;summary&amp;gt;
    /// The constructor for using the ValidateAttribute
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;param name=&quot;validationExpression&quot;&amp;gt;The validation expression, of &amp;lt;see cref=&quot;Func{dynamic,Boolean}&quot;/&amp;gt;.&amp;lt;/param&amp;gt;
    /// &amp;lt;param name=&quot;severity&quot;&amp;gt;The Severity if failing the validation.&amp;lt;/param&amp;gt;
    /// &amp;lt;param name=&quot;message&quot;&amp;gt;The message to be displayed if the validation fails.&amp;lt;/param&amp;gt;
    public ValidateAttribute(string validationExpression, ValidationErrorSeverity severity, string message)
    {
        this.ValidationExpression = validationExpression;
        this.Severity = severity;
        this.Message = message;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;ValidateContent&lt;/strong&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

using EPiServer;
using EPiServer.Core;
using EPiServer.Validation;

using Microsoft.CSharp;

public class ValidateContent : IValidate&amp;lt;PageData&amp;gt;
{
    public IEnumerable&amp;lt;ValidationError&amp;gt; Validate(PageData instance)
    {
        // A dictionary with property name as key with multiple validate attributes as value.
        var propertyValidateAttributes =
            instance.GetOriginalType()
                .GetProperties()
                .Select(
                    propertyInfo =&amp;gt;
                    new
                        {
                            propertyInfo.Name,
                            ValidateAttributes = propertyInfo.GetCustomAttributes&amp;lt;ValidateAttribute&amp;gt;()
                        })
                .Where(i =&amp;gt; i.ValidateAttributes != null)
                .ToDictionary(i =&amp;gt; i.Name, i =&amp;gt; i.ValidateAttributes);

        var validationErrors = new List&amp;lt;ValidationError&amp;gt;();

        foreach (var propertyValidationAttribute in propertyValidateAttributes)
        {
            foreach (var validateAttribute in propertyValidationAttribute.Value)
            {
                var isValid = IsValid(
                    validateAttribute.ValidationExpression,
                    instance.Property[propertyValidationAttribute.Key].Value,
                    validateAttribute.ValidationExpression.StartsWith(&quot;(&quot;) ? instance : null);

                if (isValid) continue;

                validationErrors.Add(
                    new ValidationError
                        {
                            ErrorMessage = validateAttribute.Message,
                            PropertyName = propertyValidationAttribute.Key,
                            Severity = validateAttribute.Severity,
                            ValidationType = ValidationErrorType.AttributeMatched
                        });
            }
        }

        return validationErrors;
    }

    //http://www.codeproject.com/Articles/11939/Evaluate-C-Code-Eval-Function
    public static bool IsValid(string expression, object propertyValue, PageData pageData = null)
    {
        var codeProvider = new CSharpCodeProvider();
        var compilerParameters = new CompilerParameters();

        compilerParameters.ReferencedAssemblies.Add(&quot;System.Core.dll&quot;);
        compilerParameters.ReferencedAssemblies.Add(&quot;Microsoft.CSharp.dll&quot;);
        compilerParameters.CompilerOptions = &quot;/t:library&quot;;
        compilerParameters.GenerateInMemory = true;

        var sb = new StringBuilder();

        sb.Append(&quot;using System;\n&quot;);
        sb.Append(&quot;using System.Linq.Expressions;\n&quot;);
        sb.Append(&quot;namespace ExpressionEvaluate {\n&quot;);
        sb.Append(&quot;public class ExpressionEvaluate {\n&quot;);
        sb.Append(&quot;public static Func&amp;lt;dynamic&quot; + (pageData != null ? &quot;, dynamic&quot; : &quot;&quot;) + &quot;, bool&amp;gt; Expression { get { return &quot; + expression + &quot;; } }\n&quot;);
        sb.Append(&quot;}\n&quot;);
        sb.Append(&quot;}\n&quot;);

        var compilerResults = codeProvider.CompileAssemblyFromSource(compilerParameters, sb.ToString());
        if (compilerResults.Errors.Count &amp;gt; 0)
        {
            throw new Exception(string.Join(&quot;; &quot;, compilerResults.Errors));
        }

        var compiledAssembly = compilerResults.CompiledAssembly;
        var instance = compiledAssembly.CreateInstance(&quot;ExpressionEvaluate.ExpressionEvaluate&quot;);

        if (instance == null)
            throw new Exception(&quot;Could not create an instance of the expression evaluator.&quot;);

        var instanceType = instance.GetType();

        var propertyInfo = instanceType.GetProperty(&quot;Expression&quot;, BindingFlags.Static | BindingFlags.Public);

        var func = propertyInfo.GetGetMethod().Invoke(instance, null);

        return pageData != null
                    ? ((Func&amp;lt;dynamic, dynamic, bool&amp;gt;)func)(propertyValue, pageData)
                    : ((Func&amp;lt;dynamic, bool&amp;gt;)func)(propertyValue);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;User interaction&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;And if using the validation rules as depicted in the &lt;em&gt;Examples of the ValidationAttribue&lt;/em&gt; section,&amp;nbsp;the following outcome could appear.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/35fd887ecb244bf291b5604bcd7f9193.aspx&quot; alt=&quot;Image validate-attribute-example.png&quot; /&gt;&lt;/p&gt;</id><updated>2016-09-25T11:19:19.3670000Z</updated><summary type="html">Blog post</summary></entry></feed>