While investigating implementing my own IControllerFactory I looked into the the default implementation DefaultControllerFactory and was surprised to see the RequestContext property being set in the CreateController(...) method, and then being referenced in the GetControllerInstance(...) and GetControllerType(...) methods.
The reason for my surprise is that as the factory is instantiated at Application start-up that same instance is used for all requests, so if multiple requests are received at the same time you have no guarantee which requests RequestContext has been set to the property when you come to use it.
Is there a guarantee in the MVC framework that only one request will be serviced by the registered IControllerFactory at a time?
If I am missing something here please enlighten me, as the implementaiton of my controller will be simpler if I have state between method calls during a requests lifecycle.
Thanks.
EDIT:
The answers given are as I expected but miss the main point of the question. The fact is the DefautlControllerFactory supplied as a part of the MVC framework is storing the RequestContext as if it has state - look at the source.
I believe this to be wrong and am looking for clarification (which I think I have seeing as both answers agree with my thoughts). I have cross posted to thte ASP.NET MVC Forums.
Cross posting to the ASP.NET MVC forums reveals this to be a bug with the DefaultControllerFactory implementation.
See here for information:
http://forums.asp.net/t/1414677.aspx
http://forums.asp.net/t/1404189.aspx
The latter post however reveals that you can have a controller factory be instatiated on each request, in which case you can have state.
From the post...
ControllerBuilder.Current.SetControllerFactory(typeof(DefaultControllerFactory));
This will switch the mode of the
controller builder from instance-based
to type-based, and will create a new
instance of the controller factory on
every request.
Your question: Is there a guarantee in the MVC framework that only one request will be serviced by the registered IControllerFactory at a time?
Answer: No, you have to use locks to store state.
My question: Why do you want to store state in the controller factory?
No the Controller factory CreateController method is executed for each request. In application startup you are only suppose to set your default controller and creating a new controller factory is only three lines of code:
public class CommonServiceLocatorControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(Type controllerType)
{
return (controllerType == null) ? base.GetControllerInstance(controllerType)
: ServiceLocator.Current.GetInstance(controllerType) as IController;
}
}
Related
i have just started working in MVC and I have one doubt.
Instead of Nonaction method , we can create private method in controller or we can also write method in model and call that from controller.
So , what is the real purpose to use public NonAction method in MVC ?
(I restructured the answer to better address the questions in the comments)
I think, the attribute is here only for better flexibility. As a framework designer, one wants to relax coding constraints off the end user as much as possible. Requirement of not having public non-actions may sound good "in general" but may be too restrictive for some projects. Adding [NonAction] solves their problem (introduced by their bad design though) - and obviously you're not forced to use the attribute, so it's a win-win from a framework designer perspective.
Another reason may be legacy - in the earlier MVC versions only methods marked with [Action] where considered as actions. So when they relaxed the requirement (and all public methods became treated as actions) they kept [NonAction] so that developers won't get too confused.
In general, using NonAction is a bad practice - exactly for the reasons you stated. If something shouldn't be an action, it should not be public in the first place.
Problem with public non-action methods on the controller is that they make people tempted to instantiate your controller and call the method, instead of separating out the common logic:
Compare
public class MyController : IController
{
public ActionResult Foo(long orderId)
{
var order = new OrdersController().GetOrder(orderId); //GetOrder is public
...
}
}
with
public class MyController : IController
{
public ActionResult Foo(long orderId)
{
var order = _orderService.GetOrder(orderId);
...
}
}
The first approach leads to increased coupling between controllers and non-straightforward code in the actions. Code becomes difficult to follow and refactor, and cumbersome to mock/test.
Besides increased coupling, any public non-action method is a security hole - if you forget to mark it with [NonAction] (or, better, change away from public) - because it's treated as normal action and can be invoked externally. I know the original question kinda implies you surely would never forget to attach the attribute if needed, but it's also kinda important to understand what can happen if you would ;) Oh well, and as we're on this, it seems to me that "forgetting the attribute" is more theoretically probable, comparing to "forgetting to make the method private".
Sometimes people say having public non-actions is necessary for unit testing, but again, when something is not an action it most likely can be isolated in a separate class and tested separately. Moreover, even if it's not feasible for whatever reason, marking a method public for testing purposes only is a bad habit - using internal and InternalsVisibleTo is the recommended way.
This kind of situation may be caused by requirements some testing framework such as you need to do unit testing on that method then you to expose it although its a bad design but can't change these had to bear it out.
By default, the MVC framework treats all public methods of a controller class as action methods. If your controller class contains a public method and you do not want it to be an action method, you must mark that method with the NonActionAttributeattribute.
Real purpose to use public NonAction
To restrict access to non-action method to notify MVC framework that given controller method is not action.
When you try to run a method with NonAction attribute over URL you get the error 404 as response to request.
Ref: http://msdn.microsoft.com/en-us/library/dd410269%28v=vs.90%29.aspx
For Detail: http://weblogs.asp.net/gunnarpeipman/archive/2011/04/09/asp-net-mvc-using-nonactionattribute-to-restrict-access-to-public-methods-of-controller.aspx
This is beneficial when the Url are not case sensitive. So that for example if you have the request Home/About this goes to HomeController and About action, as well as hOmE/AbOUT is going to the same controller and same action method.
Like below
public class HomeController:Controller
{
....
public ViewResult About()
{
return View();
}
public ViewResult aBOut()
{
return View();
}
}
The framework can’t determine which about function to call, and throws the exception telling that the call is ambiguous.
Of course one way to fix this problem is to change the action name.
If for some reason you don’t want to change the action name, and one of these function is not an action, then you can decorate this non action method with NonAction attribute. Example:
[NonAction]
public ActionResult aBOut()
{
return View();
}
By default, the MVC framework treats all public methods of a controller class as action methods. If your controller class contains a public method and you do not want it to be an action method, you must mark that method with the NonActionAttribute attribute.
We are using controllers as binding drivers with custom ASP pipeline, each driver is responsible for rendering one section (partial view) of result page. Then we are using public methods like:
[NonAction]
publi int GetOrder()
to resolve sections order on page or other to resolve authorization for current user (e.g. if current section is editable or just read-only).
So you should not restrain yourself to think about Controller as only a way to handle requests but also as a tool to build your custom framework for rendering page. That way we keep our Controllers responsible for exactly one task and we are separating domain concerns.
ASP.NET is highly customizable. Assume you are going to change the default behavior of the framework by overriding the MVC HTTP handler. Maybe you want to customize the logging logic depending on the controller, which is used. Some controllers implement your ILoggingController interface with the method IControllerLogger GetLogger(). For this method you need to write a public non-action method.
I have my project which uses the usual Repository pattern with Services and Unit of Work (all with Ninject injecting the dependencies from a NinjectModule), but I'm trying to access a service from an ActionFilterAttribute to inject some information (from DB) in the layout of the pages I show so I don't need to mess with all the actions on each controller.
The problem comes when I save to DB on one screen and move to the next and then come back to the previous (with a standard #Url.Action): The ActionFilterAttribute for the Index action is triggered but the call to the service and corresponding repository (within the attribute) throw an exception because the DbContext has been disposed.
Is there any problem with accessing a service and, consequently, the DbContext from an ActionFilterAttribute while injecting the service via Property Injection? I want to make a note that I use property injection for the service in the attribute because the constructor receives 2 parameters that are arbitrary depending on the signature of the Action methods, so my only option was to inject via property.
Let me know if you need some code and I'll update the question.
I found the solution to my problem in the following question:
Injecting dependencies into ASP.NET MVC 3 action filters. What's wrong with this approach?
Combining Mark Seeman's answer with striplingwarrior's comment was the solution to it.
Basically I splitted my ActionFilterAttribute into an Attribute that merely decorated my Actions and keeps the parameters I need for later, and also into an ActionFilter that checked the Action's custom attributes and if my attribute exists, then it injects the data I wanted from the DB into the ViewBag. Everything is later binded with the BindFilter extension from Ninject so it applies only to the methods it needs.
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.
I'm designing medium-size website using asp.net mvc technology.
All business logic is organized into IServices (like IDomainService, IUserService, IAuthService, ITrainingService). All services are using IRepositories.
I'm using Ninject 1.5 to wire services with controllers and it seems working perfectly.
There is so far one subject I have no idea how to handle. Some services create contexts (per request) - for instance IDomainService creates DomainContext (per request) which is needed for IUserService.
ITrainingService is used only in TrainingController, which is accessible only by authorized users, and ITrainingService requires UserContext (also per request) to know who is having training.
This is my first project using IoC container.
Is there any design pattern or code-schema how to solve it?
I think I can fill context object using ActionFilters but how to manage their lifetime and where to put them to be accessible for IServices? (in an ellegant way)
I've used Ninject specifically in an MVC application. The way you'd accomplish this with Ninject is in the configuration or binding of your dependencies. When you do this, you specify how you want your object lifetimes to be managed. In most cases of a web app, you objects will be per request as you've indicated in your question.
One thing I've noticed in your question is that your DomainContext is being created by an IDomainService object and is used by other objects. If the domain service object is a sort of factory for a DomainContext, then you don't have much of a problem -- this becomes an exercise of how you configure Ninject to provide concrete objects and inject dependencies.
Here's general guidance on how you would structure your application -- bear in mind I don't have full understanding of your interfaces and classes:
public class GlobalApplication : NinjectHttpApplication {
protected override void RegisterRoutes(RouteCollection routes) {
// Your normal route registration goes here ...
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
}
// This function is resposible for creating a Ninject kernel. This is where
// the magic starts to happen.
protected override IKernel CreateKernel() {
var modules = new IModule[] {
new AutoWiringModule(),
new AutoControllerModule(
Assembly.GetExecutingAssembly()),
new ServiceModule()
};
return new StandardKernel(modules);
}
}
Note above that the easiest way to get Ninject to work is to derive your application class from the NinjectHttpApplication class. You will need to change your RegisterRoutes to an override method and will also be required to implement a method called CreateKernel. The CreateKernel method is responsible for returning the Ninject kernel which is itself the IoC container.
In the CreateKernel method, the Ninject-provided AutoControllerModule scans assemblies for MVC controller classes and registers them with the container. What this means is that dependencies on those controllers can now be injected by Ninject as it has become the controller provider for the application. The ServiceModule class is one that you need to create to register all of your services with Ninject. I'm guessing it would look something like this:
internal class ServiceModule : StandardModule {
public override void Load() {
Bind<IDomainService>()
.To<MyDomainService>()
.Using<OnePerRequestBehavior>();
Bind<DomainContext>()
.ToMethod( ctx => ctx.Kernel.Get<IDomainService>().CurrentDomainContext )
.Using<OnePerRequestBehavior>();
Bind<IService>()
.To<MyServiceType>()
.Using<OnePerRequestBehavior>();
}
}
Ninject's got a pretty expressive fluent interface for configuration. Note above that each statement basically associates a concrete class with an interface it implements. The "Using" phrase in the statement indicates to the Ninject kernel that the object will live for the life of the request only. So, for example, this means that anytime an IDomainService object is requested from the Ninject kernel during the same request, the same object will be returned.
As for you context objects, I'm taking a stab that your domain service creates these contexts and acts as a factory of sorts. In that regard, I bound instances DomainContext classes above to be produced by getting the value of the a property called CurrentDomainContext off the IDomainService. That's what the lambda above accomplishes. The nice thing about the "ToMethod" binding in Ninject is that you have access to a Ninject activation context object that allows you to resolve objects using the kernel. That's exactly what we do in order to get the current domain context.
The next steps are to ensure your objects accept dependencies properly. For example, you say that ITrainingService is used only in the TrainingController class. So, in that case I would ensure that TrainingController has a constructor that accepts an ITrainingService parameter. In that constructor, you can save the reference to the ITrainingService in a member variable. As in:
public class TrainingController : Controller {
private readonly ITrainingService trainingService;
public TrainingController(ITrainingService trainingService) {
this.trainingService = trainingService;
}
// ... rest of controller implementation ...
}
Remember that Ninject has already registered all of your controllers with the Ninject kernel, so when this controller is created and it's actions are invoked, you'll have a reference to the ITrainingService by way of the trainingService member variable.
Hope this helps you out. Using IoC containers can become quite confusing at times. Note, I highly recommend you check out the Ninject documentation -- it's a very well written introduction to Ninject as well as DI/IoC concepts. I've also left out discussion of the AutoWiringModule shown above; however, Nate Kohari (Ninject's creator) has a good write-up on his blog about this feature.
Good luck!
Im not exactly sure if I understand your problem completely, hopefully this bit of advice can help.
When using an IoC container you let the container handle object lifetime managment. I have only used Castle Windsor and StructureMap for dependency injection so I cant give you a concrete example for how to do this with Ninject.
Looking through the Ninject documentation I think you want to look at Activation Behaviours to specify object lifetime management.
Hope this helps.
I asked a question earlier today about ActionFilters in ASP.Net MVC. It turned out my problem was really that my ActionFilter is not even running. Among other things I read this article, and I can't find anything he does that I don't.
This is my code:
// The ActionFilter itself
public class TestingIfItWorksAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.Controller.TempData["filter"] = "it worked!";
base.OnActionExecuting(filterContext);
}
}
// The Controller Action with the filter applied
[TestingIfItWorks]
public ActionResult Test()
{
var didit = TempData["filter"];
return View();
}
A breakpoint in the filter method is never hit when I debug, and TempData["filter"] holds a null value when the view is rendered.
Why is this not working?
In case it's helpful to anyone using MVC 4/5:
ActionFilters don't run if you get the namespace of your ActionFilterAttribute or IActionFilter wrong: https://stackoverflow.com/a/13710468/188926
Use System.Web.Http.Filters for Web API, System.Web.Mvc for standard MVC actions.
As in the question, the filter attribute will simply be ignored (no error) if you get it wrong, which makes it difficult to diagnose.
Based on your comments to another answer
When testing via unit tests, the filter is not invoked. If you want to invoke the filter then you'll need mimic the ControllerActionInvoker. It's probably better, to test the filter itself in isolation, then use reflection to ensure that the filter is applied to your action with the correct attributes. I prefer this mechanism over testing the filter and action in combination.
Original
Surely you need an override on your method otherwise you aren't actually replacing the method on the base class. I would have expected the compiler to complain that you needed either a new or override on it. If you don't include the override keyword, it will behave as if you used new. Since the framework invokes it as an ActionFilterAttribute, this means that your method will never get called.
Quoting from MSDN:
If the method in the derived class is
not preceded by new or override
keywords, the compiler will issue a
warning and the method will behave as
if the new keyword were present.
In addition to what tvanofosson said, your action method isn't actually rendering anything to the view. Does your view have a <%=TempData["Filter"].ToString()%> statement or something similar?