it-swarm.com.de

DataAnnotation für Required-Eigenschaft

Zuerst funktioniert es, aber heute ist es fehlgeschlagen! 

So definiere ich die Date-Eigenschaft:

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

Es hat in der Vergangenheit gearbeitet. Aber heute, wenn ich dieselbe ApiController-Aktion anrufe:

[HttpPost]
public HttpResponseMessage SaveNewReport(TripLeaderReportInputModel model)

Der Firebug berichtet:

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"

Was ist passiert? Ist das nicht [DataContract] für WCF? Ich verwende den REST WebAPI in MVC4!

Kann jemand helfen? Bitte?

---aktualisieren---

Ich habe einige ähnliche Links gefunden.

MvC 4.0 RTM hat uns kaputt gemacht und wir wissen nicht, wie wir das beheben können RSS

--- wieder aktualisieren ---

Hier ist der HTTP Response Header:

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

Anforderungsheader:

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

--- Update ---

Ich habe eine provisorische Lösung gefunden. Siehe Antwort unten. Wenn jemand versteht, warum es funktioniert oder bessere Lösungen hat, dann posten Sie bitte Ihre Antworten. Vielen Dank.

34
Blaise

Okay. Obwohl ich diese Sache nicht vollständig verstanden habe. Eine Problemumgehung wird gefunden.

In Global.asax:

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

Ich habe es im Issue Tracker in aspnetwebstack gefunden. Hier ist der Link zur Seite:

Übermäßig aggressive Validierung für die Anwendung von [DataMember (IsRequired = true)] auf erforderliche Eigenschaften mit Werttypen

Wenn uns jemand sagen kann, warum es so ist, posten Sie bitte Ihre Einsicht als Antwort. Vielen Dank.

33
Blaise

Ich habe eine ModelValidationFilterAttribute hinzugefügt und es funktioniert:

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);
        }
    }
}

Sie können entweder [ModelValidation]-Filter für die Aktionen hinzufügen. Oder füge es in Global.asax.cs hinzu:

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

Auf diese Weise verwende ich weiterhin die ursprünglichen Datenanmerkungen.

Referenz

13
Blaise

UPDATE 24-5-2013: Die InvalidModelValidatorProvider, die für diese Fehlermeldung verantwortlich ist, wurde entfernt aus dem ASP.NET-Technologiestack. Dieser Validator bewies mehr Verwirrung, als er lösen sollte. Weitere Informationen finden Sie unter dem folgenden Link: http://aspnetwebstack.codeplex.com/workitem/270

Wenn Sie Ihre Klasse mit dem Attribut [DataContract] dekorieren, müssen Sie die Member, die Sie serialisieren möchten, explizit mit dem Attribut [DataMember] dekorieren. 

Das Problem ist, dass DataContractSerializer das [Required]-Attribut nicht unterstützt. Bei Referenztypen können wir nach der Deserialisierung überprüfen, ob der Wert nicht null ist. Bei Werttypen besteht jedoch keine Möglichkeit, die [Required]-Semantik für DataContractSerializer ohne [DataMember(IsRequired=true)] durchzusetzen.

So könnten Sie eine DateTime als [Required] kennzeichnen und einen Fehler bei der Modellvalidierung erwarten, wenn die DateTime nicht gesendet wird, Sie erhalten jedoch stattdessen einen DateTime.MinValue-Wert und keinen Validierungsfehler.

10

Wenn Sie versuchen, die Ausgabe Ihrer Aktion als XML zurückzugeben, müssen Sie DataContracts verwenden, wie sie vom Standardserialisierer benötigt werden. Ich vermute, dass Sie zuvor die Ausgabe Ihrer Aktion als Json angefordert hatten. Der Json-Serializer erfordert keine Datenverträge. Können Sie eine Geige Ihrer Anfrage posten?

0
Maess