I have a problem with the Autofac ExtensibleActionInvoker interacting with the MVC ModelBinder when using interfaces for parameters. The background is as follows:
I am building a MVC application and I am using Autofac MVC3's ExtensibleActionInvoker to inject my services as parameters to my actions, e.g.
public ActionResult Test( IMyService service)
{
//A new instance of service is created by Autofac ExtensibleActionInvoker
return View();
}
This works really well and makes for a really clean design (see Alex Meyer-Gleaves post for more information on this approach). I want to use this method as I am producing a code generator to create actions, views, services and DTOs and a per-action service approach makes this easier.
However I also want to use interfaces for the parameters in action classed which receive input from an HttpPost action. This is because I use DI to create classes outside each layer. If I change the DefaultModelBinder to use DI to create the class (see page 595 of Steve Sanderson's book on MVC3 on how to do this) this this works fine, e.g.
[HttpPost]
public ActionResult Test(ITestClass dataComingFromView)
{
//model binder creates the class via DI and then binds it to the data from the post
return View();
}
However in the above simple example above I get a conflict with the ExtensibleActionInvoker enabled, i.e.
Without ExtensibleActionInvoker enabled the method above works fine, i.e. the extended
DefaultModelBinder uses DI to create the TestClass class and modelbinder binds
input from the view to the fields in the class.
With ExtensibleActionInvoker enabled it does not work, i.e. I get an empty TestClass class with no binding. I assume the ExtensibleActionInvoker takes precedence over the model binder and just creates an empty TestClass class.
(Just for completeness I should say that if I just use MVC "out of the box", i.e. no new DefaultModelBinder and no ExtensibleActionInvoker enabled, then it says you cannot use an interface as an Action method parameter.)
My question for anyone with better Autofac knowledge than me is: can I change the Autofac ExtensibleActionInvoker to select what it binds to? All my injected service classed start with IService so I could filter on that. I know you can do that in Autofac elsewhere but couldn't see anything to do that with ExtensibleActionInvoker, but maybe I missed it.
Any help would be appreciated.
Jon Smith - Selective Analytics
You are correct that the problem is caused by the ExtensibleActionInvoker class. If you look at the source for it, there is a method called GetParameterValue(). See below:
protected override object GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
{
if (_injectActionMethodParameters)
return _context.ResolveOptional(parameterDescriptor.ParameterType) ?? base.GetParameterValue(controllerContext, parameterDescriptor);
return base.GetParameterValue(controllerContext, parameterDescriptor);
}
This method overrides the method that eventually uses the MVC framework's model binder infrastructure. What this means, is that the ActionInvoker tries to resolve the parameter using AutoFac first, and if it fails, falls back to the default functionality. Based on the results you are getting, it seems that your AutoFac configuration must be setup to provide a default resolution of ITestClass.
In order to register a custom ModelBinder with AutoFac you have a couple options. You can decorate the view model with a ModelBinderTypeAttribute or you can do it in your configuration with the custom extension methods found in RegistrationExtensions.
One article I found looks like it provides an easy solution to a similar issue (see the end), but I have not tested this personally.
Having now worked on this problem I found a simple answer. My problem was due to me not really understanding how the MVC Model Binding worked.
If you look at my orginal problem I had created a DefaultModelBinder to allow me to use interfaces as my model parameters (see original question at the top). This was added after me including the Autofac's ExtensibleActionInvoker to bind my IService types. The problem was that the two DI approaches clashed.
The answer was that the DefaultModelBinder was sufficient to bind both my data classes and the Service definitions, so I do not need Autofac's ExtensibleActionInvoker. For completeness I have included the DefaultModelBinder code in case it is useful to anyone else.
public class DiModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
return modelType.IsInterface
? DependencyResolver.Current.GetService(modelType)
: base.CreateModel(controllerContext, bindingContext, modelType);
}
}
Note that I only call the DependencyResolver if the modeltype is an interface as I don't pass abstract classes between layers. Any alternative is to always call the DependencyResolver and then call the base.CreateModel if the DI does not resolve the type. I didn't do this because calling the DependencyResolver is slightly expensive so I only call it when I know I need it.
Related
If I use Spring, which of these two methods is more correct.
Can I use the new() operator even if I use dipendency injection?.Can I mix both?
I would like to have some clarification on these concepts.
Thanks
First method:
#RequestMapping(method=RequestMethod.GET)
public String create(Model model){
model.addAttribute(new User());
return "index";
}
Second Method:
#Autowired
User user;
#RequestMapping(method=RequestMethod.GET)
public String create(Model model){
model.addAttribute(user);
return "index";
}
By using dependency injection does not mean that the use of new operator is automatically prohibited throughout your code. It's just different approaches applied to different requirements.
A web application in spring is composed of a number of collaborating beans that are instantiated by the framework and (unless overriding the default scope) are singletons. This means that they must not preserve any state since they are shared across all requests (threads). In other words if you autowire the User object (or any other model attribute), it is created on application context initialization and the same instance is given to any user request. This also means that if a request modifies the object, other requests will see the modification as well. Needless to say this is erroneous behavior in multithreaded applications because your User object (or other model attribute) belongs to the request, so it must have the very narrow scope of a method invocation, or session at most.
You can also have spring create beans with different scopes for you, but for a simple scenario of a model attribute initialization, the new operator is sufficient. See the following documentation if interested in bean scopes : Bean scopes
So in your use case, the second method is totally wrong.
But you can also delegate the creation of your model attributes to spring if they are used as command objects (i.e. if you want to bind request parameters to them). Just add it in the method signature (with or without the modelattribute annotation).
So you may also write the above code as
#RequestMapping(method=RequestMethod.GET)
public String create(#ModelAttribute User user){
return "index";
}
see also : Supported method argument types
If you want your beans to be "managed" by Spring (for e.g. to use with Dependency Injection or PropertySources or any other Spring-related functionality), then you do NOT create new objects on your own. You declare them (via XML or JavaConfig) and let Spring create and manage them.
If the beans don't need to be "managed" by Spring, you can create a new instance using new operator.
In your case, is this particular object - User - used anywhere else in code? Is it being injected into any other Spring bean? Or is any other Spring bean being injected in User? How about any other Spring-based functionality?
If the answer to all these questions is "No", then you can use the first method (create a new object and return it). As soon as the create() method execution is complete, the User object created there would go out of scope and will be marked for GC. The User object created in this method will eventually be GC-ed.
Things can be injected in two ways in a Spring MVC applications. And yes, you can you can mix injection and creation if doing right.
Components like the controller in your example are singletons managed by the application context. If you inject anything to them it is global, not per request or session! So a user is not the right thing to inject, a user directory can be. Be aware of this as you are writing a multithreaded application!
Request related things can be injected to the method like the used locale, the request, the user principal may be injected as parameters, see a full list at Spring MVC Documentation.
But if you create a model attribute you may use new() to create it from scratch. I will not be filled by spring but to be used by your view to display data created by the controller. When created in the request mapped method that is ok.
I've built some code that can rebuild expression trees so I can avoid triggering the no supported translation to SQL exception and it works fine as long as I call my function to replace the iqueryable. The problem is that I'd like it to automatically be applied to all queries in my project without having to worry about calling this function on each one separately. Is there any way that I can intercept everything?
I've tried using Reflection.Emit to create a wrapping provider and using reflection to replace it on the data context and it turns out that even with Reflection.Emit I can't implement the internal IProvider interface.
I've also tried replacing the provider with a RealProxy based class and that works for non-compiled queries, but the CompiledQuery.Execute method is throwing an exception because it won't cast to the SqlProvider class. I tried replacing the response to the Compile method on the provider with another proxy so I could intercept the Execute call, but that failed a check on the return type being correct.
I'm open to any other ideas or ways of using what I've already tried?
It's hard to tell whether this is an applicable solution without seeing your code, but if you have a DI-friendly app architecture you can implement an interceptor and have your favorite IoC container emit the appropriate type for you, at run-time.
Esoteric? A little. Consider an interface like this:
public interface ISomeService
{
IEnumerable<SomeEntity> GetSomeEntities();
// ...
}
This interface might be implemented like this:
public class SomeService : ISomeService
{
private readonly DbContext _context // this is a dependency!
private readonly IQueryTweaker _tweaker; // this is a dependency!
public SomeService(DbContext context, IQueryTweaker tweaker) // this is constructor injection!
{
_context = context;
_tweaker = tweaker;
}
public IEnumerable<SomeEntity> GetSomeEntities()
{
return _tweaker.TweakTheQuery(_context.SomeEntities).ToList();
}
}
Every time you implement a method of the ISomeService interface, there's always a call to _tweaker.TweakTheQuery() that wraps the IQueryable, and that not only gets boring, it also feels like something is missing a feature - the same feeling you'd get by wrapping every one of these calls inside a try/catch block, or if you're familiar with MVVM in WPF, by raising this annoying PropertyChanged event for every single property setter in your ViewModel.
With DI Interception, you factor this requirement out of your "normal" code and into an "interceptor": you basically tell the IoC container that instead of binding ISomeService directly to the SomeService implementation, you're going to be decorating it with an interceptor, and emit another type, perhaps SomeInterceptedService (the name is irrelevant, the actual type only exists at run-time) which "injects" the desired behavior into the desired methods. Simple? Not exactly.
If you haven't designed your code with DI in mind (are your dependencies "injected" into your classes' constructor?), it could mean a major refactoring.
The first step breaks your code: remove the IQueryTweaker dependency and all the TweakTheQuery calls from all ISomeService implementations, to make them look like this - notice the virtualness of the method to be intercepted:
public class SomeService : ISomeService
{
private readonly DbContext _context
public SomeService(DbContext context)
{
_context = context;
}
public virtual IEnumerable<SomeEntity> GetSomeEntities()
{
return _context.SomeEntities.ToList();
}
}
The next step is to configure the IoC container so that it knows to inject the SomeService implementation whenever a type's constructor requires an ISomeService:
_kernel.Bind<ISomeService>().To<SomeService>();
At that point you're ready to configure the interception - if using Ninject this could help.
But before jumping into that rabbit's hole you should read this article which shows how decorator and interceptor are related.
The key point is, you're not intercepting anything that's internal to LINQ to SQL or the .NET framework itself - you're intercepting your own method calls, wrapping them with your own code, and with a little bit of help from any decent IoC container, you'll be intercepting the calls to methods that call upon Linq to SQL, rather than the direct calls to Linq to SQL itself. Essentially the IQueryTweaker dependency becomes a dependency of your interceptor class, and you'll only code its usage once.
An interesting thing about DI interception, is that interceptors can be combined, so you can have a ExecutionTimerServiceInterceptor on top of a AuditServiceInterceptor, on top of a CircuitBreakerServiceInterceptor... and the best part is that you can configure your IoC container so that you can completely forget it exists and, as you add more service classes to the application, all you need to do is follow a naming convention you've defined and voilĂ , you've just written a service that not only accomplishes all the strictly data-related tasks you've just coded, but also a service that will disable itself for 3 minutes if the database server is down, and will remain disabled until it's back up; that service also logs all inserts, updates and deletes, and stores its execution time in a database for performance analysis. The term automagical seems appropriate.
This technique - interception - can be used to address cross-cutting concerns; another way to address those is through AOP, although some articles (and Mark Seeman's excellent Dependency Injection in .NET) clearly demonstrate how AOP frameworks are a less ideal solution over DI interception.
I'm currently experimenting with OData endpoints in ASP.NET MVC 4 Web API. I like the concept and try to come up with efficient ways to use it in our project.
One question I have is the following: we have a service that is able to return an IQueryable and takes the name of an entity as Input:
public IQueryable GetAll(string entityName);
In standard Web API (as opposed to OData Controllers) I can create a generic controller, that can be called in the form /api/entities/{entityName} and returns the IQueryable.
In case of an OData Controller, I carry out the following entity-specific steps:
Register the entities in the model.
Create a separate Controller for each entity that derives from EntitySetController<>.
I want to use the generic service and avoid as much entity-specific implementations as possible. The first step can easily be automated if the service can return a list of the entities and the corresponding types.
That leaves step 2, because up to now I need to create a specific controller for each entity. I also want to avoid that and create a generic controller that uses the generic service.
Can anyone recommend a solution, maybe by influencing OData routing?
You can create a custom routing convention that selects the same controller no matter what the entity set is. Example,
public class CustomControllerRoutingConvention : IODataRoutingConvention
{
public string SelectAction(ODataPath odataPath, HttpControllerContext controllerContext, ILookup<string, HttpActionDescriptor> actionMap)
{
return null;
}
public string SelectController(ODataPath odataPath, HttpRequestMessage request)
{
return "SomeFixedContrllerNameWithoutTheControllerSuffix";
}
}
You can register that routing convention using the following code,
IList<IODataRoutingConvention> routingConventions = ODataRoutingConventions.CreateDefault();
routingConventions.Insert(0, new CustomControllerRoutingConvention());
config.Routes.MapODataRoute("OData", "odata", builder.GetEdmModel(), new DefaultODataPathHandler(), routingConventions);
I came up against the same problem, and ended up writing a custom IHttpControllerSelector instead of an IODataRoutingConvention. IODataRoutingConvention looks like a good option if your generic controller doesn't require generics :) . But since IODataRoutingConvention.SelectController() only returns a string, I don't see how it will work for instantiating a controller with generic type parameters.
I decided this problem needs a good, general-purpose, open-source solution - so I created one: https://github.com/EntityRepository/ODataServer . It's prerelease now, but I'm currently doing a lot of work on it. I think there's more to it than just choosing the right controller, there are general patterns to define for shared controllers, and by default Web API OData expects strongly typed and strongly named navigation properties which makes it challenging to create a re-usable implementation.
I'm totally stuck.
I've got two Controller: "Customer" and "Address". Both have the fields CustomerRepository and AddressRepository.
There are two ViewModels: CustomerViewModel and AddressViewModel. They also have the fields CustomerRepository and AddressRepository. (And also a parameterless constructor since they are parameters within the edit and create methods)
The Repositories themselves have a DbContext object from my Entities.
Now I'm running into one problem after another. I think I should have only ONE DbContext to share with all of my classes (Repositories AND ViewModels). And I think UnitOfWork is the solution. But I have no clue how to use that.
I currently tried to create a DbContext within the controllers constructor and pass it to every single object requiring it. But even that doesn't work.
If code is necessary, I will post it.
Couple of things to know:
1. Unit of Work
Unit of Work is not necessarily some kind of implementation for IUnitOfWork. It is just a pattern that might be applied in many ways. First, and foremost - you should understand what is it for before actually using it and overcomplicate things around. Moreover, EF Code-First DbContext API's DbContext is a kind of Unit of Work pattern. Your IDbSet<>s are your repositories. Don't try to abstract from your ORM, start with simplest possible thing.
2. DbContext injection
For the beginning, just inject the DbContext to your Controller with constructor injection. Don't forget to setup the IoC container of choice and wire up the MVC's DependencyResolver. Your controller could be look like (example also contains AutoMapper usage example, see next point about ViewModels for that):
public CustomerController : Controller
{
public CustomerController(MyDbContext data, IMappingEngine mapper)
{
Data = data;
Mapper = mapper;
}
public MyDbContext Data { get; set; }
public IMappingEngine Mapper { get; set; }
// Other controller code
}
3. View Models
This, again, is a pattern that is so easily implementable - just have your CustomerViewModel and use AutoMapper to easily transform your Customer to CustomerViewModel so that you can do it like this:
public ActionResult Details(int id)
{
var customer = Data.Customers.FirstOrDefault(c => c.Id == id);
if (customer == null)
return new HttpNotFoundResult();
return View(Mapper.Map<CustomerViewModel>(customer));
}
You can interrogate the AutoMapper's website on how to wire it up and make it running.
Notice that you don't get the ViewModel from DbContext directly. You obtain an "entity" instead which then transformed to appropriate View Model.
Hope this helps!
Your ViewModels should not have references to the DbContext or repositories. ViewModels should be largely stupid. It is the job of the controller (or a service called by the controller) to populate the ViewModels with the data the View needs.
Unit Of work is a good pattern, and one you should use.. but the patern is not a fix for your problem. Your problem is that you are making your view have too much knowledge of your data model.
I currently do the following:
One injected IUnitOfWork using unity to inject into my controllers.
IUnitOfWork implements IContext.
IContext contains IDbSet Customers and IDbSet
The concrete implementation of IContext implements DbContext.
My controllers reference a service, the service uses the IUnitOfWork.
If you use a repository, then simply use a single IContext injected into your controller (or IUnitOfWork which is fairly easy to add on top)
This way I have one context per lifetime of the request and then it's disposed. If you want more code let me know I'll see what I can post up here.
I'd like to be able to create a base controller in my Spring app that, among other things, determines if a user is a registered user or not. This base controller, following the template design pattern, would contain an abstract protected method that controller subclasses would implement.
The abstract method would have passed to it an instance of User, registered or otherwise. However, I have no idea how I would do this since it seems that by using controllers purely using the #Controller annotation each controller is free to define their request handling method however they like.
Would creating some sort of user service class that is injected into each controller and used to validate a user be one way to get around this? This begs the question (at least for me) how does such a controller get a hold of a HttpServletRequest or the Session object?
Thanks.
Define an abstract BaseController, with no annotations
Define concrete and abstract methods
Call these methods from subclasses (which are annotated with #Controller) whenever needed.
I think the Base Controller is not a good idea if the only code it is to have is for UserAuthentication...instead use Spring security. This is the best option.
Alternatively, you can have methods like this...take a look at the Spring reference..
#Controller("loginController")
public class LoginController {
#RequestMapping(value="/login.do", method=RequestMethod.POST)
public String login(Model model, HttpServletRequest request) {
String userIdFromRequest = (String)request.getParameter("userId");
String password = (String)request.getParameter("password");
boolean verified = ...send userIdFromRequest and password to the user service for
verification...
if (verified){
request.getSession().setAttribute("userId", userIdFromRequest);
}
}
//More Methods
}
Did it help?
-SB
The basic problem is that annotational bootstrapping is not polymorphic. I found this paper useful: http://sanguinecomputing.com/design-pattern-for-hierarchical-controller-organization-with-annotational-configuration-spring-mvc-3/