ASP.NET Web API removes HttpError from responses

I am creating a RESTful service using ASP.NET web API.

My problem is with HttpErrors, which the web API returns to the user when something goes wrong (e.g. 400 Bad Request or 404 Not Found).

The problem is that I don't want to receive a serialized HttpError in the response content, as it sometimes provides too much information, therefore it violates the OWASP security rules, for example:

Request:

http://localhost/Service/api/something/555555555555555555555555555555555555555555555555555555555555555555555 

As an answer, of course, I get 400, but with the following content information:

 { "$id": "1", "Message": "The request is invalid.", "MessageDetail": "The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'MyNamespaceAndMethodHere(Int32)' in 'Service.Controllers.MyController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter." } 

Something like this not only indicates that my WebService is based on ASP.NET WebAPI technology (which is not so bad), but also gives some information about my namespaces, method names, parameters, etc.

I tried setting IncludeErrorDetailPolicy to Global.asax

 GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Never; 

Yes, this is somehow good, now the result does not contain a MessageDetail section, but still I do not want to receive this HttpError at all.

I also created my own DelegatingHandler, but it also affects the 400 and 404 that I myself generate in controllers that I don't want.

My question is: Is there a convenient way to get rid of a serialized HttpError from the content of the answer? All I want the user to return to their bad queries is the response code.

+6
source share
2 answers

How about using custom IHttpActionInvoker? Basically, you just need to send an empty HttpResponseMessage.

Here is a very simple example:

 public class MyApiControllerActionInvoker : ApiControllerActionInvoker { public override Task<HttpResponseMessage> InvokeActionAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken) { var result = base.InvokeActionAsync(actionContext, cancellationToken); if (result.Exception != null) { //Log critical error Debug.WriteLine("unhandled Exception "); return Task.Run<HttpResponseMessage>(() => new HttpResponseMessage(HttpStatusCode.InternalServerError)); } else if (result.Result.StatusCode!= HttpStatusCode.OK) { //Log critical error Debug.WriteLine("invalid response status"); return Task.Run<HttpResponseMessage>(() => new HttpResponseMessage(result.Result.StatusCode)); } return result; } } 

At Global.asax

 GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpActionInvoker), new MyApiControllerActionInvoker()); 

Another important thing you could do that is not related to Web Api is to remove the redundant asp.net and IIS HTTP headers. Here is a good explanation.

+1
source

I believe that your approach to using a message handler is correct, because regardless of the component in the web API pipeline that sets the status code to 4xx, the message handler can clear the body of the response. However, you want to distinguish between those that you explicitly set and those that are installed by other components. Here is my suggestion, and I admit that this is a bit of hacks. If you do not get another better solution, try this.

In your ApiController classes, when you throw an HttpResponseException , set a flag in the request properties, for example.

 Request.Properties["myexception"] = true; throw new HttpResponseException(...); 

In the message handler, check the property and do not clear the response body if the property is set.

 var response = await base.SendAsync(request, cancellationToken); if((int)response.StatusCode > 399 && !request.Properties.Any(p => p.Key == "myException")) response.Content = null; return response; 

You can compose this a bit by adding an extension method to HttpRequestMessage so that neither ApiController nor the message handler ApiController anything about the hard-coded string "myException" that I used above.

+1
source

Source: https://habr.com/ru/post/949202/


All Articles