2010-04-06 10 views
5

Estoy usando un objeto que coincide con todos los campos en mi formulario. Luego uso el enlace predeterminado para llenar el objeto en mi acción, así;Problema de datos de formulario de vinculación MVC

public ActionResult GetDivisionData(DivisionObj FormData) 

Mi DivisionObj inicializa todos sus valores en string.empty en el constructor.

El problema es que cuando la carpeta rellena el modelo de los datos del formulario publicado, cualquier información que no se publique se establece en nulo en el objeto, aunque he inicializado el objeto para contener cadenas vacías.

Hay una forma de cambiar esto para que los datos no publicados sean una cadena vacía.

+0

Tendrá que establecer las propiedades en cadenas vacías en su Acción de controlador, manejarlas en su lógica de negocios o en la capa de acceso a datos. Sugeriría que fuera una función para tu BL. – Lazarus

Respuesta

13

Este es el comportamiento predeterminado del DefaultModelBinder, más específicamente el marco de DataAnnotations. ConvertEmptyStringToNull está configurado de forma predeterminada en verdadero. Puede crear su propia carpeta de modelo y reemplazar la carpeta de modelo predeterminada.

public class EmptyStringModelBaseBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     bindingContext.ModelMetadata.ConvertEmptyStringToNull = false; 

     return base.BindModel(controllerContext, bindingContext); 
    } 
} 

Luego, en mundial ...

ModelBinders.Binders.DefaultBinder = new EmptyStringModelBaseBinder(); 

Aunque me hubiera gustado que tenía una forma estática de establecer esto para el modelbinder defecto. Tal vez en v3 :)

O bien, también puede usar el atributo [DisplayFormat(ConvertEmptyStringToNull=false)] para configurar esto por propiedad.

2

Siempre se puede usar [Bind(Exclude="PropertyName1,PropertyName2,PropertyName3")] excluir algunas propiedades de la unión:

public ActionResult GetDivisionData([Bind(Exclude="PropertyName1,PropertyName2,PropertyName3")]DivisionObj FormData) 

Si realmente tiene que tener en String.Empty propiedades de tipo cadena, puede utilizar esta carpeta:

public class EmptyStringModelBinder : DefaultModelBinder 
{ 
    protected override void BindProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor) 
    { 
     base.BindProperty(controllerContext, bindingContext, propertyDescriptor); 
     if (propertyDescriptor.PropertyType == typeof(String)) 
      propertyDescriptor.SetValue(bindingContext.Model,propertyDescriptor.GetValue(bindingContext.Model) ?? String.Empty); 
    } 
} 

Usted También tendré que ejecutar esto en global.asax:

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

Es más dinámico que eso. Mi usuario podría completar el formulario incorrectamente. El punto es que necesito que mi objeto contenga string.empty si un campo se dejó en blanco. – John

1

Solo puedo confi Creo que veo los mismos resultados que tú. Sus opciones son:

Una forma es excluir las propiedades explicadas por LukLed. Pero esto dará lugar a la duplicación del código y tendrá que hacerlo en cada acción del controlador cada vez que aparezca como parámetro de acción la DivisiónObj (o cualquier otra clase de Modelo que desee decorar). Soo es un poco engorroso ...

Actualmente estoy en el proceso de tener problemas múltiples con varias propiedades personalizadas, algunos que necesitan ser instanciados en contructors, algunos que necesitan un valor conocido en tiempo de ejecución y otros que también son especiales de alguna manera.

He determinado que, para mí, es mejor usar Custom Model Binder y hacer la mayoría de estas cosas allí.

+0

Entonces, ¿está diciendo que el enlazador de modelo predeterminado hará que un valor de objeto sea nulo, si no se encontró un valor coincidente en los datos de la publicación, incluso si el objeto se inicializó en string.empty? – John

+0

Lo probé porque tenía algún código a mano cuando respondí su pregunta y funcionó tal como lo está experimentando. Pero no estoy 100% seguro de si siempre funciona así. Puede descargar el origen ASP.NET MVC usted mismo y comprobar las implementaciones DefaultValueProvider y DefaultModelBinder y ver usted mismo cómo lo hacen. – mare

Cuestiones relacionadas