Can't get error message on BadRequest in Web Api 2

24,954

Solution 1

Finally, I gived up. Maybe some code at web.config, mvc config, api config, filtering or whatever is disturbing and sending a diferent response than the controller does. I added a status code and a message property to my DTO and return always an object. Thanks anyway to all who tried to help me.

Solution 2

API

return new BadRequestErrorMessageResult(yourErrorMessage);

Client

var errorMessage = responseMessage.Content.ReadAsStringAsync().GetAwaiter().GetResult();
MessageBox.Show(errorMessage);

Solution 3

Have you checked your web.config httpErrors section?

I had the same issue because my web.config looked like this

<httpErrors errorMode="Custom" existingResponse="Replace">
    <clear />
    <error statusCode="404" path="~/Error/NotFound" responseMode="ExecuteURL" />
    <error statusCode="403" path="~/Error/AccessDenied" responseMode="ExecuteURL" />
    <error statusCode="500" path="~/Error/ServerError" responseMode="ExecuteURL" />
</httpErrors>

You must make sure that existingResponse is set to PassThrough

<httpErrors errorMode="Custom" existingResponse="PassThrough">
    <clear />
    <error statusCode="404" path="~/Error/NotFound" responseMode="ExecuteURL" />
    <error statusCode="403" path="~/Error/AccessDenied" responseMode="ExecuteURL" />
    <error statusCode="500" path="~/Error/ServerError" responseMode="ExecuteURL" />
</httpErrors>

Not sure if it will help you, but give it a shot.

Solution 4

Instead of returning it, throw a request exception:

throw new HttpResponseException(HttpStatusCode.BadRequest);

Unless you require more detail passing o the client in which case you could pass back a Request.CreateErrorResponse but you would need to change the return type to HttpResponseMessage

Solution 5

Add the line below to WebAPIConfig.cs in the Register method. This will include the error details instead of just the generic 500 internal server error.

        GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
Share:
24,954

Related videos on Youtube

Toni Moreno
Author by

Toni Moreno

Updated on May 16, 2020

Comments

  • Toni Moreno
    Toni Moreno about 4 years

    I've googled a lot searching for an answer to my problem with no luck so, let's try if someone else can help me.

    I have a Web Api 2 action to register an user after doing some validations. If everything works, it return the serialized user and if don't, an error message sent within a BadRequest response.

    At the other hand, I have a WPF client that calls the API for a response.

    My problem is that I can't get the reason sent by the error, the client just get the Bad Request error message.

    This is a part of the code:

    • Web Api Action:

      public async Task<IHttpActionResult> AddUser(NewUserDTO {
          if (!ModelState.IsValid)
          {
              return BadRequest(ModelState);
          }
          if (!model.IdCliente.HasValue)
          {
              ModelState.AddModelError("", "No existe el cliente");
              return BadRequest(ModelState);
          }
          // do save stuff
          return Ok(TheModelFactory.Create(user));
      }
      
    • Client function:

      public async Task<ApplicationUserDTO> AddUser(NewUserDTO dto) {
          using (var client = new HttpClient()) {
              client.BaseAddress = new Uri(_urlBase);
              client.DefaultRequestHeaders.Accept.Clear();
              client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
              client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Token);
              HttpContent content = new StringContent(JsonConvert.SerializeObject(dto));
              content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
              HttpResponseMessage responseMessage = await client.PostAsync("api/accounts/AddUser", content);
              if (responseMessage.IsSuccessStatusCode) {
                  var responseJson = await responseMessage.Content.ReadAsStringAsync();
                  user = JsonConvert.DeserializeObject<ApplicationUserDTO>(responseJson);
              }
              else
                   MessageBox.Show(responseMessage.Content.ReadAsStringAsync().Result);
              return user;
          } 
      }
      

    Anyone can help?

    Edited:

    • DTO:

      [Serializable]
      public class NewUserDTO {
      public int? IdCliente { get; set; }
      [Required]
      public string UserName { get; set; }
      [Required]
      public string Email { get; set; }
      public string Role { get; set; }
      public string Password { get; set; } }
      

    Anyway... the dto is sent correctly to api nut, here's the serialized dto as you asked for:

    "{\"IdCliente\":null,\"UserName\":\"Toni\",\"Email\":\"[email protected]\",\"Role\":\"Filtra\",\"Password\":\"TONI\"}"
    
    • Pankaj Kapare
      Pankaj Kapare over 8 years
      Can you put debug point at line HttpContent content = new StringContent(JsonConvert.SerializeObject(dto)); and post value of content? Also definition of NewUserDTO type as well.
    • Toni Moreno
      Toni Moreno over 8 years
      Added the code requested
    • jolySoft
      jolySoft over 8 years
      @ToniMoreno Can you post where you add your filters if you have any
    • Toni Moreno
      Toni Moreno over 8 years
      code public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute());}
  • Toni Moreno
    Toni Moreno over 8 years
    It doesn't work. I guess the error is cached by any filter and it returns to the client the html source code for the Internal Server Error page.
  • jolySoft
    jolySoft over 8 years
    @ToniMoreno Sorry quick, corrected now. Possible duplicate here to, have a look at this: stackoverflow.com/questions/12519561/…
  • jsxsl
    jsxsl over 8 years
    Making this change to return an HttpResponseException then adding the error detail policy I posted should return your the error details!