Is it possible to return a response from a Web API

2019-09-16 19:52发布

问题:

I have a Web API ApiController base class and I would like to perform some validations in the constructor. This might include checking the current load on the server. If it's high, I'd like to return an appropriate HttpResponseMessage indicating the requestor should try again later.

Is something like this possible?

回答1:

I Haven't tested it but that's not what the constructor is for. I don't think all plumbing is set at that time.

You could use global filters for this purpose. Here you have a sample that sets a global filter for authorization, you should use a similar logic but creating your own filter for your specific purposes.

A global filter would intercept all your requests and is executed before the controller actions so is a good place to perform your task.



回答2:

Even though what you are doing sounds like it may be better to revise the approach. Note that you can throw HttpResponseException since the WebApi is Rest Service HttpResponseException is the recommended way to throw Exceptions back to the client.

var resp = new HttpResponseMessage(HttpStatusCode.NotFound)
{
   Content = new StringContent("No idea what happened "),
   ReasonPhrase = "Something was not Not Found"
}
throw new HttpResponseException(resp);


回答3:

As long as you're using .NET 4.5, then you'd be better off creating a custom MessageHandler. You'll need to extend DelegatingHandler in order to do that.

public class MyHandler : DelegatingHandler {
    protected override async Task<HttpResponseMessage> SendAsync(
            HttpMessageRequest request, CancellationToken cancellationToken) {
        // Access the request object, and do your checking in here for things
        // that might cause you to want to return a status before getting to your 
        // Action method.

        // For example...
        return request.CreateResponse(HttpStatusCode.Forbidden);
    }
}

Then inside your WebApiConfig, just add the following code to use the new Handler:

config.MessageHandlers.Add(new MyHandler());


回答4:

You can't throw HttpResponseException in constructor, that will always cause 500.

Easiest way is to override ExecuteAsync():

public override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken) {
        if (!myAuthLogicCheck()) {
            // Return 401 not authorized
            var msg = new HttpResponseMessage(HttpStatusCode.Unauthorized) { ReasonPhrase = "User not logged in" };
            throw new HttpResponseException(msg);
        }

        return base.ExecuteAsync(controllerContext, cancellationToken);
}