HttpContext.Items vs Scoped Service - asp.net-core

Which is the better way to carry request data(Is there any difference between two way)?
For example:
Option 1(Scoped Service):
//Scoped Service(this may be interface)
public class SampleScopedService
{
public string Data { get; set; }
}
//Register service
services.AddScoped<SampleScopedService>();
//Set and Get Data
public class SampleUsage
{
private readonly SampleScopedService _sampleScopedService;
public SampleUsage(SampleScopedService sampleScopedService)
{
_sampleScopedService = sampleScopedService;
// _sampleScopedService.Data = "Sample";
// _sampleScopedService.Data
}
}
Option 2(HttpContext.Items)
//Scoped Service
public class SampleScopedService
{
private readonly IHttpContextAccessor _accessor;
public SampleScopedService(IHttpContextAccessor accessor)
{
_accessor = accessor;
}
public string GetData()
{
return (string)_accessor.HttpContext.Items["Data"];
}
}
//Register service
services.AddScoped<SampleScopedService>();
//Set Data
HttpContext.Items[“Data”] = ”Sample”;
//Get Data
public class SampleUsage
{
private readonly SampleScopedService _sampleScopedService;
public SampleUsage(SampleScopedService sampleScopedService)
{
_sampleScopedService = sampleScopedService;
//_sampleScopedService.GetData();
}
}

According to docs:
Avoid storing data and configuration directly in DI. For example, a
user’s shopping cart shouldn’t typically be added to the services
container. Configuration should use the Options Model. Similarly,
avoid “data holder” objects that only exist to allow access to some
other object. It’s better to request the actual item needed via DI, if
possible.
Since Options 1 is example of “data holder”, as far as possible we should avoid it.
Furthermore, Options 1 may cause Captive Dependency if you don't pay attention.
So using Option 2 with singleton lifetime is better way than using Option 1.

Related

.NET 5 Web API: Storing data per request

When getting a request in any action of any controller, I look at the jwt know which user is requesting and lookup the user in the database to get some user-data that I want to use throughout the application. E.g. which departments the user belongs to or the users preferred language.
Now I could create a object which wraps these information and send it down the layers and pass it to every method that likes to use some of this data. But I like the data to be available to every method throughout the application without passing it in every method. Like e.g. dependency injection (Seems to late at that point) or something else I can get access to that data quickly.
Any advice of how to handle it?
Try it with the Items property on the HttpContext. By using it you can store data during a single request. The only downside with this approach is that every service needs to have access to the HttpContext to read the values. Values can be added to the Items Dictionary as shown below
public class IndexModel : PageModel
{
//
public void OnGet()
{
HttpContext.Items.Add("Key", new RequestInfo { Key = "RequestKey" });
}
}
class RequestInfo
{
public string Key { get; set; }
}
You can then access the value by registering the IHttpContextAccessor to the IServiceCollection and then using Constructor injection to use the HttpContext in your service so that you can work with the Items Dictionary.
public class Service
{
private IHttpContextAccessor _htp;
public Service(IHttpContextAccessor http)
{
_htp = http;
}
public void Log()
{
Console.WriteLine(((RequestInfo)_htp.HttpContext.Items["Key"]).Key);
}
}

Strategy pattern to consume REST API

I have to consume two different REST API providers about VoIP. Both API do the same with different endpoints and parameters. I'm modeling classes as strategy pattern and the problem that i have encountered is the parameters of each method strategy because are different.
public interface VoIPRequests
{
string ApiKey { get; set; }
string GetExtensionsList();
string TriggerCall();
string DropCall();
string RedirectCall();
}
How can i change parameters for each of this methods depend on the implementation?.
It's good idea use strategy pattern for this case?
There is another pattern that suits better?
Thank you.
Per comment thread:
TriggerCall(), one api only needs one parameter "To" , and other api has two mandatory parameters "extension" and "destination"
I'll focus on TriggerCall, then, and let you extrapolate from there.
Implementation 1
public class VoIPRequests1 : VoIPRequests
{
private readonly object to; // Give this a more appropriate type
public VoIPRequests1(object to)
{
this.to = to;
}
public string TriggerCall()
{
// Use this.to here and return string;
}
// Other interface members go here...
}
Implementation 2
public class VoIPRequests2 : VoIPRequests
{
private readonly object extension; // Give this a more appropriate type
private readonly object destination; // Give this a more appropriate type
public VoIPRequests2(object extension, object destination)
{
this.extension = extension;
this.destination = destination;
}
public string TriggerCall()
{
// Use this.extension and this.destination here and return string;
}
// Other interface members go here...
}

How can I make an ASP Core Claims Principal available in a non-controller object?

I am working on an ASP Core 2 project using JWT authentication and the Dapper ORM.
Like all ASP projects, I have a lot of controllers, each instantiating its associated data objects. Each data object inherits from an abstract DbObject class that provides database access services. I also have an AuthenticatedUser object that abstracts the JWT to make it's properties easier to use.
What I want is to do is create the AuthenticatedUser object in the constructor of DbObject. Of course, one method is to create it in the controller and pass it to every concrete data object but this is messy as it would have to be passed hundreds of times (and it just feels wrong).
Is there a way to use the ASP Core middleware to get the token after authentication and make it available through dependency injection in the DbObject?
Edit
Hopefully, this clarifies my intentions. I would like the controller to create data objects and use their properties and methods without regard to implementation (i.e. DbObject). But queries executed by DbObject will be filtered by information in the token of the logged in user.
public class ManufacturerController : Controller {
[HttpGet]
public async Task<IActionResult> Get() {
var manufacturers = await new Manufacturer().SelectMany();
return Ok(manufacturers);
}
[HttpGet("{id}")]
public async Task<IActionResult> Get(int id) {
var manufacturer = await new Manufacturer().SelectOne(id);
return Ok(manufacturer);
}...
public class Manufacturer : DbObject<Manufacturer> {
protected override string QrySelectOne => #"
Select *
From org.fn_Manufacturers ({0})
Where Id = {1}";
protected override string QrySelectMany => #"
Select *
From org.fn_Manufacturers ({0})";
public int Id { get; set; }
public string Name { get; set; }
public string Phone { get; set; }...
public abstract class DbObject<T> {
protected readonly AuthenticatedUser authenticatedUser;
public DbObject(IHttpContextAccessor contextAccessor) {
authenticatedUser = new
AuthenticatedUser(contextAccessor.HttpContext.User);
}
protected abstract string QrySelectOne { get; }
protected abstract string QrySelectMany { get; }
public async Task<T> SelectOne (int id) {...}
public async Task<T> SelectOne(params object[] ids) {...}
public async Task<IEnumerable<T>> SelectMany () {...}
public async Task<IEnumerable<T>> SelectMany (params object[] ids) {...}
I suppose one solution may be to create a static data object factory which has the IHttpContextAccessor injected??
ASP.NET Core provides IHttpContextAccessor interface for accessing HttpContext from non-controller objects.
The usage is fair simple. Inject IHttpContextAccessor into DbObject and access HttpContext by calling IHttpContextAccessor.HttpContext:
public abstract class DbObject
{
protected DbObject(IHttpContextAccessor contextAccessor)
{
var context = contextAccessor.HttpContext;
// Create instance of AuthenticatedUser based on context.User or other request data
}
}
EDIT
Your controllers instantiate data objects directly (with new operator), that's why you can't have IHttpContextAccessor injected out of the box. Here are possible solutions. I list them in order of my preference (from best to worst).
If each controller uses only one (or just several) types of data objects, the best options will be to avoid direct instantiation and move toward normal Dependency Injection.
So if ManufacturerController requires only Manufacturer like in your sample then, it's better to inject Manufacturer instance to controller, not to create it inside:
public class Manufacturer1Controller : Controller
{
private readonly Manufacturer manufacturer;
public Manufacturer1Controller(Manufacturer manufacturer)
{
this.manufacturer = manufacturer ?? throw new ArgumentNullException(nameof(manufacturer));
}
[HttpGet]
public async Task<IActionResult> Get()
{
var manufacturers = await manufacturer.SelectMany();
return Ok(manufacturers);
}
// ...
}
IHttpContextAccessor will be injected into Manufacturer and passed to base DbObject:
public class Manufacturer : DbObject<Manufacturer>
{
public Manufacturer(IHttpContextAccessor contextAccessor) : base(contextAccessor)
{
}
}
It's the cleanest solution in the list. You use DI in classic way and utilize all benefits DI provides.
If one controller could use dozens of different data objects, you could inject the factory object that creates instances of data objects. It could be simple implementation based on IServiceProvider:
public interface IDbObjectFactory
{
TDbObject Create<TDbObject>() where TDbObject : DbObject<TDbObject>;
}
public class DbObjectFactory : IDbObjectFactory
{
private readonly IServiceProvider serviceProvider;
public DbObjectFactory(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
}
public TDbObject Create<TDbObject>() where TDbObject : DbObject<TDbObject>
{
return serviceProvider.GetRequiredService<TDbObject>();
}
}
public class Manufacturer2Controller : Controller
{
private readonly IDbObjectFactory dbObjectFactory;
public Manufacturer2Controller(IDbObjectFactory dbObjectFactory)
{
this.dbObjectFactory = dbObjectFactory ?? throw new ArgumentNullException(nameof(dbObjectFactory));
}
[HttpGet]
public async Task<IActionResult> Get()
{
var manufacturer = dbObjectFactory.Create<Manufacturer>();
var manufacturers = await manufacturer.SelectMany();
return Ok(manufacturers);
}
}
The code for Manufacturer and DbObject does not change comparing to the first option.
I don't see any reason not to use option #1 or #2. However just to complete the picture, I'll describe another two options.
Inject IHttpContextAccessor into conroller and pass this instance (or IHttpContextAccessor.HttpContext.User) to Data Object constructor invoked with operator new:
public class Manufacturer3Controller : Controller
{
private readonly IHttpContextAccessor contextAccessor;
public Manufacturer3Controller(IHttpContextAccessor contextAccessor)
{
this.contextAccessor = contextAccessor ?? throw new ArgumentNullException(nameof(contextAccessor));
}
[HttpGet]
public async Task<IActionResult> Get()
{
var manufacturer = await new Manufacturer(contextAccessor).SelectMany();
// or
// var manufacturer = await new Manufacturer(contextAccessor.HttpContext.User).SelectMany();
return Ok(manufacturer);
}
}
It's a bad solution, because you don't use Dependency Injection for Manufacturer here and loose many advantages that DI provides.
And the worst option would be using of static object factory with injected IHttpContextAccessor. With this approach you also loose benefits of DI. In addition you get ugly code somewhere in Startup that initializes static instance of IHttpContextAccessor. When you come to this approach, you'll discover that theere is no quite elegant way to do this.
My advice: use option #1 untill you have good reasons against it. Then use option #2.
Here is Sample Project on GitHub with samples for approaches ##1-3.

Avoiding Service Locator with AutoFac 2

I'm building an application which uses AutoFac 2 for DI. I've been reading that using a static IoCHelper (Service Locator) should be avoided.
IoCHelper.cs
public static class IoCHelper
{
private static AutofacDependencyResolver _resolver;
public static void InitializeWith(AutofacDependencyResolver resolver)
{
_resolver = resolver;
}
public static T Resolve<T>()
{
return _resolver.Resolve<T>();
}
}
From answers to a previous question, I found a way to help reduce the need for using my IoCHelper in my UnitOfWork through the use of Auto-generated Factories. Continuing down this path, I'm curious if I can completely eliminate my IoCHelper.
Here is the scenario:
I have a static Settings class that serves as a wrapper around my configuration implementation. Since the Settings class is a dependency to a majority of my other classes, the wrapper keeps me from having to inject the settings class all over my application.
Settings.cs
public static class Settings
{
public static IAppSettings AppSettings
{
get
{
return IoCHelper.Resolve<IAppSettings>();
}
}
}
public interface IAppSettings
{
string Setting1 { get; }
string Setting2 { get; }
}
public class AppSettings : IAppSettings
{
public string Setting1
{
get
{
return GetSettings().AppSettings["setting1"];
}
}
public string Setting2
{
get
{
return GetSettings().AppSettings["setting2"];
}
}
protected static IConfigurationSettings GetSettings()
{
return IoCHelper.Resolve<IConfigurationSettings>();
}
}
Is there a way to handle this without using a service locator and without having to resort to injecting AppSettings into each and every class? Listed below are the 3 areas in which I keep leaning on ServiceLocator instead of constructor injection:
AppSettings
Logging
Caching
I would rather inject IAppSettings into every class that needs it just to keep them clean from the hidden dependency on Settings. Question is, do you really need to sprinkle that dependency into each and every class?
If you really want to go with a static Settings class I would at least try to make it test-friendly/fakeable. Consider this:
public static class Settings
{
public static Func<IAppSettings> AppSettings { get; set; }
}
And where you build your container:
var builder = new ContainerBuilder();
...
var container = builder.Build();
Settings.AppSettings = () => container.Resolve<IAppSettings>();
This would allow to swap out with fakes during test:
Settings.AppSettings = () => new Mock<IAppSettings>().Object;
Now the AppSettings class (which I assume there is only one of) you could do with regular constructor injection. I assume also that you really want to do a resolve on each call to your settings properties, thus injecting a factory delegate that retrieves an instance when needed. If this is not needed you should of course inject the IConfigurationSettings service directly.
public class AppSettings : IAppSettings
{
private readonly Func<IConfigurationSettings> _configurationSettings;
public AppSettings(Func<IConfigurationSettings> configurationSettings)
{
_configurationSettings = configurationSettings;
}
public string Setting1
{
get
{
return _configurationSettings().AppSettings["setting1"];
}
}
public string Setting2
{
get
{
return _configurationSettings().AppSettings["setting2"];
}
}
}

Where to store data for current WCF call? Is ThreadStatic safe?

While my service executes, many classes will need to access User.Current (that is my own User class). Can I safely store _currentUser in a [ThreadStatic] variable? Does WCF reuse its threads? If that is the case, when will it clean-up the ThreadStatic data? If using ThreadStatic is not safe, where should I put that data? Is there a place inside OperationContext.Current where I can store that kind of data?
Edit 12/14/2009: I can assert that using a ThreadStatic variable is not safe. WCF threads are in a thread pool and the ThreadStatic variable are never reinitialized.
There's a blog post which suggests implementing an IExtension<T>. You may also take a look at this discussion.
Here's a suggested implementation:
public class WcfOperationContext : IExtension<OperationContext>
{
private readonly IDictionary<string, object> items;
private WcfOperationContext()
{
items = new Dictionary<string, object>();
}
public IDictionary<string, object> Items
{
get { return items; }
}
public static WcfOperationContext Current
{
get
{
WcfOperationContext context = OperationContext.Current.Extensions.Find<WcfOperationContext>();
if (context == null)
{
context = new WcfOperationContext();
OperationContext.Current.Extensions.Add(context);
}
return context;
}
}
public void Attach(OperationContext owner) { }
public void Detach(OperationContext owner) { }
}
Which you could use like that:
WcfOperationContext.Current.Items["user"] = _currentUser;
var user = WcfOperationContext.Current.Items["user"] as MyUser;
An alternative solution without adding extra drived class.
OperationContext operationContext = OperationContext.Current;
operationContext.IncomingMessageProperties.Add("SessionKey", "ABCDEFG");
To get the value
var ccc = aaa.IncomingMessageProperties["SessionKey"];
That's it
I found that we miss the data or current context when we make async call with multiple thread switching. To handle such scenario you can try to use CallContext. It's supposed to be used in .NET remoting but it should also work in such scenario.
Set the data in the CallContext:
DataObject data = new DataObject() { RequestId = "1234" };
CallContext.SetData("DataSet", data);
Retrieving shared data from the CallContext:
var data = CallContext.GetData("DataSet") as DataObject;
// Shared data object has to implement ILogicalThreadAffinative
public class DataObject : ILogicalThreadAffinative
{
public string Message { get; set; }
public string Status { get; set; }
}
Why ILogicalThreadAffinative ?
When a remote method call is made to an object in another AppDomain,the current CallContext class generates a LogicalCallContext that travels along with the call to the remote location.
Only objects that expose the ILogicalThreadAffinative interface and are stored in the CallContext are propagated outside the AppDomain.