Rectangle 27 5

In ASP.NET binding metadata gathered by TypeDescriptor, not by reflection directly. To be more precious, AssociatedMetadataTypeTypeDescriptionProvider is used, which, in turn, simply calls TypeDescriptor.GetProvider with our model type as parameter:

public AssociatedMetadataTypeTypeDescriptionProvider(Type type)
  : base(TypeDescriptor.GetProvider(type))
{
}
TypeDescriptionProvider

Let's implement our custom provider. First of all, let's define attribute for custom property name:

[AttributeUsage(AttributeTargets.Property)]
public class CustomBindingNameAttribute : Attribute
{
    public CustomBindingNameAttribute(string propertyName)
    {
        this.PropertyName = propertyName;
    }

    public string PropertyName { get; private set; }
}

If you already have attribute with desired name, you can reuse it. Attribute defined above is just an example. I prefer to use JsonProeprtyAttribute because in most cases I work with json and Newtonsoft's library and want to define custom name only once.

The next step is to define custom type descriptor. We will not implement whole type descriptor logic and use default implementation. Only property accessing will be overridden:

Also custom property descriptor need to be implemented. Again, everything except property name will be handled by default descriptor. Note, NameHashCode for some reason is a separate property. As name changed, so it's hash code need to be changed too:

public class MyPropertyDescriptor : PropertyDescriptor
{
    private readonly PropertyDescriptor _descr;
    private readonly string _name;

    public MyPropertyDescriptor(PropertyDescriptor descr)
        : base(descr)
    {
        this._descr = descr;

        var customBindingName = this._descr.Attributes[typeof(CustomBindingNameAttribute)] as CustomBindingNameAttribute;
        this._name = customBindingName != null ? customBindingName.PropertyName : this._descr.Name;
    }

    public override string Name
    {
        get { return this._name; }
    }

    protected override int NameHashCode
    {
        get { return this.Name.GetHashCode(); }
    }

    public override bool CanResetValue(object component)
    {
        return this._descr.CanResetValue(component);
    }

    public override object GetValue(object component)
    {
        return this._descr.GetValue(component);
    }

    public override void ResetValue(object component)
    {
        this._descr.ResetValue(component);
    }

    public override void SetValue(object component, object value)
    {
        this._descr.SetValue(component, value);
    }

    public override bool ShouldSerializeValue(object component)
    {
        return this._descr.ShouldSerializeValue(component);
    }

    public override Type ComponentType
    {
        get { return this._descr.ComponentType; }
    }

    public override bool IsReadOnly
    {
        get { return this._descr.IsReadOnly; }
    }

    public override Type PropertyType
    {
        get { return this._descr.PropertyType; }
    }
}

Finally, we need our custom TypeDescriptionProvider and way to bind it to our model type. By default, TypeDescriptionProviderAttribute is designed to perform that binding. But in this case we will not able to get default provider that we want to use internally. In most cases, default provider will be ReflectTypeDescriptionProvider. But this is not guaranteed and this provider is inaccessible due to it's protection level - it's internal. But we do still want to fallback to default provider.

TypeDescriptor also allow to explicitly add provider for our type via AddProvider method. That what we will use. But firstly, let's define our custom provider itself:

public class MyTypeDescriptionProvider : TypeDescriptionProvider
{
    private readonly TypeDescriptionProvider _defaultProvider;

    public MyTypeDescriptionProvider(TypeDescriptionProvider defaultProvider)
    {
        this._defaultProvider = defaultProvider;
    }

    public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
    {
        return new MyTypeDescription(this._defaultProvider.GetTypeDescriptor(objectType, instance));
    }
}

The last step is to bind our provider to our model types. We can implement it in any way we want. For example, let's define some simple class, such as:

public static class TypeDescriptorsConfig
{
    public static void InitializeCustomTypeDescriptorProvider()
    {
        // Assume, this code and all models are in one assembly
        var types = Assembly.GetExecutingAssembly().GetTypes()
                            .Where(t => t.GetProperties().Any(p => p.IsDefined(typeof(CustomBindingNameAttribute))));

        foreach (var type in types)
        {
            var defaultProvider = TypeDescriptor.GetProvider(type);
            TypeDescriptor.AddProvider(new MyTypeDescriptionProvider(defaultProvider), type);
        }
    }
}

And either invoke that code via web activation:

[assembly: PreApplicationStartMethod(typeof(TypeDescriptorsConfig), "InitializeCustomTypeDescriptorProvider")]

Or simply call it in Application_Start method:

public class MvcApplication : HttpApplication
{
    protected void Application_Start()
    {
        TypeDescriptorsConfig.InitializeCustomTypeDescriptorProvider();

        // rest of init code ...
    }
}

But this is not the end of the story. :(

public class TestModel
{
    [CustomBindingName("actual_name")]
    [DisplayName("Yay!")]
    public string TestProperty { get; set; }
}

If we try to write in .cshtml view something like:

ArgumentException

An exception of type 'System.ArgumentException' occurred in System.Web.Mvc.dll but was not handled in user code

Additional information: The property Some.Namespace.TestModel.TestProperty could not be found.

That because all helpers soon or later invoke ModelMetadata.FromLambdaExpression method. And this method take expression we provided (x => x.TestProperty) and takes member name directly from member info and have no clue about any of our attributes, metadata (who cares, huh?):

internal static ModelMetadata FromLambdaExpression<TParameter, TValue>(/* ... */)
{
    // ...

        case ExpressionType.MemberAccess:
            MemberExpression memberExpression = (MemberExpression) expression.Body;
            propertyName = memberExpression.Member is PropertyInfo ? memberExpression.Member.Name : (string) null;
            //                                  I want to cry here - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    // ...
}
x => x.TestProperty
TestModel
actual_name
TestProperty
the property could not be found

However despite this little inconvenience there are several workarounds, such as:

The easiest way is to access our members by theirs redefined names:

@model Some.Namespace.TestModel
@Html.DisplayName("actual_name") @* this will render "Yay!" *@

This is not good. No intellisense at all and as our model change we will have no any compilation errors. On any change anything can be broken and there is no easy way to detect that.

Another way is a bit more complex - we can create our own version of that helpers and forbid anybody from calling default helpers or ModelMetadata.FromLambdaExpression for model classes with renamed properties.

Finally, combination of previous two would be preferred: write own analogue to get property name with redefinition support, then pass that into default helper. Something like this:

@model Some.Namespace.TestModel
@Html.DisplayName(Html.For(x => x.TestProperty))

Compilation-time and intellisense support and no need to spend a lot of time for complete set of helpers. Profit!

Also everything described above work like a charm for model binding. During model binding process default binder also use metadata, gathered by TypeDescriptor.

But I guess binding json data is the best use case. You know, lots of web software and standards use lowercase_separated_by_underscores naming convention. Unfortunately this is not usual convention for C#. Having classes with members named in different convention looks ugly and can end up in troubles. Especially when you have tools that whining every time about naming violation.

ASP.NET MVC default model binder does not bind json to model the same way as it happens when you call newtonsoft's JsonConverter.DeserializeObject method. Instead, json parsed into dictionary. For example:

{
    complex: {
        text: "blabla",
        value: 12.34
    },
    num: 1
}
{ "complex.text", "blabla" }
{ "complex.value", "12.34" }
{ "num", "1" }

And later these values along with others values from query string, route data and so on, collected by different implementations of IValueProvider, will be used by default binder to bind a model with help of metadata, gathered by TypeDescriptor.

So we came full circle from creating model, rendering, binding it back and use it.

asp.net mvc - How to bind view model property with different name - St...

asp.net-mvc razor data-annotations model-binding asp.net-mvc-5
Rectangle 27 5

In ASP.NET binding metadata gathered by TypeDescriptor, not by reflection directly. To be more precious, AssociatedMetadataTypeTypeDescriptionProvider is used, which, in turn, simply calls TypeDescriptor.GetProvider with our model type as parameter:

public AssociatedMetadataTypeTypeDescriptionProvider(Type type)
  : base(TypeDescriptor.GetProvider(type))
{
}
TypeDescriptionProvider

Let's implement our custom provider. First of all, let's define attribute for custom property name:

[AttributeUsage(AttributeTargets.Property)]
public class CustomBindingNameAttribute : Attribute
{
    public CustomBindingNameAttribute(string propertyName)
    {
        this.PropertyName = propertyName;
    }

    public string PropertyName { get; private set; }
}

If you already have attribute with desired name, you can reuse it. Attribute defined above is just an example. I prefer to use JsonProeprtyAttribute because in most cases I work with json and Newtonsoft's library and want to define custom name only once.

The next step is to define custom type descriptor. We will not implement whole type descriptor logic and use default implementation. Only property accessing will be overridden:

Also custom property descriptor need to be implemented. Again, everything except property name will be handled by default descriptor. Note, NameHashCode for some reason is a separate property. As name changed, so it's hash code need to be changed too:

public class MyPropertyDescriptor : PropertyDescriptor
{
    private readonly PropertyDescriptor _descr;
    private readonly string _name;

    public MyPropertyDescriptor(PropertyDescriptor descr)
        : base(descr)
    {
        this._descr = descr;

        var customBindingName = this._descr.Attributes[typeof(CustomBindingNameAttribute)] as CustomBindingNameAttribute;
        this._name = customBindingName != null ? customBindingName.PropertyName : this._descr.Name;
    }

    public override string Name
    {
        get { return this._name; }
    }

    protected override int NameHashCode
    {
        get { return this.Name.GetHashCode(); }
    }

    public override bool CanResetValue(object component)
    {
        return this._descr.CanResetValue(component);
    }

    public override object GetValue(object component)
    {
        return this._descr.GetValue(component);
    }

    public override void ResetValue(object component)
    {
        this._descr.ResetValue(component);
    }

    public override void SetValue(object component, object value)
    {
        this._descr.SetValue(component, value);
    }

    public override bool ShouldSerializeValue(object component)
    {
        return this._descr.ShouldSerializeValue(component);
    }

    public override Type ComponentType
    {
        get { return this._descr.ComponentType; }
    }

    public override bool IsReadOnly
    {
        get { return this._descr.IsReadOnly; }
    }

    public override Type PropertyType
    {
        get { return this._descr.PropertyType; }
    }
}

Finally, we need our custom TypeDescriptionProvider and way to bind it to our model type. By default, TypeDescriptionProviderAttribute is designed to perform that binding. But in this case we will not able to get default provider that we want to use internally. In most cases, default provider will be ReflectTypeDescriptionProvider. But this is not guaranteed and this provider is inaccessible due to it's protection level - it's internal. But we do still want to fallback to default provider.

TypeDescriptor also allow to explicitly add provider for our type via AddProvider method. That what we will use. But firstly, let's define our custom provider itself:

public class MyTypeDescriptionProvider : TypeDescriptionProvider
{
    private readonly TypeDescriptionProvider _defaultProvider;

    public MyTypeDescriptionProvider(TypeDescriptionProvider defaultProvider)
    {
        this._defaultProvider = defaultProvider;
    }

    public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
    {
        return new MyTypeDescription(this._defaultProvider.GetTypeDescriptor(objectType, instance));
    }
}

The last step is to bind our provider to our model types. We can implement it in any way we want. For example, let's define some simple class, such as:

public static class TypeDescriptorsConfig
{
    public static void InitializeCustomTypeDescriptorProvider()
    {
        // Assume, this code and all models are in one assembly
        var types = Assembly.GetExecutingAssembly().GetTypes()
                            .Where(t => t.GetProperties().Any(p => p.IsDefined(typeof(CustomBindingNameAttribute))));

        foreach (var type in types)
        {
            var defaultProvider = TypeDescriptor.GetProvider(type);
            TypeDescriptor.AddProvider(new MyTypeDescriptionProvider(defaultProvider), type);
        }
    }
}

And either invoke that code via web activation:

[assembly: PreApplicationStartMethod(typeof(TypeDescriptorsConfig), "InitializeCustomTypeDescriptorProvider")]

Or simply call it in Application_Start method:

public class MvcApplication : HttpApplication
{
    protected void Application_Start()
    {
        TypeDescriptorsConfig.InitializeCustomTypeDescriptorProvider();

        // rest of init code ...
    }
}

But this is not the end of the story. :(

public class TestModel
{
    [CustomBindingName("actual_name")]
    [DisplayName("Yay!")]
    public string TestProperty { get; set; }
}

If we try to write in .cshtml view something like:

ArgumentException

An exception of type 'System.ArgumentException' occurred in System.Web.Mvc.dll but was not handled in user code

Additional information: The property Some.Namespace.TestModel.TestProperty could not be found.

That because all helpers soon or later invoke ModelMetadata.FromLambdaExpression method. And this method take expression we provided (x => x.TestProperty) and takes member name directly from member info and have no clue about any of our attributes, metadata (who cares, huh?):

internal static ModelMetadata FromLambdaExpression<TParameter, TValue>(/* ... */)
{
    // ...

        case ExpressionType.MemberAccess:
            MemberExpression memberExpression = (MemberExpression) expression.Body;
            propertyName = memberExpression.Member is PropertyInfo ? memberExpression.Member.Name : (string) null;
            //                                  I want to cry here - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    // ...
}
x => x.TestProperty
TestModel
actual_name
TestProperty
the property could not be found

However despite this little inconvenience there are several workarounds, such as:

The easiest way is to access our members by theirs redefined names:

@model Some.Namespace.TestModel
@Html.DisplayName("actual_name") @* this will render "Yay!" *@

This is not good. No intellisense at all and as our model change we will have no any compilation errors. On any change anything can be broken and there is no easy way to detect that.

Another way is a bit more complex - we can create our own version of that helpers and forbid anybody from calling default helpers or ModelMetadata.FromLambdaExpression for model classes with renamed properties.

Finally, combination of previous two would be preferred: write own analogue to get property name with redefinition support, then pass that into default helper. Something like this:

@model Some.Namespace.TestModel
@Html.DisplayName(Html.For(x => x.TestProperty))

Compilation-time and intellisense support and no need to spend a lot of time for complete set of helpers. Profit!

Also everything described above work like a charm for model binding. During model binding process default binder also use metadata, gathered by TypeDescriptor.

But I guess binding json data is the best use case. You know, lots of web software and standards use lowercase_separated_by_underscores naming convention. Unfortunately this is not usual convention for C#. Having classes with members named in different convention looks ugly and can end up in troubles. Especially when you have tools that whining every time about naming violation.

ASP.NET MVC default model binder does not bind json to model the same way as it happens when you call newtonsoft's JsonConverter.DeserializeObject method. Instead, json parsed into dictionary. For example:

{
    complex: {
        text: "blabla",
        value: 12.34
    },
    num: 1
}
{ "complex.text", "blabla" }
{ "complex.value", "12.34" }
{ "num", "1" }

And later these values along with others values from query string, route data and so on, collected by different implementations of IValueProvider, will be used by default binder to bind a model with help of metadata, gathered by TypeDescriptor.

So we came full circle from creating model, rendering, binding it back and use it.

asp.net mvc - How to bind view model property with different name - St...

asp.net-mvc razor data-annotations model-binding asp.net-mvc-5
Rectangle 27 2

You need a couple of generic types for your Notes class. The first is so you can derive from it and still allow the expression to filter on the derived class. The second is to specify the type of the property you wish to use to order by. For example:

public abstract class Notes<T, TProperty> where T : Notes<T, TProperty>
{
    public abstract Expression<Func<T, TProperty>> OrderByField();

    public string GetOrderByFieldName()
    {
        //snip
    }
}

public class Message : Notes<Message, int>
{
    public int item_no { get; set; }

    public override Expression<Func<Message, int>> OrderByField()
    {
        return m => m.item_no;
    }
}

Thanks for your answer, but my project structure doesn't allow me to create a number of generic types for Notes class, so much so that if your solution is indeed the only solution, then I may need to look for workarounds for GetOrderByFieldName method implementation.

Without a generic type, your code wouldn't even compile.

GetOrderByFieldName

It's not just that, but you can't override in the Message class with a different type for OrderByField.

Before I saw your answer, I was thinking if there is a way to define a pack of abstract OrderBy methods in the base class with different type parameters, but a child class would be required to override just one of the pack, depending on the type of the order by field it is going to use, which is obviously impossible, and I know I sound stupid! The idea of generic base class didn't hit me, until I saw your answer.

c# - Return Expression from a method to be used in OrderBy - Stack Ove...

c# linq lambda expression-trees
Rectangle 27 1

public static class HtmlExtensions
{
    public static IHtmlString EnumDropDownListFor<TModel>(
        this HtmlHelper<TModel> html, 
        Expression<Func<TModel, DynamicEnum>> expression)
    {
        var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
        var dynamicEnum = (DynamicEnum)metadata.Model;
        var enumType = Type.GetType(dynamicEnum.Name, true);
        if (!enumType.IsEnum)
        {
            throw new Exception(dynamicEnum.Name + " doesn't represent a valid enum type");
        }

        // TODO: You definetely want to cache the values here to avoid the expensive
        // reflection call: a ConcurrentDictionary<Type, IList<SelectListItem>> could be used
        var enumNames = Enum.GetNames(enumType);
        var values = enumNames.Select(x => new SelectListItem
        {
            Text = x,
            Value = ((int)Enum.Parse(enumType, x)).ToString(),
        }).ToList();

        string name = ExpressionHelper.GetExpressionText(expression) + ".Value";

        return html.DropDownList(name, values);
    }
}

Remark: The HtmlHelper.EnumDropDownListFor extension method already exists in ASP.NET MVC so make sure that you bring the namespace in which you declared your custom extension method into scope to avoid collisions. Or just use a different method name.

I think it based on which version he is using. If 5.2 then it akready exists.

@DarinDimitrov Thank you. It's perfect, I just add Selected to SelectListItem, and I am just wondering as long as I used MVC 5.2.3 is there any way that in Custom Helper we return EnumDropDownListFor instead of DropDownList?

@Saeid, no unfortunately there's no way because this built-in helper expects an expression that returns a property of type Enum which you do not have. According to your requirements you have a custom view model with a string and value properties which must be transformed before being used. Also I really don't understand why you edited my answer and added this Selected property? The idea here is that the selected value will come from the integer Value property of the view model which is why I used the ExpressionHelper.GetExpressionText method.

asp.net mvc - MVC html helper to generate enum drop down list dynamicl...

asp.net-mvc razor html-helper