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.
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:
If anyone can tell us why it is like this, please post your insight as answers. Thank you.
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.
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.
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