Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
557 views
in Technique[技术] by (71.8m points)

c# - Model Binding to Enums in ASP.NET MVC 3

I have a method in my controller that accepts an object as an argument and returns a JsonResult. One of the properties on this object is an enum with three possible values. I assumed that when the client passed in an int for that property it would populate the enum, but it doesn't, it defaults to 0 and the enum is set to the first of it's possible selections.

Any suggestions?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

NOTE: This has been resolved in MVC 4. If upgrading to MVC 4 is a viable option for your project then that is all you have to do in order to begin model-binding to enums.

That said, here is the workaround for MVC 3 if you still need it.


The issue is with the default model binder in MVC. The correct integer value makes it to the model binder but the binder is not coded to map to the integer value of the enum. It correctly binds if the value being passed in is a string containing the named value of the enum. The problem with this is that when you parse a C# object into JSON using the Json() method it sends the integer value as the enum value, not the named value.

The easiest and most transparent fix for this is to override the default model binder and write some custom logic to fix the way it binds enums.

  1. Create a new class, like so.

    namespace CustomModelBinders
    {
        /// <summary>
        /// Override for DefaultModelBinder in order to implement fixes to its behavior.
    
        /// This model binder inherits from the default model binder. All this does is override the default one,
        /// check if the property is an enum, if so then use custom binding logic to correctly map the enum. If not,
        /// we simply invoke the base model binder (DefaultModelBinder) and let it continue binding as normal.
        /// </summary>
        public class EnumModelBinder : DefaultModelBinder
        {
            /// <summary>
            /// Fix for the default model binder's failure to decode enum types when binding to JSON.
            /// </summary>
            protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext,
                PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder)
            {
                var propertyType = propertyDescriptor.PropertyType;
                if (propertyType.IsEnum)
                {
                    var providerValue = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
                    if (null != providerValue)
                    {
                        var value = providerValue.RawValue;
                        if (null != value)
                        {
                            var valueType = value.GetType();
                            if (!valueType.IsEnum)
                            {
                                return Enum.ToObject(propertyType, value);
                            }
                        }
                    }
                }
                return base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder);
            }
        }
    }
    
  2. Then simply register it in your Global.asax file.

    protected override void OnApplicationStarted()
    {
        base.OnApplicationStarted();
    
        AreaRegistration.RegisterAllAreas();
        RegisterRoutes(RouteTable.Routes);
    
        // Register your new model binder
        ModelBinders.Binders.DefaultBinder = new EnumModelBinder();
    }
    

That's it. Enums will now be correctly bound on JSON objects.

http://www.codetunnel.com/how-to-bind-to-enums-on-json-objects-in-aspnet-mvc-3


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...