Подтвердить что ты не робот

DataAnnotation для обязательного свойства

Сначала это работает, но сегодня это провалилось!

Вот как я определяю свойство date:

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

Отчет Firebug:

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

--- обновление ---

Я обнаружил временное решение. См. Ответ ниже. Если кто-нибудь поймет, почему он работает или имеет лучшие решения, отправьте свои ответы. Спасибо.

4b9b3361

Ответ 1

Хорошо. Хотя я еще не понял этого. Обходной путь найден.

В Global.asax:

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

Я нашел его в Tracker Issue в aspnetwebstack. Вот ссылка на страницу:

Слишком агрессивная проверка для применения [DataMember (IsRequired = true)] к требуемым свойствам со значениями типов

Если кто-нибудь скажет нам, почему это так, пожалуйста, напишите свое понимание в качестве ответов. Спасибо.

Ответ 2

Я добавил 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);

Таким образом, я продолжаю использовать оригинальную аннотацию данных.

Ссылка

Ответ 3

ОБНОВЛЕНИЕ 24-5-2013: InvalidModelValidatorProvider, ответственный за это сообщение об ошибке, был удален из стека технологий ASP.NET. Этот валидатор доказал, что вызывает больше путаницы, чем он должен был решить. Для получения дополнительной информации см. Следующую ссылку: http://aspnetwebstack.codeplex.com/workitem/270

Когда вы украшаете свой класс атрибутом [DataContract], вам необходимо явно украсить элементы, которые вы хотите сериализовать, с атрибутом [DataMember].

Проблема заключается в том, что DataContractSerializer не поддерживает атрибут [Required]. Для ссылочных типов мы можем проверить, что после десериализации значение не равно нулю. Но для типов значений мы не можем обеспечить семантику [Required] для DataContractSerializer без [DataMember(IsRequired=true)].

Таким образом, вы можете пометить DateTime как [Required] и ожидать ошибку проверки модели, если DateTime не отправлен, но вы просто получите значение DateTime.MinValue и не получите ошибку проверки.

Ответ 4

Если вы пытаетесь вернуть результат своего действия в формате XML, вам нужно будет использовать DataContracts, как того требует сериализатор по умолчанию. Я предполагаю, что вы ранее запрашивали вывод своего действия как Json, сериализатор Json не требует контрактов с данными. Можете ли вы опубликовать скрипт вашего запроса?