2010-05-08 69 views
6

Tengo un modelo como este:ASPNET MVC: ¿Por qué ModelState.IsValid es falso "El campo x es obligatorio" cuando ese campo tiene un valor?

public PurchaseOrder 
{ 
    [Required] [StringLength(15)] 
    public virtual string OrderNumber {get;set;} 
    // etc.   
} 

Cuando envío una orden de la vista (usando $ .post, no input type = submit) que va a mi clase controlador:

public class PurchaseOrderController 
{ 
    public JsonResult Save(PurchaseOrder order) 
    { 
     // TryUpdateModel(order); // commented out since modelstate.isvalid remains false anyway 
     if (ModelState.IsValid) 
     { 
      // its never valid 
     } 
    } 
} 

ModelState.IsValid siempre devuelve falso, con el error: "Se requiere el campo Número de orden". Pero hay un valor en este campo (¿por qué?)

¿Por qué debería decir "se requiere valor" cuando tiene un valor? ¿Me he perdido algo? ¿Es por el $ .post en lugar del submit? ¿Que puedo hacer?

Esto es lo que se ve como el depurador:

alt text http://www.freeimagehosting.net/uploads/f734f3d95d.png

EDIT: Información adicional ....

Realmente creo que por alguna razón el modelo de unión que no está ocurriendo. Cuando intento este código encontrado aquí:)

if (!ModelState.IsValid) 
{ 
    ModelState.Clear(); 
    ModelMetadata modelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => order, order.GetType()); 
    ModelValidator compositeValidator = ModelValidator.GetModelValidator(modelMetadata, base.ControllerContext); 

    foreach (ModelValidationResult result in compositeValidator.Validate(null)) 
    { 
     this.ModelState.AddModelError(result.MemberName, result.Message); 
    } 
} 

Then ModelState.IsValid = true. compositeValidator.Validate() devuelve 0 errores. Creo que esto indica que el modelo no estaba vinculado, pero aún no sé por qué.

El método controlador en realidad se parece a esto (me perdí el filtro cuando se escribe originalmente esta pregunta)

[JsonFilter(Param = "order", JsonDataType = typeof(PurchaseOrder))] 
public JsonResult Save(PurchaseOrder order) { // etc ... } 

Y el JsonFilter hace esto para extraer la POCO desde el JSON datos presentados:

filterContext.ActionParameters[Param] 
    = jsSerializer.Deserialize(inputContent, JsonDataType); 

Puse un punto de interrupción en esta línea, y el orden es válido, más el orden. OrderNumber tiene el valor correcto.

Así que todavía no resuelto, pero es de esperar que esta información adicional le ayudará a encontrar una solución

+2

¿por qué la propiedad se marca como virtual? ¿Estás usando el seguimiento de cambios POCO? –

+0

¿Cuál es el valor? ¿Cómo estás usando '$ .post'? ¿Funciona con envío normal? –

+0

No sé por qué es virtual, fue así cuando comencé a trabajar en la aplicación existente. –

Respuesta

1

Bueno, lo he "resuelto", pero realmente no entiendo por qué los cambios que he hecho han ayudado.

que tenía que hacer tres cosas:

  1. quitar el filtro JSON (filtros no se unen)

  2. Cambiar el contentType en application/json

    $ .ajaxSetup ({ contentType: "application/json; charset = utf-8" });

  3. Utilice MVC futuros para descargar Microsoft.Mvc.dll como se describe aquí: http://haacked.com/archive/2010/04/15/sending-json-to-an-asp-net-mvc-action-method-argument.aspx. Donde se dice agregar esto a Application_Start() en Global.asax.cs:

    ValueProviderFactories.Factories.Add (new JsonValueProviderFactory());

Ahora no sé exactamente por qué ha funcionado, pero lo ha hecho.

Desafortunadamente, ha tenido un efecto secundario negativo: el tipo de contenido se aplica a todos los métodos $ .get() y $ .post(), y todos mis jqgrids rotos, parecen funcionar solo si el tipo de contenido es el predeterminado de la aplicación/x-www-form-urlencoded

lo tanto he pedido 2 seguimiento de preguntas:

  1. ¿es posible establecer el tipo de contenido en un $ .post() llama? Entonces no tendría que configurar de forma global Jquery - How to make $.post() use contentType=application/json?

  2. ¿Es posible hacer que el trabajo jqrid si el contenttype es application/json? Jquery - How to make $.post() use contentType=application/json?

+0

Parece que necesito cambiar mis $ .post() s que llaman a un método de controlador a $ .ajax(). Pero parece que estoy haciendo algo mal y debería funcionar si contentType es el predeterminado de application/x-www-form-urlencoded. –

+0

JK, sus dos enlaces de preguntas apuntan a la misma pregunta. –

1

¿Estas seguro que el error está viniendo del campo OrderNumber?

Parece extraño que el mensaje de error tenga Número de pedido en 2 palabras.

Intente cambiar el nombre del campo o eliminar la etiqueta requerida para asegurarse de que es allí donde proviene el error.

+1

Creo que el framework MVC lo maneja automáticamente para usted. Es lo mismo que cuando usa Html.LabelFor (model.OrderNumber). La etiqueta dice "Número de orden" con un espacio entre las palabras. –

+0

Si elimino la anotación [Obligatorio], entonces ModelState.IsValid == true. También es el único campo con esta anotación. –

1

Existe la posibilidad de que su publicación de jQuery no se publique correctamente en el controlador. Puede estar publicando solo el número de orden en lugar de un objeto que represente exactamente el modelo. Tendría que ver tu javascript para estar absolutamente seguro.

La forma correcta de colocar a ese método sería (suponiendo que el número de pedido se almacena en una variable de JavaScript llamada "orderNumber":

$.post([url to method], 
     { order: { OrderNumber: orderNumber } }, 
     function(json) { 
     //Insert code for actions to take after AJAX post returns. 
     }, 
     'json'); 

Si este es el caso, entonces el siguiente paso que había Take es comprobar que javascript captura el valor de su número de pedido y lo publica como parte de la solicitud.Un examen rápido a través de Firebug debería poder decirle si eso está sucediendo o no.

Cuestiones relacionadas