Getting HTTP 500 instead of HTTP 404 with WCF webapi - wcf-web-api

I am having trouble returning the correct HTTP error code for a "not found" in my WCF Web API code. Here is my api method ...
[WebInvoke(Method = "GET", UriTemplate = "{id}")]
[RequireAuthorisation]
public Customer GetCustomer(int id)
{
var customer = Repository.Find(id);
if (customer == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return customer;
}
I also have a logging handler ...
protected override bool OnTryProvideResponse(Exception exception, ref HttpResponseMessage message)
{
if (exception != null)
{
var msg = "Request failed.";
_logger.Error(exception, msg);
}
message = new HttpResponseMessage
{
StatusCode = HttpStatusCode.InternalServerError
};
return true;
}
What is happening is I am getting the following exception ...
HttpResponseException
"The response message returned by the Response property of this exception should be immediately returned to the client. No further handling of the request message is required."
... which my logging handler picks up and changes the response status code to a 500.
So, based on reading a few blog posts and answers on SO, I changed to this ...
if (customer == null)
{
WebOperationContext.Current.OutgoingResponse.SetStatusAsNotFound();
return null;
}
... but this now give me a 200. Which is clearly wrong.
So, what is the right way to do this? It seems as if the throwing of the HttpResponseException doesn't work and the code after gets executed.

The code snippet for your error handler is always changing the response message to 500 no matter what as you are explicitly setting the status always to 500.
It sounds like what you are trying to do is return a 500 ONLY if it is an application error. If that is the case you should check if the error exception is an HttpResponseException and just return rather than overriding.
As to WebOperationContext, don't use it at all with Web Api as it is basically no-op.
Hope this helps
Glenn

Related

Xamarin Log User Out When 401 Unauthorized Response

I have a Xamarin app that talks to an API. There is a certain scenario that happens when talking to the API in that a 401 (Unauthorized) exception is returned. This 401 (Unauthorized) is returned on purpose when the user account is made inactive so that even though the users token is still valid on the app they wouldn't be able to get any data back from the API.
I want to be able log the user out of the app, only when a 401 (Unauthorized) exception is thrown.
My API call looks like this:
public async Task<T> GetAsync<T>(string url)
{
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _authToken?.AccessToken ?? this.GetToken().AccessToken);
var json = await _client.GetStringAsync(url);
return json.Deserialize<T>();
}
When the debugger reaches the var json = await _client.GetStringAsync(url); line a 401 (Unauthorized) exception is correctly thrown.
I want to be able to handle this 401 (Unauthorized) exception and log the user out of the app (preferably with an alert informing them of this).
I'm currently debugging on an Android device so I tried adding the following code to the MainActivity class.
protected override async void OnCreate(Bundle bundle)
{
AndroidEnvironment.UnhandledExceptionRaiser += AndroidEnvironmentOnUnhandledException;
}
private void AndroidEnvironmentOnUnhandledException(object sender, RaiseThrowableEventArgs e)
{
if(e.Exception.InnerException.GetBaseException().Message == "401 (Unauthorized)")
{
}
}
When the error is thrown I check if its a 401 (Unauthorized). It was here that I thought I would then log the user out of the app but I don't think this is the right direction.
Is there a best practice for handing this type of scenario that I am not aware of yet?
You could try to use try catch to warp var json = await _client.GetStringAsync(url) like the following code.
try
{
var json = await _client.GetStringAsync(url)
}
catch (WebException e)
{
using (WebResponse response = e.Response)
{
HttpWebResponse httpResponse = (HttpWebResponse)response;
Console.WriteLine("Error code: {0}", httpResponse.StatusCode);
using (Stream data = response.GetResponseStream())
using (var reader = new StreamReader(data))
{
// text is the response body
string text = reader.ReadToEnd();
if (text == "401 (Unauthorized)")
{
}
}
}
}

WebApi 2: Custom HttpResponseMessage after handling OperationCanceledException in Message Handler is not returned to client

I am currently investigating in WebApi 2 Message Handler and how to implement a server side timeout using cancellation tokens. If a cancellation occurs a OperationCanceledException is thrown and handled in my Message Handler. In this case I return a HttpResponseMessage with a adequate HttpStatusCode (HttpStatusCode.RequestTimeout).
I expected that my consuming client (using postman) retrieves this HttpStatusCode, but instead "Could not get any response" is displayed, thus my client aborts without any additional information. Could someone explain to me whats the deal with this behavior? What am I missing?
See following example code:
public class RequestTimeoutHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
TimeSpan timeout = TimeSpan.FromSeconds(10.0);
using (CancellationTokenSource timeoutCancellationTokenSource = new CancellationTokenSource(timeout))
using (CancellationTokenSource linkedCancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCancellationTokenSource.Token))
{
try
{
return await base.SendAsync(request, linkedCancellationTokenSource.Token);
}
catch (OperationCanceledException e)
{
return new HttpResponseMessage(HttpStatusCode.RequestTimeout);
}
}
return null;
}
}
My Test Controller Method looks as follows:
[Route("testTimeoutAsyncHandleException"), HttpPost]
public IHttpActionResult TestTimeoutAsynchandle(string hugo, CancellationToken ct)
{
for (int i = 0; i < 500; i++)
{
Thread.Sleep(1000); //sleep 1 sec until exception is thown
if (ct.IsCancellationRequested)
{
ct.ThrowIfCancellationRequested();
}
}
return Ok("yes");
}
turns out, using postman was not my best idea. I created a console application using a httpclient and requested my test method. the httpstatus 408 is returned as expected.

How do I get the URL for the request when I get a BadRequestException in Jax-rs?

I'm getting a BadRequestException when using Jersey 2 and I'd like to get the URL that was used in the request and print it in the logs when the exception is caught.
Is there a property/method combination on the BadRequestException object that will return the URL? I don't see it in the JavaDocs, but it could have a name unrelated to "URL".
You can't get URI from BadRequestException. But you can get it from WebTarget you invoked the request on:
WebTarget target = ClientBuilder.newClient().target("http://localhost");
try {
String result = target.request().get(String.class);
} catch (BadRequestException bre) {
// get the URI
target.getUri();
}
If you don't want to use try-catch block:
Response response = target.request().get();
if (response.getStatus() == 200) {
// OK
} else {
// Handle other state.
}

Restlet: Get response body on failed get()

I am trying to debug a particular connection that responds with a Unauthorized (401). In Restlet this causes Respresentation.get() to throw an error.
What I want to do is get the response body as this particular api gives you greater error information in the body.
Any suggestions?
Thanks,
Luke
I would be reluctant to reccomend it for production but certainly for debugging you can override handleInbound in ClientResource to change the conditions under which an error is thrown. Restlet will then return the body, in the usual way.
ClientResource clientResource = new ClientResource("http://your.url") {
#Override
public Representation handleInbound(Response response) {
Representation result = null;
if (response.getRequest().isSynchronous()) {
if (response.getStatus().isError()
&& !Status.CLIENT_ERROR_UNAUTHORIZED.equals(response.getStatus())) {
doError(response.getStatus());
} else {
result = (response == null) ? null : response.getEntity();
}
}
return result;
}
};
Representation response = clientResource.get();
System.out.println(response.getText());

Mvc4 WepApi Empty Response when non 200

When an Action is called and throws a specific exception, I use an ExceptionFilterAttribute that translate the error into a different response as HttpStatusCode.BadRequest. This has been working locally, but we pushed it to a server and now when I get the BadRequest I do not get any information in the reponse. What am I missing?
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
MyException ex = actionExecutedContext.Exception as MyException;
if (ex == null)
{
base.OnException(actionExecutedContext);
return;
}
IEnumerable<InfoItem> items = ex.Items.Select(i => new InfoItem
{
Property = i.PropertyName,
Message = i.ToString()
});
actionExecutedContext.Result = new HttpResponseMessage<IEnumerable<InfoItem>>(items, HttpStatusCode.BadRequest);
}
Edit: When I hit the service locally the body is included. It seems the problem is when hitting the service from a remote machine.
Try this:
GlobalConfiguration.Configuration.IncludeErrorDetailPolicy =
IncludeErrorDetailPolicy.Always