2

Currently I am facing, a problem, when try to call Web Api put method from MVC Api Client, lets describe my code structure bellow

Test Model (Web Api end)

 public sealed class Test    
    {
        [Required]
        public int Id { get; set; }
        [Required]
        public string Name { get; set; }
    }

Web Api PUT Method

public HttpResponseMessage Put(string token, IEnumerable<Test> data)
{
     [...]
     return Request.CreateResponse(HttpStatusCode.OK);
}

Web Api Custom Filter

 public sealed class ValidateFilterAttribute : ActionFilterAttribute
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="actionContext"></param>
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            if (!actionContext.ModelState.IsValid)
            {
                actionContext.Response = actionContext.Request.CreateErrorResponse(
                    HttpStatusCode.BadRequest, actionContext.ModelState);
            }
        }

    }

Call from Web Api Client

async System.Threading.Tasks.Task VerifiedFAccount()
        {
            using (var client = GetHttpClient())
            {
                var url = string.Concat("/api/Verfication", "?token=", token);

                var data = new SampleTest { Id = 1, Name = "xxx" };
                var temp = new List<SampleTest>();
                temp.Add(data);
                using (HttpResponseMessage response = await client.PutAsJsonAsync
                <IEnumerable<SampleTest>>(url, temp).ConfigureAwait(false))
                {
                    if (response.IsSuccessStatusCode)
                    {


                    }
                }
            }

Client code unable to execute Api call (Even I placed the debug point within Web Api Put method, unable to hit the debug point) & always got the bellow error response

{StatusCode: 500, ReasonPhrase: 'Internal Server Error', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
  Pragma: no-cache
  X-SourceFiles: =?UTF-8?B?STpcRGV2QXJlYUxvY2FsXENPTVBBTlkgLSBQU1AgUFJPSkVDVFNcRS1BdXRob3JpdHkgLSBBdXN0cmVsaXlhXFNvdXJjZUNvbnRyb2xcVHJ1bmtcMDYgRGVjIDIwMTNcRS1BdXRob3JpdHkuQXBpIC0gMjAxM1xFYXV0aG9yaXR5LldlYi5BcGkuUHJlc2VudGF0aW9uTGF5ZXJcYXBpXFNtc2ZBY2NvdW50VmVyZmljYXRpb24=?=
  Cache-Control: no-cache
  Date: Mon, 14 Apr 2014 11:23:27 GMT
  Server: Microsoft-IIS/8.0
  Content-Length: 2179
  Content-Type: application/json; charset=utf-8
  Expires: -1
}}

But when I remove [Required] from Test Model (Web Api end). Then above described client code execute successfully.

Please tell me what is the reason of this kind of confusing behavior ?

Shubhajyoti Ghosh
  • 1,292
  • 5
  • 27
  • 45
  • Why do you send an array of `Test` to the service? In some of my projects it was quite useful to implement an ITraceWriter and register it in order to find the reason for similar errors (see http://www.asp.net/web-api/overview/testing-and-debugging/tracing-in-aspnet-web-api). – Markus Apr 14 '14 at 14:47

1 Answers1

2

The issue you are facing might be because of the behaviour of the default configuration when it comes to data validation. You have a Required attributed on a non-nullable type and since int can't be null, it will always have a value (the default of 0) if the incoming request does not provide the value.

In these cases, the model validator will throw an exception because it doesn't make sense to have a Required attribute on a property that can't be null.

The straightforward way you would be to change a setting on your MVC application:

DataAnnotationsModelValidatorProvider
    .AddImplicitRequiredAttributeForValueTypes = false;

This will get rid of the error that is thrown by the framework. This introduce the problem that you will get a value of 0 even when the request does not include the property. It makes more sense to have your integer be of Nullable<int>. The Required attribute will be able to handle a null value and you will know whether or not the incoming request included the property

public sealed class Test    
{
    [Required]
    public int? Id { get; set; }
    [Required]
    public string Name { get; set; }
}
Simon Belanger
  • 14,752
  • 3
  • 41
  • 35
  • `.AddImplicitRequiredAttributeForValueTypes = false;` is good to know, but actual problem is not `public int?` in my case. I converted my Project from 4 to 4.5 and the problem is gone. Previous project with framework 4, malfunctioning some how. (surprisingly but it is true) – Shubhajyoti Ghosh Apr 28 '14 at 10:10