Can't get error message on BadRequest in Web Api 2
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;
Related videos on Youtube
Toni Moreno
Updated on May 16, 2020Comments
-
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 over 8 yearsCan 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 over 8 yearsAdded the code requested
-
jolySoft over 8 years@ToniMoreno Can you post where you add your filters if you have any
-
Toni Moreno over 8 years
code
public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute());}
-
Toni Moreno over 8 yearsIt 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 over 8 years@ToniMoreno Sorry quick, corrected now. Possible duplicate here to, have a look at this: stackoverflow.com/questions/12519561/…
-
jsxsl over 8 yearsMaking this change to return an HttpResponseException then adding the error detail policy I posted should return your the error details!