ASP.NET MultiLayer App Migration To ASP.NET Core - c#

I migrate my ASP.NET multi layer project to ASP.NET Core. I was using Ninject for DI in my old project and i could call it as follow in my BLL.
public void IamMethodInBll()
{
...
//i could call ninject like this.
var prodCalcManager = Const.NinjectKernel.Get<IProdCalcService>();
prodSurr.CalculatedPrice = prodCalcManager.GetMyMethod()
..
}
In now i use ASP Net Core's DI system of course. But how can i call the service locator in business layer for ASP.NET core? I need your samples and suggestions.
In Startup.cs
services.AddScoped<IProdCalcService,ProdCalcManager>();
In BLL
public void IamMethodInBll()
{
...
//What's the proper way to call another service in BLL
//How can i get the service provider in BLL
var prodCalcManager = _serviceProvider.GetService<IProdCalcService>();
prodSurr.CalculatedPrice = prodCalcManager.GetMyMethod()
..
}

The correct answer is: Dont use ServiceLocator. Register your services using the services.AddScoped<T> like you are and then add that to the constructor of the class you want to use it in.
Like so:
services.AddScoped<IProdCalcService,ProdCalcManager>();
Then your class looks like this:
public class MyClass()
{
private IProdCalcService calcService;
public MyClass(IProdCalcService calcService)
{
this.calcService = calcService;
}
public void IamMethodInBll()
{
//...
prodSurr.CalculatedPrice = calcService.GetMyMethod();
//...
}
}

It is better to DONT USE Service Locator but in this case you can inject ServiceProvider to your Controller or better solution is wrap and abstract ServiceProvider in a Container that can be injectable simply.
I prefer to use 3rd party DI Containers for use in this situation, specially CastleCore can be good choice.
public interface IContainer
{
T Resolve<T>();
}
public class ServiceProviderContainer : IContainer
{
private IServiceProvider _serviceProvider;
public ServiceProviderContainer(IServiceProvider serviceProvider)
{
this._serivceProvider = serviceProvider;
}
public T Resolve<T>()
{
return _seriveProvider.GetService<T>();
}
}
public class MyController : Controller
{
private IContainer contianer;
public MyController(IContainer container)
{
this._container = container;
}
public IActionResult Get()
{
var service = _container.Resolve<IUserRepository>();
}
}

Related

How to do Caching and Dependency Injection outside of Controller in .NET Core MVC

I've used DI purely for tests within a controller and I'm oddly having a real hard time using it outside of a controller. I had a static caching class called caching engine, but apparently DI and static classes don't mix well, so I decided to make it non-static instead. However, I can't get this to work well and I'm not sure what the best approach is. I have a controller that I need to pass products and send them to the view. However, for speed improvements, I'd like to use memory caching, but I'm really confused on the best design here. I'd like to know the best way to do this.
1) How does instantiating a new class work with DI if you don't pass the dependencies?
2) Should I inject my memorycache and product repository into the controller and then pass them into the cachingengine constructor? That seems like a lot of unnecessary parameter passing, so I didn't like this.
3) Should I just instantiate a MemoryCache class in the caching engine and not worry about DI?
4) Should I just switch the CachingEngine back to a static class?
Thank you for your help and advice. It is much appreciated.
Here's the Startup.cs
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
//Add Dependencies
services.AddTransient<IProductRepository, ProductRepository>();
//Extention method that sets up the shared objects used in MVC apps
services.AddMvc();
services.AddMemoryCache();
....
}
}
Here's the Controller
public class MainController : Controller
{
private CachingEngine engine;
public MainController()
{
//This isn't valid, missing parameters
engine = new CachingEngine();
}
public IActionResult Index()
{
var products = CachingEngine.GetProducts();
....
}
}
And here's the caching class:
public class CachingEngine
{
private readonly IMemoryCache memoryCache;
private IProductRepository prodRepo;
public CachingEngine(IMemoryCache memory, IProductRepository rep)
{
memoryCache = memoryCache;
prodRepo = rep;
}
public List<Product> GetProducts()
{
var cacheKey = "Products";
List<Product> prods;
if (memoryCache.TryGetValue(cacheKey, out prods))
{
return prods;
}
else
{
memoryCache.Set(cacheKey, prodRepo.Products);
return prods;
}
}
}
First off, to clarify, a static class cannot be instantiated so how could you inject instantiations into its constructor using a dependency injection framework. It is not that static classes do not work well with DI, they do not work at all and make no sense in the context of dependency injection.
Your Controller needs a CachingEngine, so you need to inject it, a simple rule of setting up DI in your software: do not use the new operator.
Anytime you use the new operator you are tightly coupling your code to a particular type and you have the exact problem that Dependency Inject is trying to solve.
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
//Add Dependencies
services.AddTransient<IProductRepository, ProductRepository>();
//configure DI for IMemoryCache and CachingEngine
services.AddTransient<IMemoryCache, MyMemoryCacheClass>();
services.AddTransient<MyICachingEngineInterface, CachingEngine>();
//Extention method that sets up the shared objects used in MVC apps
services.AddMvc();
services.AddMemoryCache();
....
}
}
public class MainController : Controller
{
private readonly MyICachingEngineInterface _cachingEngine;
public MainController(MyICachingEngineInterface cachingEngine)
{
_cachingEngine = cachingEngine;
}
public IActionResult Index()
{
var products = _cachingEngine.GetProducts();
....
}
}

Register Service at Runtime via DI?

I am using ASP.NET Core and want to add a service to the IServiceProvider at runtime, so it can be used across the application via DI.
For instance, a simple example would be that the user goes to the settings controller and changes an authentication setting from "On" to "Off". In that instance I would like to replace the service that was registered at runtime.
Psuedo Code in the Settings Controller:
if(settings.Authentication == false)
{
services.Remove(ServiceDescriptor.Transient<IAuthenticationService, AuthenticationService>());
services.Add(ServiceDescriptor.Transient<IAuthenticationService, NoAuthService>());
}
else
{
services.Remove(ServiceDescriptor.Transient<IAuthenticationService, NoAuthService>
services.Add(ServiceDescriptor.Transient<IAuthenticationService, AuthenticationService>());
}
This logic works fine when I am doing it in my Startup.cs because the IServiceCollection has not been built into a IServiceProvider. However, I want to be able to do this after the Startup has already executed. Does anyone know if this is even possible?
Instead of registering/removing service at runtime, I would create a service factory that decides the right service at runtime.
services.AddTransient<AuthenticationService>();
services.AddTransient<NoAuthService>();
services.AddTransient<IAuthenticationServiceFactory, AuthenticationServiceFactory>();
AuthenticationServiceFactory.cs
public class AuthenticationServiceFactory: IAuthenticationServiceFactory
{
private readonly AuthenticationService _authenticationService;
private readonly NoAuthService _noAuthService;
public AuthenticationServiceFactory(AuthenticationService authenticationService, NoAuthService noAuthService)
{
_noAuthService = noAuthService;
_authenticationService = authenticationService;
}
public IAuthenticationService GetAuthenticationService()
{
if(settings.Authentication == false)
{
return _noAuthService;
}
else
{
return _authenticationService;
}
}
}
Usage in a class:
public class SomeClass
{
public SomeClass(IAuthenticationServiceFactory _authenticationServiceFactory)
{
var authenticationService = _authenticationServiceFactory.GetAuthenticationService();
}
}
Something of the sort is possible in Autofac:
private ILifetimeScope BeginChildScope()
{
return _lifetimeScope.BeginLifetimeScope(x =>
{
x.Register<IAuthenticationService>(b => new AuthenticationService());
});
}
using (var childScope = BeginChildScope())
{
// Do sth here
}
For .NET Core, I think this is the only possible solution atm.:
Best strategy for creating a child container (or isolated scope) with Microsoft.Extensions.DependencyInjection
Microsoft states unsupported features of ASP.NET Core DI here:
https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection-guidelines#default-service-container-replacement

Unity Config error in console application

Hi am working on console application which uses Dependency Injection pattern, i have created the interface like
public interface IRecurringTransactionPlanDataService : IService<RecurringTransactionPlan>
{
IQueryable<RecurringTransactionPlan> RecurringTransactionPlanData();
}
and the class implements as
public class RecurringTransactionPlanDataService : Service<RecurringTransactionPlan>, IRecurringTransactionPlanDataService
{
private readonly IRepositoryAsync<RecurringTransactionPlan> _repository;
public RecurringTransactionPlanDataService(IRepositoryAsync<RecurringTransactionPlan> repository)
: base(repository)
{
_repository = repository;
}
public IQueryable<RecurringTransactionPlan> RecurringTransactionPlanData()
{
return _repository.RecurringTransactionPlanData();
}
}
The repository:
public static class RecurringTransactionPlanRepository
{
public static IQueryable<RecurringTransactionPlan> RecurringTransactionPlanData(this IRepository<RecurringTransactionPlan> repository)
{
return repository.Queryable();
}
}
the above code all in separate projects, i am using this in MVC and also in console application, while using in MVC there is no error fetching data from db by UnityConfig.cs, but in console application we need to manually register and resolve the interfaces, i have tried this,
My Console Application:
public class RecurringTransaction
{
public readonly IRecurringTransactionPlanDataService _recurringTransactionPlanDataService;
public RecurringTransaction()
{
var container = new UnityContainer();
container.RegisterType<IRecurringTransactionPlanDataService, RecurringTransactionPlanDataService>();
_recurringTransactionPlanDataService = container.Resolve<IRecurringTransactionPlanDataService>();
}
}
public class Program
{
public static void Main(string[] args)
{
FeePaymentTracker.UnityConfig.RegisterComponents();
RecurringTransaction rt = new RecurringTransaction();
var restult = rt.GetRecurringTransactionRecords();
}
}
am getting the above error. expecting your ideas to resolve the error.
In your RecurringTransaction-method you create a new container and then you register RecurringTransactionPlanDataService in that new container. But you do not register the dependencies that the implementation RecurringTransactionPlanDataService has. That container will only have one registration.
var container = new UnityContainer();
container.RegisterType<IRecurringTransactionPlanDataService, RecurringTransactionPlanDataService>();
_recurringTransactionPlanDataService = container.Resolve<IRecurringTransactionPlanDataService>();
Since RecurringTransactionPlanDataService has a dependency to IRepositoryAsync<RecurringTransactionPlan> you need to register that as well.
Change your code to:
var container = new UnityContainer();
container.RegisterType<IRecurringTransactionPlanDataService, RecurringTransactionPlanDataService>();
container.RegisterType<IRepositoryAsync<RecurringTransactionPlan>, YourRepositoryImplementation>();
_recurringTransactionPlanDataService = container.Resolve<IRecurringTransactionPlanDataService>();
As a sidenote you may want to re-use the same container. In console-applications I usually resolve a "ProgramStarter", which then gets the correct injections. This way you only need to use the service locator anti-pattern in the root. But can use proper DI in the rest of the application.
class Program
{
static void Main(string[] args)
{
var container = new UnityContainer();
container.RegisterType<ProgramStarter, ProgramStarter>();
// Pass the same container to the config.
FeePaymentTracker.UnityConfig.RegisterComponents(container);
var program = container.Resolve<ProgramStarter>();
program.Run();
}
}
public class ProgramStarter
{
IRecurringTransactionPlanDataService _dataService;
public ProgramStarter(IRecurringTransactionPlanDataService dataService)
{
_dataService = dataService;
}
public void Run()
{
// Do stuff.
}
}
in the code that you have posted you have an interface called IPaymentService and its implementation. It seems ok. But then in the screenshot you are trying to resolve a dependency called RecurringTransactionPlanDataService. Make your that you have registered this dependency. Could you add information about how you are registering the dependencies in the container?
The problem in your code is that you are trying to resolve the implementation instead of the interface. You should change the following line:
_recurringTransactionPlanDataService = container.Resolve<RecurringTransactionPlanDataService>();
with that:
_recurringTransactionPlanDataService = container.Resolve<IRecurringTransactionPlanDataService>();
Cheers,

How to implement DIP in an MVC environment?

Dependency Inversion Principle states that higher level modules should not depend on lower level modules. Both should depend on abstractions. I do understand that principle. But as I'm using ASP.NET MVC, I often get my controller methods as:
public ActionResult MyAction(string userValue)
{
User user = MyDatabase.GetUser();
if (!user.CheckSomeCondition(userValue))
{ //Something failed. Try again.
return View();
}
user.Update(userValue);
return RedirectToAction("Success");
}
I believe this violates DIP because the result of my controller depends on the User class. In this scenario, I cannot think of a way of decoupling the Controller from my User class. Is there a way to get rid of this dependency? Or is this just fine to do it this way in this scenario?
create an interface and inject an implementation on that to your mvc controller.
public interface IMyDataAccess
{
User GetUser();
}
Create your implementation now.
public class MyMongoDBDataAccess : IMyDataAccess
{
public User GetUser()
{
//return a user from my fancy db
}
}
Now in your controller
public class HomeController : Controller
{
IMyDataAccess dao;
public HomeController(IMyDataAccess myDataAccess)
{
this.dao=myDataAccess;
}
public ActionResult MyAction(string userValue)
{
User user=this.dao.GetUser();
//return something to the view as needed.
}
}
You may use any dependency injection framework like Unity to inject the desired implementation of your interface to your controller.
If you want bring in more layers like Business Layer, Service layer, follow the same thing.
If your application structure is like below, than you are implementing DIP (Dependency Inversion Principle).
DIP says that a layer in your application should depend on a interface, not by an implementation. Like below, Service is depending on IDatabase not MyDatabase
public interface IDatabase {
Update(User user);
}
public interface MyDatabase : IDatabase
{
public Update(User user) {
// update user
}
}
public interface IService {
Update(string user);
}
public class Service : IService
{
private IDatabase _database;
public Service(IDatabase database)
{
_database = database;
}
public Update(User user) {
_database.Update(user);
}
}
DIP also says that high level modules like MvcController don't need to know/depend on low level modules, MyDatabase.
public class MvcController : Controller
{
private IService _service;
private IUserValidator _userValidator;
public MvcController(IService service, IUserValidator userValidator) // depending on abstraction
{
_service = service;
_userValidator = userValidator;
}
public ActionResult MyAction(string userValue)
{
if (!_userValidator.CheckSomeCondition(userValue))
{ //Something failed. Try again.
return View();
}
User user = _service.GetUser();
user.UserValue = userValue;
_service.Update(user);
return RedirectToAction("Success");
}
}
Note:
I recommend to take a look on 3-tier-architecture doing this you will improve your understanding of SOLID and your application will be more organized.
If in your case MyDatabase is a module Higher then User than, you are not respecting DIP principles, because your Controller make uses of a lower module.
DIP or IoC says High-level modules should not depend on low-level modules. Both should depend on abstractions.
It means that High Level class should not depend on concrete class but it should depend on Interface.
But here you are talking about User class which seems a DTO (Data Transfer Object).
So In that case, You must have to use that DTO in your last layer to either return data or deal with data.
But you should not be using POCO classes provided by entity framework, Instead you should create and use your DTO classes as ViewModels.
Ups, this is how I do it when using ASP.NET Web API, not sure if this works MVC Controller. But there is Unity.MVC (v3 or v4 or v5) lib (Unity.Mvc4) that you can use!
And you can wire it up like this, you should call this code in the Application_Start event!
public static class WebApiBootstrapper
{
public static void Init(IUnityContainer container)
{
GlobalConfiguration.Configure(config =>
{
config.DependencyResolver = new WebApiDependencyResolver(container); // DI container for use in WebApi
config.MapHttpAttributeRoutes();
WebApiRouteConfig.RegisterRoutes(RouteTable.Routes);
});
// Web API mappings
// All components that implement IDisposable should be
// registered with the HierarchicalLifetimeManager to ensure that they are properly disposed at the end of the request.
container.RegisterType<IYourController, YourController>(
new HierarchicalLifetimeManager(), new InjectionConstructor(typeof(IMyDataBase)));
}
}
But before running tthis code you have to register the type mapping
container.RegisterType<IMyDatabse, MyDataBase>();
And you also have to implement the DependencyResolver class:
public class WebApiDependencyResolver : IDependencyResolver
{
protected IUnityContainer container;
public WebApiDependencyResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = container.CreateChildContainer();
return new WebApiDependencyResolver(child);
}
public void Dispose()
{
container.Dispose();
}
}
In your controller:
public class YourController : ApiController, IYourController
{
IDataBase _db;
public PlayGroundController(IDataBase db)
{
_db = db;
}

Unity - How to avoid circular reference?

I'm trying to implement dependency injection in my ASP.NET MVC Project using Unity and would like some advice on how to avoid circular references.
At my work we used to implement the service locator pattern, which returned a singleton for each individual service of the application.
public class ServiceWrapper
{
private UserService _userService;
private ProductService _productService;
public UserService User
{
if(_userService == null)
{
_userService = new UserService();
}
return _userService;
}
public ProductService Product
{
if(_productService == null)
{
_productService = new ProductService();
}
return _productService;
}
}
Then in the controller, you could easily access all the services by instantiating the ServiceWrapper and calling methods, like:
private ServiceWrapper _services = new ServiceWrapper();
public ActionResult Index()
{
List<Product> products = _services.Product.GetProducts();
return View(products);
}
Setting up DI using Unity was a breeze. I created a container in Application_Start() (global.asax), like so:
var container = new UnityContainer();
container.RegisterType<IUserService, UserService>(new ContainerControlledLifetimeManager());
container.RegisterType<IProductService, ProductService>(new ContainerControlledLifetimeManager());
container.RegisterType<IServiceWrapper, ServiceWrapper>(new ContainerControlledLifetimeManager());
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
The ServiceWrapper is registered as a Singleton. And implemented constructor injection as follows:
public class ProductController: Controller
{
private IServiceWrapper _services;
public ProductController(IServiceWrapper services)
{
_services = services;
}
public ActionResult Index()
{
List<Product> products = _services.Products.GetProducts();
return View(products);
}
That worked beautifully. But then I came accross the problem.
We like every service to also have a property containing the ServiceWrapper, so that you can easily access the other services from within another, like so:
public class ProductService
{
private IServiceWrapper _services;
public ProductService(IServiceWrapper services)
{
_services = services;
}
public IServiceWrapper Services { get { return _services; } }
}
But when I implemented constructor injection of the ServiceWrapper in the individual services, it resulted in a stackoverflow exception due to circular referencing.
I read that Unity does not support circular referencing. Is there a (solid) way around this. Or should I implement a different architecture? If so, could you recommend a solution?
The way this is typically done is to declare just the services you need and have them ctor-injected. Don't inject a "ServiceWrapper" which just contains everything. Inject what you need. As the container builds up your type you don't have to worry about providing the services. They will be just there.
The development workflow often goes like this:
Add a new dependency injected field
Delete the existing ctor
Regenerate the ctor using Resharper: alt+ins, generate ctor.

Categories