Is Serilog DiagnosticContext thread safe? - asp.net-core

I am working on a prototype logging solution using Serilog in ASP.NET Core 3.1 and one of my requirements is the ability to log the entire HTTP request and response payload. To do this, I am writing my own middleware and instead of creating a whole new log entry for this data, I would like to associate the request and response payload with the current log context via Serilog's IDiagnosticContext / DiagnosticContext in https://github.com/serilog/serilog-extensions-hosting
I've been studying the code a bit and it appears it is thread-safe by way of the AmbientDiagnosticContextCollector class and the System.Threading.AsyncLocal that it utilizes.
Is my understanding of this correct or am I missing something that I should be accounting for?

Related

How to fix WrongInputException in ASP.NET Core?

I want to use a SOAP web service prepared by another team, used internally in my new REST API prepared in ASP.NET Core. My web service client code was scaffolded with WCF Web Service Reference Provider Tool. I cleaned up code (e.g. I changed property and method names) according to my team's naming convention.
When I send requests by my new REST API, I received WrongInputException. I checked all the parameters from an example request, all of them are in the same place in my C# code consuming scaffolded client.
I don't know what message exactly is sent by my new REST API.
In my case, the main cause of the described behavior and WrongInputException was premature refactoring. I changed the names of properties in the web service client without knowledge of the consequences.
E.g. if the element in the request body is objectRefNum, then I cannot simply change the related property in the scaffolded service reference class, because - without extra configuration - that name is copied with the same letter case to the request body of the SOAP envelope. The SOAP envelope should be encoded in the case-sensitive mode.
To trace the raw request body send by my new REST API in ASP.NET Core, I followed instructions from this excellent answer.
(Note, BTW, that kind of error (applying inappropriate letter case) could be handled by IDE, at least as a warning, but it is not, so: we need to be careful when we make refactoring, even if we have unit tests covering all the paths, and even if we use semantic renaming supported by IDE.)

How to access to request body using WebFlux and Netty HttpClient

I need to calculate some kind of digest of the request body using the WebClient of Webflux and this digest must be set into a HTTP header. Using the good old Spring MVC ClientHttpRequestInterceptor is easy because the request body is provided as an array of bytes.
The ExchangeFilterFunction does not provide access to the request body.
The body is sent as JSon and Spring uses Jackson in order to serialize Java objects, so an option could be serialize my Object into Json and calculate the digest on it, but this strategy has two drawbacks:
my code would repeat what Spring will do when the request is actually sent
there's no guarantee that the acutal bytes sent by Spring as a request are equal to what I've passed to the digest function
I suppose that I should use some low level API of Netty, but I can't find any example.
I implemented the solution proposed by #rewolf and it worked, but I encountered an issue because of the multi-threading nature of WebFlux.
In fact, it's possible that the client request is saved into the thread-local map by one thread, but a different thread tries to get it, so a null value is returned.
For example, it happens if the request to be signed is created inside a Rest controller method which has a Mono as a request body parameter:
#PostMapping
public String execute(#RequestBody Mono<MyBody> body){
Mono<OtherBody> otherBody = body.map(this::transformBodyIntoOtherBody);
...
webClient.post()
.body(otherBody)
.exchange();
...
}
According to Reactor specs, the Reactor Context should be used instead of Thread Local.
I forked #rewolf project and implemented a solution based on Reactor Context: https://github.com/taxone/blog-hmac-auth-webclient
This is not currently easy to do with WebClient. But there are ways to do so by intercepting the body post-serialization. This can be done by registering a custom encoder that intercepts the data after encoding, and the passes it to a custom HttpConnector to inject it as a header.
This blog post explains one way to achieve it: https://andrew-flower.com/blog/Custom-HMAC-Auth-with-Spring-WebClient
Edit: Currently this blog post doesn't take into account concurrent requests. See the accepted answer by Claodio for the modified approach.

How to create a Per Request Context for my application

I am playing around with the ASP.NET vNext. and I was wondering how to create my own context per request.
In older versions I would create a singleton and store it in HttpContext.Current.Items.
The idea is that I want to load some data at the beginning of the request that should be available through the entire request.
You can achieve the same with HttpContext Items. You would write a middleware like this one and you can handle your stuff inside the Invoke method.

ServiceStack and NHibernate Unit Of Work Pattern

Long story as brief as possible...
I have an existing application that I'm trying to get ServiceStack into to create our new API. This app is currently an MVC3 app and uses the UnitOfWork pattern using Attribute Injection on MVC routes to create/finalize a transaction where the attribute is applied.
Trying to accomplish something similar using ServiceStack
This gist
shows the relevant ServiceStack configuration settings. What I am curious about is the global request/response filters -- these will create a new unit of work for each request and close it before sending the response to the client (there is a check in there so if an error occurs writing to the db, we return an appropriate response to the client, and not a false "success" message)
My questions are:
Is this a good idea or not, or is there a better way to do
this with ServiceStack.
In the MVC site we only create a new unit
of work on an action that will add/update/delete data - should we do
something similar here or is it fine to create a transaction only to retrieve data?
As mentioned in ServiceStack's IOC wiki the Funq IOC registers dependencies as a singleton by default. So to register it with RequestScope you need to specify it as done here:
container.RegisterAutoWiredAs<NHibernateUnitOfWork, IUnitOfWork()
.ReusedWithin(ReuseScope.Request);
Although this is not likely what you want as it registers as a singleton, i.e. the same instance returned for every request:
container.Register<ISession>((c) => {
var uow = (INHibernateUnitOfWork) c.Resolve<IUnitOfWork>();
return uow.Session;
});
You probably want to make this:
.ReusedWithin(ReuseScope.Request); //per request
.ReusedWithin(ReuseScope.None); //Executed each time its injected
Using a RequestScope also works for Global Request/Response filters which will get the same instance as used in the Service.
1) Whether you are using ServiceStack, MVC, WCF, Nancy, or any other web framework, the most common method to use is the session-per-request pattern. In web terms, this means creating a new unit of work in the beginning of the request and disposing of the unit of work at the end of the request. Almost all web frameworks have hooks for these events.
Resources:
https://stackoverflow.com/a/13206256/670028
https://stackoverflow.com/search?q=servicestack+session+per+request
2) You should always interact with NHibernate within a transaction.
Please see any of the following for an explanation of why:
http://ayende.com/blog/3775/nh-prof-alerts-use-of-implicit-transactions-is-discouraged
http://www.hibernatingrhinos.com/products/nhprof/learn/alert/DoNotUseImplicitTransactions
Note that when switching to using transactions with reads, be sure to make yourself aware of NULL behavior: http://www.zvolkov.com/clog/2009/07/09/why-nhibernate-updates-db-on-commit-of-read-only-transaction/#comments

WCF using Enterprise Library Validation Application Block - how to get hold of invalid messages?

I've got some WCF services (hosted in IIS 6) which use the Enterprise Library (4.0) Validation Application Block. If a client submits a message which fails validation (i.e. gets thrown back in a ValidationFault exception), I'd quite like to be able to log the message XML somewhere (using code, no IIS logs). All the validation happens before the service implementation code kicks in.
I'm sure it's possible to set up some class to get run before the service implementation (presumably this is how the Validation Application Block works), but I can't remember how, or work out exactly what to search for.
Is it possible to create a class and associated configuration that will give me access to either the whole SOAP request message, or at least the message body?
Take a look at using the Policy Injection Application Block...
I'm currently developing an application in which I intercept (using PIAB) all requests incoming to the server and based on the type of request I apply different validation behavior using the VAB.
Here's an article about integrating PIAB with WCF:
http://msdn.microsoft.com/en-us/magazine/cc136759.aspx
You can create different inteception mechanisms such as attributes applied to exposed operations.
You could log the whole WCF Message:
http://msdn.microsoft.com/en-us/library/ms730064.aspx
Or you could combine it with Enterprise Library Logging Application Block.
I found a blog post which seems to do what I want - you create a class that implements IDispatchMessageInspector. In the AfterReceiveRequest method, you have access to the whole incoming message, so can log away. This occurs after authentication, so you also have access to the user name - handy for logging. You can create supporting classes that let you assign this behaviour to services via attributes and/or configuration.
IDispatchMessageInspector also gives you a BeforeSendReply method, so you could log (or alter) your response message.
Now when customers attempt to literally hand-craft SOAP request messages (not even using some kind of DOM object) to our services, we have easy-to-access proof that they are sending rubbish!