DataAnnotation for Required property

大兔子大兔子 提交于 2019-11-26 19:34:59

问题


First it works, but today it failed!

This is how I define the date property:

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

It has been working in the past. But today, when I call the same ApiController action:

[HttpPost]
public HttpResponseMessage SaveNewReport(TripLeaderReportInputModel model)

The Firebug reports:

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"

What happened? Isn't those [DataContract] for WCF? I am using the REST WebAPI in MVC4!

Can anyone help? please?

---update---

There are some similar links I have found.

MvC 4.0 RTM broke us and we don't know how to fix it RSS

--- update again ---

Here is the 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

Request Header:

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 ---

I have found out a makeshift solution. See answer below. If anyone understand why it works or has better solutions, please post your answers. Thank you.


回答1:


Okay. Though I have not complete understood this thing. A workaround is found.

In Global.asax:

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

I found it in the Issue Tracker in aspnetwebstack. Here is the link to the page:

Overly aggressive validation for applying [DataMember(IsRequired=true)] to required properties with value types

If anyone can tell us why it is like this, please post your insight as answers. Thank you.




回答2:


I have added a ModelValidationFilterAttribute and made it work:

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

You can either add [ModelValidation] filter on the actions. Or add it into Global.asax.cs:

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

In this way, I continue to use the original data annotation.

Reference




回答3:


UPDATE 24-5-2013: The InvalidModelValidatorProvider responsible for this error message has been removed from the ASP.NET technology stack. This validator proofed to cause more confusion than it was meant to solve. For more information, see the following link: http://aspnetwebstack.codeplex.com/workitem/270

When you decorate your class with [DataContract] attribute, you need to explicitly decorate the members you would want to serialize with the [DataMember] attribute.

The issue is that DataContractSerializer does not support the [Required] attribute. For reference types, we're able to check that the value is not null after deserialization. But for value types, there is no way for us to enforce the [Required] semantics for DataContractSerializer without [DataMember(IsRequired=true)].

So you could end up marking an DateTime as [Required] and expect a model validation error if the DateTime isn't sent, but you'd just get a DateTime.MinValue value and no validation error instead.




回答4:


If you are attempting to return the output of your action as XML, then you will need to use DataContracts as they are required by the default serializer. I am guessing that you had previously been requesting the output of your action as Json, the Json serializer does not require data contracts. Can you post a fiddle of your request?



来源:https://stackoverflow.com/questions/12305784/dataannotation-for-required-property

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!