模型绑定到枚举在ASP.NET MVC 3 [英] Model Binding to Enums in ASP.NET MVC 3

查看:144
本文介绍了模型绑定到枚举在ASP.NET MVC 3的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的控制器中有一个接受一个对象作为参数的方法,并返回一个 JsonResult 。此对象的其中一个属性是具有三个可能值的枚举。我假设当客户端通过int属性传递该属性时,它将填充枚举,但它不会,默认为0,并且枚举被设置为可能的选择中的第一个。



任何建议?

解决方案

注意:这已在MVC 4中解决。 strong>如果升级到MVC 4是您项目的可行选项,那么这就是为了开始模型绑定到枚举所需要做的所有。



这是MVC 3的解决方法,如果您仍然需要它。






问题是MVC中的默认模型binder。正确的整数值使其成为模型绑定器,但是绑定器未被编码以映射到枚举的整数值。如果传入的值是包含枚举的命名值的字符串,它将正确绑定。这样做的问题是,当您使用 Json()方法将C#对象解析为JSON时,它会将整数值作为枚举值发送,而不是命名的值。 p>

最简单和最透明的修复方法是覆盖默认模型binder,并编写一些自定义逻辑来修复绑定枚举的方式。


  1. 像这样创建一个新类。

     命名空间CustomModelBinders 
    {
    ///< summary>
    ///覆盖DefaultModelBinder,以实现其行为的修复。
    ///此模型binder从默认模型binder继承。所有这一切都会覆盖默认值,
    ///检查属性是否为枚举,如果是,则使用自定义绑定逻辑来正确映射枚举。如果没有,
    ///我们简单地调用基本模型绑定器(DefaultModelBinder),并让它继续正常绑定。
    ///< / summary>
    public class EnumModelBinder:DefaultModelBinder
    {
    ///< summary>
    ///修复默认模型binder在绑定到JSON时解码枚举类型的失败。
    ///< / summary>
    保护覆盖对象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);
    }
    }
    }
    }
    返回base.GetPropertyValue(controllerContext,bindingContext,propertyDescriptor,propertyBinder);
    }
    }
    }


  2. 然后只需注册它在您的Global.asax文件中。

      protected override void OnApplicationStarted()
    {
    base.OnApplicationStarted ();

    AreaRegistration.RegisterAllAreas();
    RegisterRoutes(RouteTable.Routes);

    //注册新模型binder
    ModelBinders.Binders.DefaultBinder = new EnumModelBinder();
    }


就是这样。枚举现在将正确绑定在JSON对象上。



http://www.codetunnel.com/how-to-bind-to-enums-on-json-objects-in-aspnet- 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?

解决方案

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

这篇关于模型绑定到枚举在ASP.NET MVC 3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆