While Scott Hanselman performed an excellent demonstration of the use of IModelBinder in
“IPrincipal (User) ModelBinder in ASP.NET MVC for easier testing” he felt compelled to make this rather defensive comment:
Yes, I realize I could use an IoC container for this also.
Did he mean that he could have used IOC instead of IModelBinder or is he saying that we should use IModelBinder with IOC? With the understanding that many, many things can be done with a general-purpose programming language (now I’m getting defensive) what is actually done in real-world scenarios? For example, a project like KiGG does not appear to be using IModelBinder at all.
For example, in my project I have a custom binder that does something like this (I use it with ViewModel like shown here):
public interface IEntityResolver
{
object Find(string id);
}
public class PrimaryKeyResolver<T> where T: Entity
{
public PrimaryKeyResolver(IRepository<T> repository) {}
public object Find(string id)
{
return repository.Get(new Guid(id));
}
}
public class NameResolver<T> where T: NamedEntity
{
public NameResolver(IRepository<T> repository) {}
public object Find(string id)
{
return repository.Find(new { Name = id });
}
}
public class MyBinder: IModelBinder
{
public override object BindModel()
{
var id = ... //get id from context
var resolverType = typeof(IResolver<>).MakeGenericInterface(typeof(bindingContext.ModelType));
var resolver = ServiceLocator.Current.GetInstance(resolverType);
return resolver.Find(id);
}
}
Now, what are the benefits and why it's about IoC? This helps me to keep my model binder free of entity resolution concerns, preserving Separation of Concerns. What does id means and how we get entity is delegated to resolver. This helps to reuse same IModelBinder for any entity. The only thing I need to do is to provide model resolver if (as shown above) I want to search by name, not by id.
IoC here (I use Service Locator but anyway) helps to find proper resolver and instantiate it. Notice that resolvers accept IRepository, which IoC container passes automatically.
About your specific questions, of course we should use IoC with IModelBinder, not without - but you can probably also use IoC to instantiate IModelBinder - this will avoid the need to use ServiceLocator; but I don't know how to intercept MVC creating the binder, and frankly I don't care since I'm happy with Locator.
As for KiGG, I usually suggest not to rely on example projects such as NerdDinner or Oxite (can't tell anything about KiGG) as if they're "good design" references - as far as I see they usually demonstrate technical aspects (i.e. features), not good design.
I've just added this to codeplex http://mvcunity.codeplex.com/ which might help.
I've also added a sample application, let me know if you have any questions.
Related
I understand the basics of DI in .NET Core, but I'm having trouble figuring out how to use it with multiple projects. Imagine I'm setting up a database context in the Startup class of ASP.NET Core:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<GalleryDb>();
}
I know how to access that context in an API controller:
public class AlbumController : Microsoft.AspNetCore.Mvc.Controller
{
private GalleryDb _ctx;
public AlbumController(GalleryDb ctx)
{
_ctx = ctx;
}
}
But what does one do when there are many layers and functions between the API controller and the data access class? Eventually the code reaches my repository class, which is the one that actually requires the context. It looks like this:
public class AlbumRepository
{
private GalleryDb _ctx;
public AlbumRepository(GalleryDb ctx)
{
_ctx = ctx;
}
public void Save(AlbumEntity entity)
{
// Use _ctx to persist to DB.
}
}
I understand that I could pass the context from the API entry point all the way down, but that seems like an anti-pattern because it means passing it as a parameter through multiple classes and functions that have no interest in it.
Instead, I'd like to do something like this at the point where I invoke the repository class:
public void Save(AlbumEntity album)
{
var ctx = DependencyResolver.GetInstance<GalleryDb>();
var repo = new AlbumRepository(ctx);
repo.Save(album);
}
I believe some DI frameworks have something like this, but I'm trying to figure out how to do it with native .NET Core 2.0. Is this possible? What is the best practice? I found one thread (ASP.NET Core DependencyResolver) talk about using IServiceProvider but the implication was that this was not a desirable solution.
I'm hoping whatever the solution is, I can extend it to apply to other DI classes like ASP.NET Identity's RoleManager and SignInManager.
The key breakthrough chris-pratt helped me understand is that the only way this works is to use DI through all the layers. For example, down in the data layer I get a DB context through DI:
public class AlbumRepository
{
private GalleryDb _ctx;
public AlbumRepository(GalleryDb ctx)
{
_ctx = ctx;
}
}
In the business layer I use DI to get a reference to the data layer:
public class Album
{
private AlbumRepository _repo;
public Album(AlbumRepository repo)
{
_repo = repo;
}
}
Then, in the web layer, I use DI to get a reference to the business layer class:
[Route("api/[controller]")]
public class AlbumController : Microsoft.AspNetCore.Mvc.Controller
{
private Album _album;
public AlbumController (Album album)
{
_album = album;
}
}
By using DI through every layer, the DI system is able to construct all the necessary classes at the point where they are needed.
This requirement has a profound impact on the architecture of an application, and I now realize that my initial hope to tweak an existing, non-DI app to start using DI for the DB context is a major undertaking.
I understand that I could pass the context from the API entry point all the way down, but that seems like an anti-pattern because it means passing it as a parameter through multiple classes and functions that have no interest in it.
No, that's not an anti-pattern. That's how you should do it. However, the bit about "classes and functions that have no interest in it" makes no sense.
Simply, if you're working with something like a repository that wraps a DbContext (a horrible idea, by the way, but we'll put a pin in that), then you shouldn't ever be dealing directly with that DbContext. Instead, you should be injecting your repository into your controllers and then simply let the context be injected into that:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<GalleryDb>();
services.AddScoped<AlbumRepository>();
}
Since ASP.NET Core knows how to inject GalleryDb, and AlbumRepository takes GalleryDb as a constructor param, you simply register AlbumRepository for injection as well (using a "scoped" or request lifetime).
Now, you can inject AlbumRepository the same way you're currently injecting the context:
public class AlbumController : Microsoft.AspNetCore.Mvc.Controller
{
private AlbumRepository _repo;
public AlbumController(AlbumRepository repo)
{
_repo = repo;
}
}
Where this starts to get tricky is when you have many repositories, especially if you have controllers that need to interact with several repositories. Eventually, your code will become a rat's nest of service config and injection boilerplate. However, at that point, you should really be employing the unit of work pattern as well, encapsulating all your repositories in one class that you can inject instead. But wait, oh yeah, that's what DbContext is already. It's a unit of work encapsulating multiple repositories, or DbSets. This is why you shouldn't being using the repository pattern in conjunction with Entity Framework. It's a pointless abstraction that does nothing but add additional and unnecessary entropy to your code.
If you want to abstract DbContext, then you should use something like the service layer pattern (not to be confused with the RPC bull excrement Microsoft refers to as the "service pattern") or the CQRS (Command Query Responsibility Segregation) pattern. The repository pattern is for one thing: abstracting away raw SQL. If you don't have raw SQL, you should not be implementing that pattern.
I need to implement MVC architecture in my company, So can anyone suggest where to keep frequently used methods to call on all pages. Like:
states ddl, departments ddl also roles list and etc...
Please give me suggestions where to keep them in architecture.
Thanks
There are different solutions depending on the scale of your application. For small projects, you can simply create a set of classes in MVC application itself. Just create a Utils folder and a DropDownLists class and away you go. For simple stuff like this, I find it's acceptable to have static methods that return the data, lists, or enumerations you require.
Another option is to create an abstract MyControllerBase class that descends from Controller and put your cross-cutting concerns in there, perhaps as virtual methods or properties. Then all your actual controllers can descend from MyControllerBase.
For larger applications, or in situations where you might share these classes with other MVC applications, create a shared library such as MySolution.Utils and reference the library from all projects as required.
Yet another possibility for larger solutions is to use Dependency Injection to inject the requirements in at runtime. You might consider using something like Unity or Ninject for this task.
Example, as per your request (also in GitHub Gist)
// declare these in a shared library
public interface ILookupDataProvider
{
IEnumerable<string> States { get; }
}
public class LookupDataProvider: ILookupDataProvider
{
public IEnumerable<string> States
{
get
{
return new string[] { "A", "B", "C" };
}
}
}
// then inject the requirement in to your controller
// in this example, the [Dependency] attribute comes from Unity (other DI containers are available!)
public class MyController : Controller
{
[Dependency]
public ILookupDataProvider LookupDataProvider { get; set; }
public ActionResult Index()
{
var myModel = new MyModel
{
States = LookupDataProvider.States
};
return View(myModel);
}
}
In the code above, you'll need to configure your Dependency Injection technology but this is definitely outside the scope of the answer (check SO for help here). Once configured correctly, the concrete implementation of ILookupDataProvider will be injected in at runtime to provide the data.
One final solution I would suggest, albeit this would be very much overkill for small projects would be to host shared services in a WCF service layer. This allows parts of your application to be separated out in to highly-scalable services, should the need arise in the future.
I'm not sure if its just me, but I get the feeling that constructor injection used in ASP.NET MVC controllers is causing unnecessary resource consumption.
Components that's not being used for a particular web request still needs to be created when controllers are created. It's like buying booth milk and juice when I'm thirsty for milk and then I just throw away the juice.
Compare these examples of constructor injection and service locator for controller to clarify my concern.
Constructor Injection, booth deps are created but only one is used.
public class MyController : Controller
{
private readonly IDep1 _dep1;
private readonly IDep2 _dep2;
public MyController(IDep1 dep1, IDep2 dep2)
{
_dep1 = dep1;
_dep2 = dep2;
}
public ActionResult Index()
{
_dep1.MakeStuff();
return View();
}
public ActionResult PageTwo()
{
_dep2.MakeStuff();
return View();
}
}
Service Locator, each dep are created only when its being used.
public class MyController : Controller
{
public ActionResult Index()
{
var dep1 = ServiceLocator.Resolve<IDep1>();
dep1.MakeStuff();
return View();
}
public ActionResult PageTwo()
{
var dep2 = ServiceLocator.Resolve<IDep2>();
dep2.MakeStuff();
return View();
}
}
PLEASE NOTE that an IoC container (which is beneficial for many reasons) can still be used for the Service Locator pattern. I do not want this to be a discussion around IoC and container frameworks neither other benefits from constructor injection (clear visibilty of dependencies etc). It's the constructor injection pattern and how it wastes resources in ASP.NET MVC controller situations that is my concern.
I guess the main question here is:
Is Service Locator a better solution performance wise for the above scenario (ASP.NET MVC controllers) ?
If the object creation is your bottleneck you are in either a very good situation (everything else works like a charm so the < 1 ms operations count) or in a very bad one (your constructors are doing some heavy lifting - which they are not supposed to).
Mark Seemann already covered the subject here:
http://blog.ploeh.dk/2011/03/04/Composeobjectgraphswithconfidence/
In many cases that's a performance hit you'll have to take because you
need those classes anyway, but sometimes you might be concerned with
taking this performance hit too early. However, I make the claim that
in the vast majority of cases, this concern is irrelevant.
And supplied a possible solution if it still matters to you (deferred branches).
If you don't want to construct something you don't need / use pass in something that can construct what you do need.
Using the service locator + DI in our controller factory we can pass in a dep factory to the controller and allow the controller to decide what to ask the factory for.
Is this not the reason we have the factory pattern?
So to refactor your example in the question you might want to do something like this ...
public class MyController : Controller
{
private readonly IDepFactory _factory;
public MyController(IDepFactory factory)
{
_factory= factory;
}
public ActionResult Index()
{
var dep1 = factory.Get<IDep1>();
dep1.MakeStuff();
return View();
}
public ActionResult PageTwo()
{
var dep2 = factory.Get<IDep2>();
dep2.MakeStuff();
return View();
}
}
This is both efficient and a good use of patterns.
From a testing point of view you can mock the passed in IDepFactory so that it always returns some constant that when queries returns a known result to allow you to confirm that your logic in your controller is behaving right.
From a performance point of view I would think that the difference depends mainly on the depth of your dependency stacks in each case, you may prefer to not use a factory and pass in both deps as you were doing before if the dependency stack is very shallow as the gains are virtually nothing.
I am following Steven Sanderson's Pro MVC2 book and have a question about using Ninject.
In the sports store example, we have in Global.asax.cs
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
and NinjectControllerFactory is defined as:
public class NinjectControllerFactory : DefaultControllerFactory
{
//A Ninject "kernet" is the thing that can supply object instances
private IKernel kernel = new StandardKernel(new SportsStoreServices());
protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
return (IController)kernel.Get(controllerType);
}
private class SportsStoreServices : NinjectModule
{
public string QString = null;
public override void Load()
{
Bind<IProductsRepository>().To<SqlProductsRepository>()
.WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString);
}
}
}
As you see the SqlProductsRepository is taking the connection string from the configuration file. If I need to make a decision here based on the URL query string parameters e.g. if param1=true I want to load from one repository versus the other, how can I do that? I have tried to see how to access query parameters in Load() method but I am not able to find a prepopulated place for that.
Also is Load() the right place to make a decision based on query parameters or should I somehow make this decision in Controller?
One would have multiple bindings that have .WithMetadata (or the special case thereof, are .Named()). Then, when resolving, you need to pass in a metadata filter and/or name parameter into the .Get<>() call to indicate the bindings. A small but of searching around here will yield examples, but by far the best source of ninject examples is the ninject tests, which are really clean and one of the reasons the ninject docs dont get the love they deserve (i.e. a v2 update).
i.e., you put a name or metadata filter in as an extra param into the:
return (IController)kernel.Get(controllerType, **here**);
As for best practice on how to manage this in more complex situations, I personally would go read Brand Wilson's set of posts on how they did it in MVC 3.
I guess it depends on your destination and aims:
making a sample do something while you learn - lash in the above
sort out DI based architecture to make you happy, run and buy Dependency Injection in .NET by Mark Seemann, strongly consider ASP.NET MVC 3 and read the Brad Wilson article series either way
a Module's Load() method only gets called when the application starts and the kernel is intialized. hence, there is no request context to make decisions on.
if it were me, I would inject both repositories into the controller and have the controller make the decisions on which to use. that way you can write unit tests to verify it's making the correct decisions.
Here is the example code:
public interface IService<TEntity> {
IContext Context { get; set; }
//unimportant methods
bool Validate(TEntity entity);
void Add(TEntity enttity);
}
public class UsersController : Controller {
private IService<User> _service;
public MyController(IService<User> service){
_service = service;
_service.Context = ControllerContext;
}
}
I'm using AutofacControllerFactory to create controllers in my ASP.NET MVC app.
Is it possible to eliminate this line of code in every controller's constructor:
_service.Context = ControllerContext;
In other words: is it possible to automatically set this property with ControllerContext?
It should be possible because every IService implementation has a settable IContext property.
Should I extend the AutofacControllerFactory or is there a standard way of doint this?
What you have there is a Circular Dependency.
UsersController depends on IService<User>
IService<User> depends on ControllerContext
ControllerContext depends on UsersController
No DI Container can reach into your classes' innards and control what happens there. They can set up dependencies for you and inject them into your classes from the outside. However, they can't very well deal with circular dependencies, so a better option is to redesign the API.
From here it looks very much like the Context property of IService<TEntity> is a Leaky Abstraction. A Service shouldn't need to know anything about the UI framework in which it is running.
You can often break a circular dependency by changing one of the consumers to a more event-driven architecture.
Here's an article about this sort of problem.
Here's a related answer to a ASP.NET MVC question that looks a lot like yours: Is there a good/proper way of solving the dependency injection loop problem in the ASP.NET MVC ContactsManager tutorial?
See also the answer: Dependency-Injection to resolve circular dependencies