How do you initialize application state at startup and access it from controllers in MVC 6? - asp.net-core-mvc

Let's say I have a class called MySiteConfiguration in which I have a bunch of, you guessed it, configuration data. This data will not change over the course of the application's runtime after it has been loaded.
My goal would be to construct an instance of this class at startup and access it from my controller actions. I do not want to construct the class more than once, as this should not be needed.
To do this in WebApi 2 for instance, I would:
Instantiate the class in my application start method.
Store the instance on the HttpConfiguration.Properties
Create a ControllerBase class which inherits from ApiController.
Override the Initialize(HttpControllerContext) method in my ControllerBase class. This override would read the configuration instance from HttpControllerContext.Configuration.Properties and assign it to a property / field in ControllerBase.
Any controller needing access to the configuration instance would inherit ControllerBase and reference the base property. Not so bad...
With that said, this pattern does not work in the new framework from what I can tell. There is no initialize method to override on MVC 6's new Controller class. I'm also not familiar enough with the new Startup.cs patterns and middleware available to know where to start with this problem.
Thanks.

Use dependency injection. Register a singleton service that has your data, and then use constructor injection on your controllers to acquire the service instance.
First, define a service. A service can really be any class or interface.
public class MyConfigService {
// declare some properties/methods/whatever on here
}
In your Startup.cs do something like this:
services.AddSingleton<MyConfigService>();
(Note that there are other overloads of AddSingleton depending on your scenario.)
And then consume it in each controller:
public MyController : Controller {
public MyController(MyConfigService myService) {
// do something with the service (read some data from it, store it in a private field/property, etc.
}
}

How about using the application state to store your configuration data?
protected void Application_Start()
{
Application["MySiteConfiguration"] = new MySiteConfiguration();
}
You can then access your configuration data from inside your controllers.
public ActionResult Index()
{
var config = HttpContext.Application["MySiteConfiguration"] as MySiteConfiguration;
}

Related

How to inject ISession into Repository correctly?

Please correct me on the following scenario. ( Question is at the end)
(I asked a similar question that was un-organized and it was voted to close. So I have summarized the question here into a scope that can be replied with exact answers.)
I am developing a web application with multiple layers using nhibernate as ORM. My layer structure is as follow
Model Layer
Repository Layer
Services Layer
UI Layer
with the above layers, the classes and interfaces are placed as below.
ProductController.cs (UI Layer)
public class ProductController : Controller
{
ProductServices _ProductServices;
NHibernate.ISession _Session;
public ProductController()
{
_Session = SessionManager.GetCurrentSession();
_ProductServices = new ProductServices(
new ProductRepository(), _Session);
}
// Cont..
}
ProductServices.cs (Service Layer)
public class ProductServices : IProductServices
{
protected IProductRepository _ProductRepository;
protected NHibernate.ISession _Session;
public ProductServices(IProductRepository productRepository,
NHibernate.ISession session)
{
_ProductRepository = productRepository;
_Session = session;
_ProductRepository.SetSession(_Session);
}
// cont...
}
ProductRepository.cs (Repository Layer)
public class ProductRepository : IProductRepository
{
NHibernate.ISession _Session;
public void SetSession(NHibernate.ISession session)
{
_Session = session;
}
public IEnumerable<Product> FindAll()
{
return _Session.CreateCriteria<Product>().List<Product>();
}
//cont..
}
From the UI layer, I create the session as request per session and inject into service layer with the help of class constructor. Then set the session of repository with a help of a method.
I am afraid if I pass the _Session directly to repository as constructor, I will not have the control over it under the service layer. Also there is a future extension plan for using a webservice layer.
** Is there a way to ensure in each method of ProductRepository class that _Session is set already, without writing the piece of code if(_Session==null) in each and every method as it is repeating the same code.
** If the above pattern is wrong, Please show me a right way to achieve this goal.
What you are doing amazed me a bit. You applying the constructor injection pattern in the ProductService, which is definitely the way to go. On the other hand you are not injecting the dependencies into the ProductController, but that class is requesting one of those dependencies through a static class (this is the Service Locator anti-pattern) and creates a ProductServices class itself. This makes this class hard to test and makes your application less flexible and maintainable, since you can't easily change, decorate or intercept the use of the ProductServices class, when it's been used in multiple places.
And although you are (correctly) using constructor injection for the dependencies in the ProductServices, you are passing those dependencies on to the product repository, instead of applying the constructor injection pattern on the ProductResopistory as well.
Please show me a right way to achieve this goal.
The right way is to apply the constructor injection pattern everywhere. When you do this, your code will start to look like this:
public class ProductController : Controller
{
private ProductServices _ProductServices;
public ProductController(ProductServices services)
{
_ProductServices = services;
}
// Cont..
}
public class ProductServices : IProductServices
{
private IProductRepository _ProductRepository;
public ProductServices(
IProductRepository productRepository)
{
_ProductRepository = productRepository;
}
// cont...
}
public class ProductRepository : IProductRepository
{
private ISession _Session;
public ProductRepository (ISession session)
{
_Session = session;
}
public IEnumerable<Product> FindAll()
{
return _Session
.CreateCriteria<Product>().List<Product>();
}
//cont..
}
See how each class only takes in dependencies that it uses itself. So the ProductController and ProductServices don't depend on ISession (I made the assumption that only ProductRepoistory needs ISession). See how -from a class's perspective- everything is much simpler now?
Did we actually solve a problem here? It seems like we just moved the problem of wiring all classes together up the dependency graph. Yes we did move the problem. And this is a good thing. Now each class can be tested in isolation, is easier to follow, and the application as a whole is more maintainable.
Somewhere in the application however, a ProductController must be created. This could look like this:
new ProductController(
new ProductServices(
new ProductRepository(
SessionManager.GetCurrentSession())));
In its normal configuration, ASP.NET MVC will create controller classes for you, and it needs a default constructor to do so. If you want to wire up controllers using constructor injection (which you should definitely do), you need to do something 'special' to get this to work.
ASP.NET MVC allows you to override the default ControllerFactory class. This allows you to decide how to create controller instances. However, when your application starts to grow, it will get really awkward very quickly when you are creating your dependency graphs by hand (as my last example shows). In this case, it would be much better to use a Dependency Injection framework. Most of them contain a feature / package that allows you to integrate it with ASP.NET MVC and automatically allows to use constructor injection on your MVC controllers.
Are we done yet? Well... are we ever? There's one thing in your design that triggered a flag in my brain. Your system contains a class named ProductServices. Although a wild guess, the name Services seems like you wrapped all product related business operations inside that class. Depending on the size of your system, the number of people on your team, and the amount of changes you need to make, this might get problematic. For instance, how to you effectively apply cross-cutting concerns (such as logging, validation, profiling, transaction management, fault tolerance improvements) in such way that to system stays maintainable?
So instead of wrapping all operations in a single ProductServices class, try giving each business transaction / use case its own class and apply the same (generic) interface to all those classes. This description might be a bit vague, but it is a great way to improve the maintainability of small and big systems. You can read more about that here.
You can use a dependency injection container such as Autofac to instantiate your session and manage the lifetime of it. Leave the responsibility of instantiating the session to Autofac and simply inject the ISession interface into any classes that require the dependency. Have a look at this post: Managing NHibernate ISession with Autofac
You will also find this wiki page useful about configuring Autofac with MVC3: http://code.google.com/p/autofac/wiki/MvcIntegration3

Symfony 2: Dependency injection (DI) of Controllers

Is there any chance to make Controllers dependent on their services not via using of service container inside them but through pure constructor dependency injection?
I would like to write controllers in this way:
<?php
class ArticleController extends \Symfony\Bundle\FrameworkBundle\Controller\Controller
{
private $articleFacade;
private $articleRepository;
public function __construct(ArticleFacade $articleFacade, ArticleRepository $articleRepository)
{
$this->articleFacade = $articleFacade;
$this->articleRepository = $articleRepository;
}
public function indexAction()
{
...
}
}
Unfortunatelly as I can see Symfony ControllerResolver does new instances of Controllers not via ServiceContainer but via simple return new $controller call.
Absolutely in fact it's recommended and if you look at most 3rd party bundles such as FOSUser you can see that that is exactly what they do.
The trick is to define your controllers as services and then use the service id instead of the class name.
http://symfony.com/doc/current/cookbook/controller/service.html
Keep in mind that you will have to inject all your needed services such as entity managers and you won't usually extend the symfony base class. Of course you could inject the complete container but that tends to be frowned on.

ASP.Net MVC 3 - instantiate data context class in BaseController

When adding a controller in ASP.Net MVC 3 using "Controller with Read/Write actions and views, using EntityFramework" as template, it generates a class as follows:
namespace Project.Controllers
{
public class Default1Controller : Controller
{
private ProjectEntities db = new ProjectEntities();
...
}
}
Now, I would like to know if it would be a good practice to change this so that my Controller would inherit a custom base controller that would instantiate ProjectEntities. It would look as follows:
BaseController:
namespace MatchesHorsConcours.Controllers
{
public class BaseController : Controller
{
protected MatchesEntities db = new MatchesEntities();
...
}
}
Other controllers:
namespace Project.Controllers
{
public class Default1Controller : BaseController
{
...
}
}
This technique is useful when you need logic in your master page (for example, to dynamically render menu options). Read about this here: http://www.asp.net/mvc/tutorials/passing-data-to-view-master-pages-cs
However, in general this is not a good technique. I would recommend using dependency injection (Ninject works well with MVC and is easy to implement)
No absolutely not. It makes totally untestable. Please use repository pattern and constructor injection if possible: Repository Pattern vs DAL

Property Injection without attributes using Ninject in an abstract base controller in MVC3

I have the following code:
public abstract class BaseController : Controller
{
public IUserService UserService { get; set; }
}
All my controllers inherit from this base controller. I started out by configuring it in Ninject using the following code:
kernel.Bind<BaseController>()
.ToSelf()
.WithPropertyValue("UserService", x => x.Kernel.GetService(typeof(IUserService)));
This did not work. I assume it is because of the fact that the BaseController is an abstract class (please confirm my assumption). So I moved on to modify the configuration to:
kernel.Bind<HomeController>()
.ToSelf()
.WithPropertyValue("UserService", x => x.Kernel.GetService(typeof(IUserService)));
This does work. The minor downside is that I now have to configure every controller the same way.
Since I also have DependencyResolver setup in my ASP.NET MVC 3 project I could also remove the above Ninject configuration and modify my base controller to look like:
public IUserService UserService
{
get
{
return DependencyResolver.Current.GetService<IUserService>();
}
}
Is there any benefit to using the fluent configuration as opposed to using the DependencyResolver approach? Is one better than the other? Which approach would be considered a better practice?
It is worth mentioning that I did not want to do constructor injection in my base controller.
A better practice in MVC it is to use constructor injection over property injection. Why did you make your choice like this ?
Using Constructor Injection you states that all dependencies in constructor are necessary for the class to do its job.
Property injection means that the dependencies are optional or that there are the local defaults implementations, so all will work even if you don't provide necessary implementations yourself.
You should really know what you're doing using Property injection or you have no other choice, so the safer approach is to rely on constructor injection.
Now I'll give you my point of view. Other may have other opinions.
DependencyResolver was introduced in MVC 3 for "convenient" service location but for me it's a regular Service locator which for me is also an anti-pattern http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx. I don't use it because I don't like it and there is no benefit in using it.
I prefer to user my controller factory like before and pass the dependencies through constructor.
More the IDependencyResolver has somme issues with some IoC containers (I don't know if it's the case with Ninject). You can read more here : http://mikehadlow.blogspot.com/2011/02/mvc-30-idependencyresolver-interface-is.html
If you need the same dependency in each controller then there seems to be something wrong in your design. Most likely you are handling some kind of cross cutting concern in your base controller. In this case Doing property injection is just treating sympthoms instead of cureing the disease. This should rather be handled by an aspect (e.g. a filter or an interceptor) so that you do not have to pollute your controller with something that does not belong there.
There are many ways to skin the cat they say. You could use conventions-based bindings with .WithPropertyValue() or with .OnActivaction() (as described here).
public class ControllerModule : NinjectModule
{
public override void Load()
{
// Get all controller types derived from the base controller.
IEnumerable<Type> controllerTypes = // ...
foreach (var controllerType in controllerTypes)
{
Bind(controllerType).ToSelf().InRequestScope()
.WithPropertyValue(...);
}
}
}
You could create your own custom implementation of the IInjectionHeuristic interface as described here or your own custom implementation of the IControllerActivator interface.
public class CustomNinjectControllerActivator : IControllerActivator
{
private readonly IKernel kernel;
public CustomNinjectControllerActivator(IKernel kernel)
{
this.kernel = kernel;
}
public IController Create(RequestContext context, Type controllerType)
{
var baseController = kernel.TryGet(controllerType) as BaseController;
if (baseController == null)
{
return null;
}
baseController.UserService = kernel.Get<IUserService>();
return baseController;
}
}
Heck, you could even use the service locator pattern if you are comfortable using it.
public IUserService UserService
{
get { return DependencyResolver.Current.GetService<IUserService>(); }
}
You should choose whichever solution is easiest to implement, test and maintain, and of course provides the desired behavior.

MVC - Interface as Controller Action parameter

I want to pass one of a number of classes that implement an interface from my view back to my controller action. I use an ActionLink in my view passing the instance to my action, but it naturally fails because MVC cannot deal with interfaces via default model binding.
So :
<%=Html.ActionLink(flow.Source.Name, "Get", new {container=flow.Source})%>
is in a loop and each flow.Source conforms to IContainer.
public class Flow
{
public virtual IContainer Source { get; private set; }
}
public interface IContainer
{
//members here
}
public class File : IContainer
{}
public class Worksheet : IContainer
{}
Basically I want to call an action method :
public ActionResult Get(IContainer container)
{
// Do something
}
The reason being that I need to retrieve the state of the current container passed to my action method from the database. I use NHibernate and have entities mapped on a table per entity, so have one for File and one for Worksheet for example, so need to able to decide which data access class to use. Make sense? Probably not!
Can this be done without moving towards a base class Container? Can I stick with an interface being passed to my action method and resolve the subtype instance passed in place of the interface?
Any help with this would be gratefully appreciated.
An interface needs 'some' concrete implementation to reference when you would call your class. I think judging by your post you are aware of this : )
With that said there is 'kinda' of an approach handled here where you just create your own model binder that has to know about (or how) to map to and create a concrete type (either directly or by dependency injection)
ASP.NET MVC - Custom Model Binder on Interface Type

Resources