34

首先它可以工作,但今天它失败了!

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

[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]为了WCF?我正在使用REST WebAPIin MVC4

任何人都可以帮忙吗?请?

- -更新 - -

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

MvC 4.0 RTM 打破了我们,我们不知道如何修复它 RSS

---再次更新---

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

请求标头:

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

- - 更新 - -

我找到了一个临时解决方案。请参阅下面的答案。如果有人理解它为什么起作用或有更好的解决方案,请发布您的答案。谢谢你。

4

4 回答 4

34

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

Global.asax

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

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

将 [DataMember(IsRequired=true)] 应用于具有值类型的所需属性的过于激进的验证

如果有人可以告诉我们为什么会这样,请发表您的见解作为答案。谢谢你。

于 2012-09-06T18:45:51.153 回答
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);

就这样,我继续使用原来的数据标注。

参考

于 2012-09-20T18:03:25.217 回答
10

2013 年 5 月 24日更新:InvalidModelValidatorProvider导致此错误消息的原因已从ASP.NET 技术堆栈中删除。这个验证器被证明会引起比它想要解决的更多的混乱。有关详细信息,请参阅以下链接:http ://aspnetwebstack.codeplex.com/workitem/270

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

问题是DataContractSerializer不支持该[Required]属性。对于引用类型,我们能够在反序列化后检查该值是否不为空。但是对于值类型,我们无法强制执行without的[Required]语义。DataContractSerializer[DataMember(IsRequired=true)]

因此,如果未发送,您最终可能会标记DateTime[Required]并期望模型验证错误DateTime,但您只会得到一个DateTime.MinValue值而没有验证错误。

于 2012-09-06T18:05:34.370 回答
0

如果您尝试将操作的输出作为 XML 返回,那么您将需要使用 DataContracts,因为默认序列化程序需要它们。我猜您之前一直请求将您的操作输出为 Json,Json 序列化程序不需要数据协定。您可以发布您的请求的小提琴吗?

于 2012-09-06T18:03:30.827 回答