-->

Can't get error message on BadRequest in Web A

2019-06-18 15:34发布

问题:

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\":\"soft@moreno-csa.com\",\"Role\":\"Filtra\",\"Password\":\"TONI\"}"

回答1:

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.



回答2:

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



回答3:

API

return new BadRequestErrorMessageResult(yourErrorMessage);

Client

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


回答4:

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;


回答5:

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.