必需属性的DataAnnotation

时间:2012-09-06 17:58:22

标签: asp.net-mvc-4 asp.net-web-api data-annotations

首先它有效,但今天它失败了!

这就是我定义日期属性的方法:

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

过去一直在努力。但今天,当我调用相同的ApiController动作时:

[HttpPost]
public HttpResponseMessage SaveNewReport(TripLeaderReportInputModel model)

萤火虫报道:

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"

发生什么事了? [DataContract]的{​​{1}}不是吗?我在WCF中使用了REST WebAPI

有人可以帮忙吗?请?

--- ---更新

我发现了一些类似的链接。

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

---再次更新---

这是HTTP响应标头:

MVC4

请求标题:

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

---更新---

我找到了一个临时解决方案。见下面的答案。如果有人理解为什么它有效或有更好的解决方案,请发表您的答案。谢谢。

4 个答案:

答案 0 :(得分:33)

好。虽然我还没有完全理解这件事。找到了解决方法。

Global.asax

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

我在aspnetwebstack的问题跟踪器中找到了它。这是该页面的链接:

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

如果有人能告诉我们为什么会这样,请将您的见解发布为答案。谢谢。

答案 1 :(得分:13)

我添加了ModelValidationFilterAttribute并使其正常工作:

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

您可以在操作上添加[ModelValidation]过滤器。或者将其添加到Global.asax.cs

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

通过这种方式,我继续使用原始数据注释。

Reference

答案 2 :(得分:10)

更新24-5-2013:已从ASP.NET技术堆栈删除了已删除此错误消息的InvalidModelValidatorProvider。该验证器证明引起的混淆比它要解决的更多。有关详细信息,请参阅以下链接:http://aspnetwebstack.codeplex.com/workitem/270

使用[DataContract]属性装饰类时,需要使用[DataMember]属性显式装饰要序列化的成员。

问题是DataContractSerializer不支持[Required]属性。对于引用类型,我们可以在反序列化后检查该值是否为null。但对于值类型,我们无法在没有[Required]的情况下强制执行DataContractSerializer的{​​{1}}语义。

因此,您最终可能会将[DataMember(IsRequired=true)]标记为DateTime,并且如果未发送[Required],则会出现模型验证错误,但您只需获得DateTime }而不是验证错误。

答案 3 :(得分:0)

如果您尝试以XML格式返回操作的输出,则需要使用默认序列化程序所需的DataContracts。我猜你以前一直在请求输出你的动作作为Json,Json序列化器不需要数据合同。你能发一个小提问吗?