As I understand Owin now it is a pipeline of modules you can define that handles incoming requests. Any module can return a response or pass the request to the next module. So that makes it very easy to add logging or authentication or whatnot, very cool.
But what if I would like to log responses? Can you create a module that runs for every response, irrespective of where the response came from in the pipeline? If it is possible, can you provide an example or link, I can't seem to find this scenario on the web.
Turn out it is quite simple and logical, This blogpost shows an example on how to time the request. Since a module either passes the request on to the next module or RETURNS a response it is just a question of registering a module as the first and processing the returnvalue with ContinueWith:
public Task Invoke(IDictionary<string, object> environment)
{
return _next(environment).ContinueWith(result =>
{
Logger.LogResult(result);
return result;
});
}
Related
I'm a beginner in ASP.NET Core, just a question on how middleware generate error.
I'm reading a book that explain the importance of order when you configure middleware:
But I'm a little bit confused, for the second scenario, why can't the image resizing middleware produce an error like:
Because it will be logical for a middleware to generate an error before calling next():
public class ImageResizeMiddleware
{
private readonly RequestDelegate _next;
public ImageResizeMiddleware (RequestDelegate next) { _next = next }
public Task Invoke(HttpContext context)
{
... // if an error occurs here, then 500 should be added to the context here
await next(context); // control passed to the error handling middleware
}
}
So if an error occurs before next(context), then the error handling middleware can see 500 in HttpContext, no?
It depends! Does it make sense for an error to be propagated further in to the pipeline and possibly overwritten by another middleware/controller?
For an image resizing middleware I would expect the handler to check whether the request should be handled by and if not only then pass the request on to the next handler. If the request matches and is handled by the middleware it doesn't make sense to propagate the request further in to the pipeline to potentially be overwritten by something else and should instead return immediately once the response is written. This would mean that the error handling middleware would never be invoked and would not get a chance to prettify/log the error.
Imagine if authentication/authorisation middleware didn't short-circuit the pipeline and return immediately! You could end up with unauthenticated/unauthorised requests to potentially access resources they shouldn't have access to.
Simply put, if an error occurs then the middleware should return and not propagate the request further in to the pipeline.
The idea behind middleware is similar to how Unix commands are supposed to do one thing and do [that] well. By removing the need for each middleware to produce proper error responses, you are removing the need to duplicate the logic all over the place.
If you just look at the default error handling middleware, there are multiple ways to configure it: You could simply return a failure status code, you could have some handler that write directly to the response, you could also have a Razor view that is being displayed to show the user a nice error message.
If each middleware would now be responsible to generate this response, then each middleware would have to be able to do that. But middleware is usually designed to be rather independent: An authentication middleware does not need to care whether you even have Razor views in your application, and especially not how it could render an authentication failure using Razor. Instead, middlewares can rely on standard control mechanisms (e.g. exceptions) and just assume that someone else will hopefully take care of it.
And if you have the error handling middleware early in your pipeline, then that middleware can take care of it. And you only need to configure once how an error should be handled. And if a fancy Razor view should be rendered and returned to the user, then this can be done in this one place.
In my work I was asked to implement health checks into an ASP.NET Web API 2 written in C#. I have searched but all the documentation is for ASP.NET Core and its implementation, does anyone know how to implement health check featurs in the classic / full .NET Framework?
I agree with Igor. Here's a concrete application of what he suggested (obviously, there are other ways to do this, but this is the best way I know how to keep it clear and honor separation of concerns):
Create a new controller. In this example, I'll call it HealthController
Add an action to the controller, and annotate it with [HttpGet]
Place logic inside the action that checks for the stability of external dependencies. For example, if disk access is critical for your API, run a test or two to make sure that the disk is responding like you need it to. If you need to be able to query a database, make a sample query, and make sure it's successful. This part is completely custom and really depends on your API and how it needs to perform.
public class HealthController : ApiController
{
[HttpGet]
public IHttpActionResult Check()
{
// Add logic here to check dependencies
if (/* successful */)
{
return Ok();
}
return InternalServerError(); // Or whatever other HTTP status code is appropriate
}
}
Have an external service issue a GET request to your endpoint (currently at https://whatever.your.domain.is/Health/Check) and report back when it doesn't receive 200 OK for some amount of time.
I've used Amazon CloudWatch in the past and I've been happy with it. There are going to be other services out there that will do this for you, but I don't have any experience with them.
I'm following guides/docs on registering HTTP client within my application. There are couple of services I need to call so I decided to go with "Typed clients".
In order to call another service I need to use OAuth - since this is service-to-service call, when I obtain access token, I cache it + I have setup periodical refresh of token. This means there's another component IAccessTokenCache which gives me access token for service.
Thing I'm struggling to figure out is how to register and configure my typed HTTP client providing it also dependency on IAccessTokenCache.
I'm using ASP.NET Core 2.1 (crucial detail, read on).
HTTP client wrapper looks like this (from: HttpClientFactory in ASP.NET Core 2.1 (Part 2) ):
public class ServiceFooClient
{
public ServiceFooClient(HttpClient client)
{
Client = client;
}
public HttpClient Client { get; }
}
And this is how I register and configure client:
services
.AddHttpClient<ServiceFooClient>(
c =>
{
c.BaseAddress = new Uri("https://www.foo.svc");
// TODO: grab particular access token from cache
c.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "...");
})
.AddHttpMessageHandler<ResponseMonitorHandler>()
.ConfigureHttpMessageHandlerBuilder(
b =>
{
var handler =
b.AdditionalHandlers.OfType<ResponseMonitorHandler>().FirstOrDefault();
if (handler != null)
{
handler.ServiceName = "Foo Service";
}
});
... I'm already configuring HTTP client and even adding my custom HTTP handler. You can see exact point where I want to access IAccessTokenCache, but I can't.
Possible solutions I can think of:
Configure underlying HttpClient in ServiceFooClient wrapper, like:
// ctor
public ServiceFooClient(HttpClient httpClient, IAccessTokenCache tokenCache)
{
Client = httpClient;
Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokenCache.GetToken("Foo"));
}
This could work nicely, except I don't configuration decoupling - suddenly dedicated HTTP client has part of configuration in Startup (base URI, additional HTTP handler) and another part in wrapping class (setting authorization header).
Not using AddHttpClient extension method (and others)
I don't really need to call HttpClientFactoryServiceCollectionExtensions.AddHttpClient<T>(...) - I could do all that stuff myself. But as lazy developer... I don't even want to finish this sentence. There's quite a lot of registering inside, so this is just big no no for me.
Upgrade to ASP.NET Core 2.2
Related to previous point - in 2.1, there's no overload of AddHttpClient (2.2: AddHttpClient<TClient>(this IServiceCollection services, Action<IServiceProvider, HttpClient> configureClient)) which would accept callback with service provider. Upgrading to 2.2 would be probably the best solution, yet I will have to be pretty sure that nothing else gets broken (and I already know that there is/was BC break with getting/setting request tracing ID on HTTP context). This could be potentially risky, so I'm trying first to solve my issue in scope of 2.1.
Compare branch of 2.1 with 2.2: HttpClientFactoryServiceCollectionExtensions
Custom HTTP handler setting request headers
Same way as I now register ResponseMonitorHandler, I could register HTTP handler which has access to IAccessTokenCache and sets request authorization header.
But again, as in first case, this decouples configuration of HTTP client. Also if I had several different access tokens, I would either need to implement several HTTP handlers or do some logic deciding what token from cache to use based on request properties.
Finally, question: is there any other way I didn't consider? Is there easy solution of this in ASP.NET 2.1? (... apart of just copy-pasting method from 2.2 of course)
Apparently, there's another extension method in 2.1 ConfigureHttpClient(IHttpClientBuilder, Action<IServiceProvider,HttpClient>) which does exactly what I need!
We have a WebApi 2.0 application with several controllers, one of which is used to relay data. Due to issues with scalability, we want to move that particular controller out to a separate process so that we can scale it separately from the rest of the application, possibly on a different server altogether. We don't want to break compatibility though, and until we can get all of the clients updated, we will still have requests being made to the old endpoint that controller sat on. What is the simplest way to redirect those requests (it must work with GET/POST/DELETE) to the new location? Does this have to be done within IIS, or is there a way to modify the route? So far we've tried simply returning a redirect response within the old controller, but this doesn't work properly for POST:
public async Task<HttpResponseMessage> Post()
{
var response = Request.CreateResponse(HttpStatusCode.Moved);
response.Headers.Location = new Uri("http://new/api/endpoint");
return response;
Even if it did, we have some library components that use WebClient with auto-redirect turned off, and those would need to be refactored, which is not ideal. Is there a guaranteed solution?
A redirect is nothing more than an HTTP response with a particular status code and some extra information. If your client application isn't going to follow a redirect than that's not an option for solving your problem.
You could have your Post() method act as a proxy for the other web service. As an example, if your first API is at example.com/Site1 and your second API is at example.com/Site2 then you could have your client make a request to Site1 while Site1 internally makes a request to Site2.
Creating an ASP.NET Web API module in Orchard CMS is simple and straightforward. The following link explains how to do it and it works just fine. http://www.sebastienros.com/web-api-makes-it-in-orchard
However, the GET requests does not work when the WebAPI is running under Orchard and you use the [Authorize] attribute at the same time.
[Authorize]
public IEnumerable<string> Get()
{
return _moduleManager.GetUsers().Select(n => n.UserName);
}
When I call this from the client
HttpClientHandler handler = new HttpClientHandler();
handler.Credentials = new NetworkCredential("user", "password");
HttpClient client = new HttpClient(handler);
var response = await client.GetAsync("http://localhost:30321/OrchardLocal/api/MyWebAPIModule/Users");
Console.WriteLine(response);
the response variable returns to me the "Not found" HTML page from Orchard. Without the [Authorize], it returns a list of users.
Does Orchard have something already built-in to match the credentials with a registered user in Orchard? Or is there steps missing in the process?
This blog post may be a helpful resource for a deeper understand ASP.NET's Authorize attribute. It might help to look in the web.config file to see what the authentication mode is set to.
I think the problem is that if you are making a call in code, you need to pass any cookies in the request.
A user is authenticated against the website by the use of the aspnetAuth (or FedAuth) cookie, which is provided by the browser. So if you called /OrchardLocal/api/MyWebAPIModule/Users from the browser you would expect this to work (you should see this happen in fiddler by looking at the headers/cookies).
However if you make a call in code you need to pass cookies/auth. header yourself. The call you have does not have any of this, thus it fails (you should see the absence of the cookie in fiddler for this request).
I'm not sure why you would call the api in this way from within your own module. Presumably the API controller calls a service that does the actual workload. You could call this service directly from your Driver/Action, still safe in the knowledge that your business logic is behind the service interface.