web-dev-qa-db-fra.com

DataAnnotation for Required property

D'abord cela fonctionne, mais aujourd'hui cela a échoué! 

Voici comment je définis la propriété de date:

[Display(Name = "Date")]
[Required(ErrorMessage = "Date of Submission is required.")]        
[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
[DataType(DataType.Date)]
public DateTime TripDate { get; set; }

Cela a fonctionné dans le passé. Mais aujourd'hui, lorsque j'appelle la même action ApiController:

[HttpPost]
public HttpResponseMessage SaveNewReport(TripLeaderReportInputModel model)

Le Firebug rapporte:

ExceptionMessage:

"Property 'TripDate' on type 'Whitewater.ViewModels.Report.TripLeaderReportInputModel' 
is invalid. Value-typed properties marked as [Required] must also be marked with
[DataMember(IsRequired=true)] to be recognized as required. Consider attributing the 
declaring type with [DataContract] and the property with [DataMember(IsRequired=true)]."

ExceptionType

"System.InvalidOperationException"

Qu'est-il arrivé? Est-ce que ces [DataContract] pour WCF? J'utilise le REST WebAPI dans MVC4!

Quelqu'un peut-il aider? S'il vous plaît?

---mettre à jour---

J'ai trouvé des liens similaires.

MvC 4.0 RTM nous a cassé et nous ne savons pas comment le réparer RSS

--- mettre à jour à nouveau ---

Voici l'en-tête de réponse HTTP:

Cache-Control   no-cache
Connection  Close
Content-Length  1846
Content-Type    application/json; charset=utf-8
Date            Thu, 06 Sep 2012 17:48:15 GMT
Expires         -1
Pragma          no-cache
Server          ASP.NET Development Server/10.0.0.0
X-AspNet-Version    4.0.30319

En-tête de demande:

Accept          */*
Accept-Encoding gzip, deflate
Accept-Language en-us,en;q=0.5
Cache-Control   no-cache
Connection          keep-alive
Content-Length  380
Content-Type    application/x-www-form-urlencoded; charset=UTF-8
Cookie          .ASPXAUTH=1FF35BD017B199BE629A2408B2A3DFCD4625F9E75D0C58BBD0D128D18FFDB8DA3CDCB484C80176A74C79BB001A20201C6FB9B566FEE09B1CF1D8EA128A67FCA6ABCE53BB7D80B634A407F9CE2BE436BDE3DCDC2C3E33AAA2B4670A0F04DAD13A57A7ABF600FA80C417B67C53BE3F4D0EACE5EB125BD832037E392D4ED4242CF6
DNT                 1
Host            localhost:39019
Pragma          no-cache
Referer         http://localhost:39019/Report/TripLeader
User-Agent          Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20100101 Firefox/15.0
X-Requested-With    XMLHttpRequest

--- mettre à jour ---

J'ai trouvé une solution de fortune. Voir la réponse ci-dessous. Si quelqu'un comprend pourquoi cela fonctionne ou a de meilleures solutions, postez vos réponses. Je vous remercie.

34
Blaise

J'ai ajouté un ModelValidationFilterAttribute et l'ai fait fonctionner:

public class ModelValidationFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (!actionContext.ModelState.IsValid)
        {
            // Return the validation errors in the response body.
            var errors = new Dictionary<string, IEnumerable<string>>();
            //string key;
            foreach (KeyValuePair<string, ModelState> keyValue in actionContext.ModelState)
            {
                //key = keyValue.Key.Substring(keyValue.Key.IndexOf('.') + 1);
                errors[keyValue.Key] = keyValue.Value.Errors.Select(e => e.ErrorMessage);
            }
            //var errors = actionContext.ModelState
            //    .Where(e => e.Value.Errors.Count > 0)
            //    .Select(e => new Error
            //    {
            //        Name = e.Key,
            //        Message = e.Value.Errors.First().ErrorMessage
            //    }).ToArray();

            actionContext.Response =
                actionContext.Request.CreateResponse(HttpStatusCode.BadRequest, errors);
        }
    }
}

Vous pouvez soit ajouter un filtre [ModelValidation] aux actions. Ou ajoutez-le dans Global.asax.cs:

GlobalConfiguration.Configuration.Services.RemoveAll(
typeof(System.Web.Http.Validation.ModelValidatorProvider),
v => v is InvalidModelValidatorProvider);

De cette manière, je continue à utiliser l'annotation de données d'origine.

Référence

13
Blaise

UPDATE 24-5-2013: La InvalidModelValidatorProvider responsable de ce message d'erreur a été supprimé de la pile de technologies ASP.NET. Ce validateur a prouvé qu'il pouvait causer plus de confusion qu'il n'était censé en résoudre. Pour plus d'informations, voir le lien suivant: http://aspnetwebstack.codeplex.com/workitem/270

Lorsque vous décorez votre classe avec l'attribut [DataContract], vous devez explicitement décorer les membres que vous souhaitez sérialiser avec l'attribut [DataMember]

Le problème est que DataContractSerializer ne prend pas en charge l'attribut [Required]. Pour les types de référence, nous pouvons vérifier que la valeur n'est pas nulle après la désérialisation. Mais pour les types de valeur, il n’ya aucun moyen pour nous d’appliquer la sémantique [Required] pour DataContractSerializer sans [DataMember(IsRequired=true)].

Ainsi, vous pourriez marquer une DateTime en tant que [Required] et vous attendre à une erreur de validation du modèle si la DateTime n'est pas envoyée, mais vous obtiendrez simplement une valeur DateTime.MinValue et aucune erreur de validation.

10
Martin Devillers

Si vous essayez de renvoyer la sortie de votre action au format XML, vous devrez alors utiliser DataContracts car ils sont requis par le sérialiseur par défaut. Je suppose que vous demandiez précédemment la sortie de votre action en tant que Json, le sérialiseur Json ne nécessite pas de contrat de données. Pouvez-vous poster un violon de votre demande?

0
Maess