Scenario
I am trying to change my existing HttpClient to IHttpClientFactory. When I verified the existing code, its using using{...} statement which causes issues and it is mentioned here. So I thought of implementing singleton Http client and reached another blog related to this and it is here.
From all these, I understood that the best one is IHttpClientFactory introduced in .NET Core.
Implementation Plan
As this application is in ASP.NET MVC 4 and does not use DI, I have to do something to use without the DI framework. Based on my search, got answers from StackOverflow and planned to implement the same way. Meanwhile, I also got another project, which already removed all the dependencies and is ready to use in earlier projects without doing all things. The repo is HttpClientFactoryLite.
Question
Now I can use HttpClientFactoryLite by initializing this class? The description also mentioned it can be used along with the existing DI framework so that ClientFactory can be registered as a singleton. Please find the wordings from the readme
using HttpClientFactoryLite;
var httpClientFactory = new HttpClientFactory(); //bliss
If you are using dependency injection, make sure that IHttpClientFactory is registered as a singleton.
In my scenario, I don't have any DI framework added. So I am going to initialize the factory wherever I needed. Here I am confused that in 2 things
Is it necessary to make a singleton class for HttpClientFactoryLite?
How is this HttpClientFactory class disposed? Is there a need to dispose of it as part of the controller or same using statement etc?
Based on the answer from this, Microsoft.Extensions.Http provides the HttpClientFactory only, not the new optimized HttpClient. This is only available in .NET Core 2.1. So any difference in implementing IHttpClientFactory?
Please advise
ASP.NET 3.1:
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddSingleton<IHttpClientFactory, HttpClientFactory>();
}
ASP.NET will automatically pass the correct singleton to controllers which demand an IHttpClientFactory in their constructor.
Poormans variation without DI-Container:
public static class Singleton<TInterface>
{
private static TInterface instance;
public static TInterface Instance
{
get => instance;
private set => instance ??= value;
}
public static void Add<TConcrete>() where TConcrete : TInterface, new()
=> Instance = new TConcrete();
public static void Add<TConcrete>(TConcrete instance) where TConcrete : TInterface
=> Instance = instance;
// put dispose logic if necessary
}
Usage:
// Application Entrypoint
Singleton<IHttpClientFactory>.Add<HttpClientFactory>();
// Class/Controller Property
private readonly IHttpClientFactory httpClientFactory
= Singleton<IHttpClientFactory>.Instance;
Related
This question is similar to my previous question about Razor Components, but instead, this question is about Razor Pages, which requires a different interception point.
I am making an ASP.NET Core application using the Pure DI approach explained in the book Dependency Injection Principles, Practices, and Patterns (DIPP&P). Part of my application has a web API controller. To implement Pure DI with my controller, I was easily able to follow section 7.3.1 "Creating a custom controller activator" from DIPP&P to create a controller activator class, similar to the example found in DIPP&P. This was done by implementing IControllerActivator and composing my composition root within the create method.
My application will also feature Razor Pages. I would like to continue using the Pure DI approach but I cannot find any examples on how to do this. My assumption is I need to create a RazorPageActivator class, which implements IRazorPageActivator and add my composition root to the Activate method. However, after reviewing the RazorPageActivator class found in the ASP.NET Core GitHub, it looks very complex and I fear if I intercept it (or override it?) by making my own class that implements IRazorPageActivator things will break and I'll be in a mess.
My question is how does one go about implementing Pure DI with Razor Pages, if possible?
With Razor Pages, the IPageModelActivatorProvider functions as your Composition Root's Composer. Here's an example based on the default Visual Studio (2019) Razor Pages project template.
Let's start with the custom IPageModelActivatorProvider, which acts as your Composer, which is part of your Composition Root:
public class CommercePageModelActivatorProvider
: IPageModelActivatorProvider, IDisposable
{
// Singletons
private readonly ILoggerFactory loggerFactory;
public CommercePageModelActivatorProvider(ILoggerFactory loggerFactory) =>
this.loggerFactory = loggerFactory;
public Func<PageContext, object> CreateActivator(
CompiledPageActionDescriptor desc) =>
c => this.CreatePageModelType(c, desc.ModelTypeInfo.AsType());
public Action<PageContext, object> CreateReleaser(
CompiledPageActionDescriptor desc) =>
(c, pm) => (pm as IDisposable)?.Dispose();
private object CreatePageModelType(PageContext c, Type pageModelType)
{
// Create Scoped components
var context = new CommerceContext().TrackDisposable(c);
// Create Transient components
switch (pageModelType.Name)
{
case nameof(IndexModel):
return new IndexModel(this.Logger<IndexModel>(), context);
case nameof(PrivacyModel):
return new PrivacyModel(this.Logger<PrivacyModel>());
default: throw new NotImplementedException(pageModelType.FullName);
}
}
public void Dispose() { /* Release Singletons here, if needed */ }
private ILogger<T> Logger<T>() => this.loggerFactory.CreateLogger<T>();
}
Notice a few things with this implementation:
The structure of this class is very similar to the one's given in the book's code samples.
It implements IDisposable to allow disposing of its own created singletons. In this case, no singletons are created in its constructor, so nothing needs to be disposed. The ILoggerFactory is "externally owned"; it is created by the framework, and will be disposed (if needed) by the framework.
The class uses a custom TrackDisposable extension method (shown later on) that allows tracking scoped and transient dependencies. The TrackDisposable method will add those instances to the request and allows the framework to dispose them when the request ends.
This is why the CreateReleaser method only disposes the Page itself. The disposing of all other created components is done by the framework when you track them for disposal. You can also choose to track the Page itself; in that case you can leave the CreateReleaser delegate empty.
There is a handy Logger<T>() method that simplifies the creation of ILogger<T> implementations. Those come from the framework and are created by the ILoggerFactory.
Here's the TrackDisposable extension method:
public static class DisposableExtensions
{
public static T TrackDisposable<T>(this T instance, PageContext c)
where T : IDisposable
{
c.HttpContext.Response.RegisterForDispose(instance);
return instance;
}
}
The last missing piece of infrastructure required is the registration of your CommercePageModelActivatorProvider into the framework's DI Container. This is done inside the Startup class:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
// Register your custom component activator here
services.AddSingleton<
IPageModelActivatorProvider, CommercePageModelActivatorProvider>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
}
}
We migrated our web project from ASP .NET Framework 4.7.2 to ASP .NET 5
But now, for some reason, the IMemoryCache refuses to work any longer. We inject an instance into our constructor.
public class MyClass
{
private readonly IMemoryCache _memoryCache
public MyClass(IMemoryCache memoryCache)
{
_memoryCache = memoryCache ?? throw new ArgumentNullException();
}
}
And anytime we try to do an operation on that cache
_memoryCache.TryGetValue(_cacheKey, out object item);
We get an exception
Cannot access a disposed object.
Object name: 'Microsoft.Extensions.Caching.Memory.MemoryCache'.
But we nowhere in our application call the Dispose() method on our cache.
FYI In our startup.cs file, we use services.AddMemoryCache(); to have the DI.
EDIT:
Okay for future readers, I have managed to solve this problem for my scenario by creating my own public class MyMemoryCache : IMemoryCache, injecting it through services.addSingleton<IMemoryCache, MyMemoryCache>() and then setting a breakpoint in the Dispose() method that I had to implement myself to backtrack to the caller.
What we do in our application is mark some classes as a startup service, these are business classes that have to do stuff when the server starts such as filling some caches. This is all done through reflection, but in short in our startup.cs file:
using(var serviceProvider = services.BuildServiceProvider())
{
foreach (var startupServiceType in _startupServiceTypes)
{
var startupService = serviceProvider.GetRequiredService(startupServiceType) as IStartupService;
startupService.Start();
}
}
Okay now one of these services had an asynchronous method in which it scheduled stuff. The main loop however (the loop through all startup services) continued and once the using statement was closed, so did the serviceProvider. This then called Dispose() on all injected classes that inherited from IDisposable (which was only one class in our case, the IMemoryCache). The simplest solution was just nog using the keyword using. But I think this is also not the cleanest solution
I am looking for simple approaches to the use of the Options pattern for mixes of environment-agnostic, environment-specific and secret configuration in .NET Core. I have seen unnecessarily complex approaches to this, and developed one approach which feels much simpler than what I have seen, but still begs to be simplified further. I will provide that in the first answer to this question.
So, put as a clear question:
What is the simplest approach to Binding Options objects to Configuration sections in .NET Core that is a consistent approach across all types of .NET Core projects, e.g. Function apps, Worker services, ASP.NET Core, etc?
Bonus questions:
How can this approach be used without requiring the use of a Dependency Injection container?
creating an instance of IConfiguration with a Dependency Injection container feels very messy to me in that IConfiguration then needs to be a parameter of every constructor within a chain of dependencies, or it requires that all class/interface implementations need to be registered within the DI container.
How can this approach be used with a Dependency Injection container?
most people I've met do use DI containers (either Autofac or the .NET Core DI container) so it's definitely worth discussing how the approach might also be useful in a DI container scenario.
===========
It's worth noting that I completely adhere to the Dependency Inversion principle via Dependency Injection, but do so via chained constructors (typically two) and only minimally use DI containers in .NET Core - almost always for logging only. There are a number of reasons for this which are probably best stated by Ygor Bugayenko in Elegant Objects and not the topic of this post.
===========
One more thing:
I am not going to accept my own answer that I'm providing below. In fact, I'm not going to accept an answer for awhile so that there is plenty of time for alternate approaches to be provided in the answers.
Looking forward to your ideas! Cheers
One approach to this is to create Options objects that lazy-initialize, and use an implementation of IConfiguration that has been stored in a singleton at startup that is available to the entire application in order to eliminate the need for DI container gymnastics. I believe that the following approach does not diverge from Microsoft's intent regarding the use of the Options pattern, but is a different and IMO simpler approach to doing so.
In this example implementation I'm going to use naive Singleton patterns for simplicity - if you're concerned at all with multiple threads creating multiple instances you might go with the use of the Lazy class or a traditional double-locking singleton pattern.
I'll use a RemoteCache configuration object as an example of an Options compliant model:
public class RemoteCache
{
private const string SectionName = "Redis";
private static RemoteCache _instance;
private static readonly Redis RedisConfig = new();
public static RemoteCache Instance()
{
if (_instance is not null) return _instance;
_instance = new RemoteCache();
return _instance;
}
private RemoteCache() { }
public string CacheConnection => RedisConfigInstance.CacheConnection;
public string CacheKey => RedisConfigInstance.CacheKey;
private Redis RedisConfigInstance
{
get
{
if (string.IsNullOrWhiteSpace(RedisConfig.CacheConnection) is false) return RedisConfig;
AppConfiguration.Instance.GetSection(SectionName).Bind(RedisConfig);
return RedisConfig;
}
}
private class Redis
{
public string CacheConnection { get; set; } = string.Empty;
public string CacheKey { get; set; } = string.Empty;
}
}
Q. What is AppConfiguration and where does this get initialized?
A. A static class that gets initialized in your Startup class.
My Startup class for a function app typically looks like this. You might notice that I am using "appsettings.json" which is typically not done in function apps, but I wanted the environment-agnostic portion of my configuration to follow the same pattern used in non-function-apps, rather than shoving dang-near everything into Environment Variables which seems pretty typical of function apps and leads to a glut of environment variables being pushed in during the deployment process. I do use environment variables for secrets in non-local deployments, and use KeyVault references to acquire those secrets at runtime. When running locally, secrets are acquired using the UserSecrets.
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
ExecutionContextOptions executionContextOptions = builder.Services.BuildServiceProvider().GetService<IOptions<ExecutionContextOptions>>().Value;
IConfigurationBuilder configurationBuilder = new ConfigurationBuilder()
.SetBasePath(executionContextOptions.AppDirectory)
.AddEnvironmentVariables()
.AddJsonFile("appsettings.json", false)
.AddJsonFile("local.settings.json", true)
.AddUserSecrets(Assembly.GetExecutingAssembly(), true);
AppConfiguration.Instance = configurationBuilder.Build();
builder.Services.AddLogging(logging =>
{
logging.AddApplicationInsights(new ApplicationInsightsConfiguration().AppInsightsInstrumentationKey());
}
}
}
This is all the AppConfiguration class is:
public static class AppConfiguration
{
public static IConfiguration Instance;
}
So, once you have your startup code and AppConfiguration class in place you can happily create Options model objects that map to your configuration sections to your heart's content. These models are implemented as singletons so you can then access them from whatever code needs configuration no matter how deeply nested in your application.
Usage example:
(I prefer accessing configuration models through an interface, which allows my code to be TDD with true unit tests that use fakes of config implementations [of course, use mocks if you prefer])
public interface IRemoteCacheConfiguration
{
string CacheConnection();
string RedisCacheKey();
}
public class RemoteCacheConfiguration : IRemoteCacheConfiguration
{
public string CacheConnection() => RemoteCache.Instance().CacheConnection;
public string RedisCacheKey() => RemoteCache.Instance().CacheKey;
}
public class MyThingThatAccessesTheCache
{
private readonly IRemoteCacheConfiguration _remoteCacheConfiguration;
public MyThingThatAccessesTheCache() : this(new RemoteCacheConfiguration()) { }
public MyThingThatAccessesTheCache(IRemoteCacheConfiguration remoteCacheConfiguration) => _remoteCacheConfiguration = remoteCacheConfiguration;
public void DoStuff()
{
string cacheConnection = _remoteCacheConfiguration.CacheConnection();
}
}
My old code looks like this:
public static class DbHelper {
// One conection per request
public static Database CurrentDb() {
if (HttpContext.Current.Items["CurrentDb"] == null) {
var retval = new DatabaseWithMVCMiniProfiler("MainConnectionString");
HttpContext.Current.Items["CurrentDb"] = retval;
return retval;
}
return (Database)HttpContext.Current.Items["CurrentDb"];
}
}
Since we don't have HttpContext anymore easily accesible in core, how can I achieve the same thing?
I need to access CurrentDb() easily from everywhere
Would like to use something like MemoryCache, but with Request lifetime. DI it's not an option for this project
There are at least 3 options to store an object per-request in ASP.NET Core:
1. Dependency Injection
You could totally re-design that old code: use the built-in DI and register a Database instance as scoped (per web-request) with the following factory method:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<Database>((provider) =>
{
return new DatabaseWithMVCMiniProfiler("MainConnectionString");
});
}
Introduction to Dependency Injection in ASP.NET Core
.NET Core Dependency Injection Lifetimes Explained
2. HttpContext.Items
This collection is available from the start of an HttpRequest and is discarded at the end of each request.
Working with HttpContext.Items
3. AsyncLocal<T>
Store a value per a current async context (a kind of [ThreadStatic] with async support). This is how HttpContext is actually stored: HttpContextAccessor.
What's the effect of AsyncLocal<T> in non async/await code?
ThreadStatic in asynchronous ASP.NET Web API
Will not the database or connection string would be same across the
requests?
If so then you could do it by a static variable and middleware.
The middleware would check and set the info on each request start and static variable would store the value then your method could read it from the static variable.
Other simpler approach would be to inject/pass the IHttpContextAccessor as parameter. With this you could do with minimal changes but you have the pass the IHttpContextAccessor service from each calling method.
I am currently trying to get my head around structuremap now that the ObjectFactory static function has been marked as obsolete.
In the long run I have to use this in a MVC and WebApi application. When previously used, a line to a static method was placed in the the global.asax to initialise everything using the ObjectFactory.
ObjectFactory.Initialize{
container.For .....
}
Trying to convert this to the new IContainer approach I have come up with the following however am wondering if I have actually inadvertently implemented this often mentioned Anti-Pattern in my approach.
Static method to return container:
public class StructureMapConfig
{
public static IContainer GetContainer()
{
return new Container(container =>
{
container.For<IUserService>().Use<UserService>();
container.For<IStringService>().Use<StringService>();
container.For<IUserRepository>().Use<UserRepository>();
});
}
}
Userservice's contstructor looks like this:
public class UserService : IUserService
{
private readonly IUserRepository _userRepository;
private readonly IStringService _stringService;
public UserService(IUserRepository userRepository, IStringService stringService)
{
_userRepository = userRepository;
_stringService = stringService;
}
Finally the initialise (this instance in a console app) looks somthing like this:
private static IUserService _userService;
private static IContainer _container;
static void Main(string[] args)
{
_container = StructureMapConfig.GetContainer();
_userService = _container.GetInstance<IUserService>();
}
So to my questions.
Am I doing anything seriously wrong here
In the UserService, should I be passing the IContainer in and using the object factory to get the instance or should I leave as is.
Is returning the IContainer from the static method the best approach
If this was a MVC app, is it best practice to build this once in the Global.asax or should the controller constructor call the static method every time.
Thanks for any advice.
To go through your questions in order:
Am I doing anything seriously wrong here
No, I don't see anything seriously wrong here. There are a few improvements you could make that I'll talk about shortly.
In the UserService, should I be passing the IContainer in and using
the object factory to get the instance or should I leave as is.
You're correct in injecting UserService over an instance of IContainer. If your controller only requires the UserService then why inject the entire container. Really you only want to inject the bare minimum of what you need to reduce unnecessary coupling and dependencies.
Is returning the IContainer from the static method the best approach
Within the removal of the ObjectFactory then yes, returning an instance of the container via a static method is a common approach for those classes whose creation is not managed via MVC's Dependency Resolution.
If this was a MVC app, is it best practice to build this once in the
Global.asax or should the controller constructor call the static
method every time.
Creating the container in Global.asax.cs is your best approach as it's done once on Application_Start, however see below for my recommendation of using a nested container per http request.
Improvements:-
Take advantage of StructureMap's registries:
Instead of referencing the dependencies directly like this:
public static IContainer GetContainer()
{
return new Container(container =>
{
container.For<IUserService>().Use<UserService>();
container.For<IStringService>().Use<StringService>();
container.For<IUserRepository>().Use<UserRepository>();
});
}
Opt to use StructureMap's registries instead. This way you can group your dependencies (such as MVC specific dependencies or WebAPI specific dependencies, like so:
public class WebsiteRegistry : Registry
{
public WebsiteRegistry()
{
this.For<IUserService>().Use<UserService>();
this.For<IStringService>().Use<StringService>();
this.For<IUserRepository>().Use<UserRepository>();
}
}
Then load your registries like this:
container.Configure(c => {
c.IncludeRegistry<WebsiteRegistry>();
c.IncludeRegistry<TaskRegistry>();
});
HTTP Context bound containers:
Another recommended pattern when using StructureMap with ASP.NET MVC or WebApi (or any HTTP based application) is to use nested containers that are bound to each HTTP request. This basically involves creating a new nested container on each HTTP request and then disposing it at the end of the request. This ensures that dependencies such as session objects, database connections, or UoW contexts are disposed of as soon as the HTTP request is over.
I would recommend taking a look over this article which goes into more detail on the matter and talks about how this can be set up.
This is exactly the same technique that's used in the StructureMap.MVC5 package that's often recommended by StructureMap's creator, Jeremy Miller.
Auto registering dependencies
Instead of registering every dependency with StructureMap manually you can take advantage of StructureMap's auto-registration. You can also specify your own scanning conventions.