2011-01-03 1284 views
5

Tengo un problema con ASP.Net MVC3 (RC2). Estoy descubriendo que la nueva funcionalidad de enlace de modelo JSON, que está implícita en MVC3, no desea deserializar a una propiedad que tenga un tipo de enumeración.ASP.Net MVC3: ¿por qué la compatibilidad predeterminada para el enlace del modelo JSON no se decodifica en los tipos enum?

Aquí es una clase de muestra y la enumeración de tipo:

public enum MyEnum { Nothing = 0, SomeValue = 5 } 
public class MyClass 
{ 
    public MyEnum Value { get; set; } 
    public string OtherValue { get; set; } 
} 

Consideremos el siguiente código, que supera con éxito la prueba de unidad:

[TestMethod] 
public void Test() 
{ 
    var jss = new JavaScriptSerializer(); 
    var obj1 = new MyClass { Value = MyEnum.SomeValue }; 
    var json = jss.Serialize(obj1); 
    var obj2 = jss.Deserialize<MyClass>(json); 
    Assert.AreEqual(obj1.Value, obj2.Value); 
} 

Si serializar obj1 arriba, pero luego puesto que los datos de un controlador MVC3 (ejemplo a continuación) con un único parámetro de tipo MyClass, cualquier otra propiedad del objeto se deserializará correctamente, pero cualquier propiedad que sea un tipo enum se deserializará al valor predeterminado (cero).

[HttpPost] 
public ActionResult TestAction(MyClass data) 
{ 
    return Content(data.Value.ToString()); // displays "Nothing" 
} 

he descargado el código fuente de CodePlex MVC pero estoy perplejo en cuanto a donde se produce el código real de realizar la deserialización, lo que significa que no puedo trabajar en lo que la gente de Microsoft se han utilizado para llevar a cabo la deserialización y así determinar si estoy haciendo algo mal o si hay una solución alternativa.

Cualquier sugerencia sería apreciada.

+0

He agregado una respuesta en este hilo que podría ayudar. http://stackoverflow.com/questions/6051756/model-binding-to-enums-in-asp-net-mvc-3/9070963#9070963 – Difinity

Respuesta

9

He encontrado la respuesta. Espero que esto se solucione en MVC3 RTM, pero esencialmente lo que ocurre es que el objeto se deserializa correctamente internamente a través de JsonValueProviderFactory, que usa JavaScriptSerializer para hacer el trabajo. Utiliza DeserializeObject() para que pueda pasar los valores al cuaderno de modelo predeterminado. El problema es que el enlazador de modelo predeterminado no convertirá/asignará un valor int cuando el tipo de propiedad sea una enumeración.

No es una discusión de esto en los foros de ASP.Net aquí:
http://forums.asp.net/p/1622895/4180989.aspx

La solución discutida no es reemplazar el ligante modelo por defecto de este modo:

public class EnumConverterModelBinder : DefaultModelBinder 
{ 
    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); 
    } 
} 

Luego, en Application_Start, agregue la siguiente línea:

ModelBinders.Binders.DefaultBinder = new EnumConverterModelBinder(); 
+0

Este problema se solucionará en la próxima versión de ASP.NET MVC. – marcind

0

¿Cómo llamas esta acción? Ha intentado:

$.post(
    '/TestAction', 
    JSON.stringify({ OtherValue : 'foo', Value: 5 }), 
    function(result) { 
     alert('ok'); 
    } 
); 
+0

No lo llamo desde una página web, Estoy llamándolo desde otra aplicación a través de 'WebClient.UploadString()'. El proceso de publicación realmente funciona, solo son las propiedades enum de la clase que no se deserializan. Todas las demás propiedades se ven bien. –

+0

@ Nathan, ¿podría mostrar el código de llamada? –

+0

He encontrado el problema; la clase DefaultModelBinder no convierte ints a Enums. http://forums.asp.net/p/1622895/4180989.aspx –

Cuestiones relacionadas