Reputation:
I would like to pass global custom data from API Level to Application Service, to Repository and DB Context layer, without using parameters in every method.
1) One method is HttpContextAccessor
.
Curious if there is any other global parameter embedded in Net Core, or is this the only known strategy? We are passing auditable data, CreateBy, ModifiedDate, but may extend it other properties. We have 100+ apis, application methods, repositories, and trying to prevent passing around a parameter.
_httpContextAccessor.HttpContext.Items["TestKey"] = "SampleData";
DBContext:
public class AuditableDbContext: DbContext
{
private readonly IHttpContextAccessor _httpContextAccessor;
public AuditableDbContext(DbContextOptions<AuditableDbContext> options, IHttpContextAccessor httpContextAccessor)
: base(options)
{
_httpContextAccessor = httpContextAccessor;
}
Custom Data changes based on application behavior and user interaction.
Upvotes: 0
Views: 645
Reputation: 13400
One problem with using context aware objects across multiple layers is the dependency to that context. It makes it really hard to understand the code in the long run, and, most importantly, it makes it harder to unit test.
Imagine you rely on an HttpContext item coming from your controller in another layer. The unit test of that layer would now have to mimic the controller and set the item on the context to produce a proper state.
Having multiple parameters getting passed around everywhere is bad, too, true. One way of solving it would be a simple Poco object to store the state and pass that around, that would make unit testing simple and also reduce the number of parameters of methods in all layers.
public class RequestState
{
public User CreateBy { get; }
...
}
The controller would initiate the state object and all layers would use it...
Another way would be to rely on the DI framework and use a scoped lifetime object which gets injected into all layers which you then can abuse to store your state information. That's pretty similar to http context but at least its your own thing and you can do whatever you want with it and also add strongly typed properties instead of an Items collection.
In your startup, you'd inject the scope object with Scoped lifetime. You inject the object into your controller and all other classes (works only if those classes are also scoped or transient).
Upvotes: 1