I put the println() in each method of Action class.
public String execute() throws Exception {
System.out.println("execute");
//...
}
public void prepare() throws Exception {
System.out.println("prepare");
//...
}
public Object getModel() {
System.out.print("getModel");
//...
}
I thought the order would be;
prepare → execute → getModel.
Because I remember I read it in the book, so I used to construct beans class and do some logics in prepare(), and just return SUCCESS in execute().
And I think getModel is for pushing the bean to the valueStack, right?
...anyway the console showed me this. It's very weird;
prepare → getModel → execute.
And this is becoming a huge problem to me. It's very hard to explain the reason in English... but I'll try!
I used to create each action class which is dealing with same beans, and of course there are same codes(variables, and their getters and setters) duplicated in each action class.
Now I'm trying to create one action to avoid that duplication. This action class has several methods(mapped in struts.xml like this;<action name="View_board" method="view">).
And as we saw in the console, this view() is called at the last in the action class like execute(). The prepare() does only construct beans, and the view() does real jobs. But getModel() is called before calling of view(), so there's no chance to put the beans to ValueStack.
I hope you guys understand what I'm trying to explain.
To sum it up, there are each action class like BoardView, BoardDelete, BoardWrite... and they worked well! But I hate that duplicated things so I created BoardManager class. This class has each method(like view()) which was handled by class(like BoardView). But this view() was called after the call of getModel(), so the bean(return of getModel()) has no chance to be pushed to the ValueStack.
Please help me out. Teach me your know-how in the field. I'm developing it all on my own and this is making me feel so hard.
Thank you!!
You have to set the Model object yourself as the modeldriven interceptor can only push it to the stack if its not null. If your getModel() looks like this:
SomeModelClass myModelObject = null;
public Object getModel()
{
return myModelObject;
}
... you'll have to set the modelObject so it can get pushed to the valueStack. You could do it this way I guess:
public void prepare(){
myModelObject = new myModelObject("I'm so new");
}
... or just initialize it in the field:
SomeModelClass myModelObject = new myModelObject("I'm so new");
Don't forget to implement the appropriate Interfaces (ModelDriven and Preparable). Hope this helps a bit.
I found my own solution.. but not a good one..
When setting domain object by setter, I push it to the valuestack manually..
It works good and only 2 lines added to my class.
But I don't feel that good.
Related
I'm wondering if this is possible. I have a typical MVC action method with a signature that looks like this:
public ActionResult View(MyModel model)
{
IAnObject myObject = new AnObject();
//several lines of code follow.....
return View(model);
}
I'd like to get rid of that new keyword and inject an instance of IAnObject into the action method. But I'm not sure if MVC allows for this, injecting a class along side a model in an action method? Has anyone run across this, and are there ways of tackling it? (Our IoC container is Windsor, in case that makes a difference.)
If you are expecting to inject this reference into the action method as a parameter, you can look to the ControllerActionInvoker, which has an InvokeActionMethod method, which I believe is called from InvokeAction. This method has a list of parameters passed into it, and a description of the action (ActionDescriptor class). This action descriptor has a GetParameters method that will give you more detailed information about the parameter, such as type information that you would need for the dependency injector. I've not done this, so I don't know quite how it works out, but it seems possible.
I also don't know how that might affect how MVC selects an action method to post to, so factor that in.
You may want to do your injection in OnActionExecuting which is called before any action on the controller is executed. This will give you context such as the Request but will allow you to set member variables - thus 'simulating' constructor injection. And of course you only have to do it once for the whole controller.
[NonAction]
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
_myService = .........; // get from IoC container
base.OnActionExecuting(filterContext);
}
Well, I agree with the guys on the comments, but if you want to take an instance in the method scope, try to get it from your container of IoC, something like this:
public ActionResult View(MyModel model)
{
// take from the container of IoC
IAnObject myObject = _continerIoC.Resolve<IAnObject >();
//several lines of code follow.....
return View(model);
}
Avoid using the new to create your instance and your concrete type in the container and decouple your controller from dependecies/references.
I really consider using constructor/property Injection. There is a method injection too.
Per a conversation with #Aaronaught on another thread, I've started converting my application to use Dependency Injection and the Repository patterns, but I'm a little stuck. I think I get most of the stuff and flow of the patterns, but I'm stuck on implementing StructureMap into ASP.NET MVC 2. The examples I've read seem to be out of date with the latest version of Structure Map which I'm using (2.6.1).
I'm hoping that someone can fill in the gaps based on the code I paste below:
public static class Bootstrapper {
public static void Configure() {
ObjectFactory.Configure(x => {
x.For<DataContext>().Add(new DataContext());
});
}
}
With this I can get an instance of the DataContext from within my controller(s) with:
protected DataContext dc = ObjectFactory.GetInstance<DataContext>();
I know that's wrong to do, but I'm confused on how to avoid it. Moving on, here's the controller factory:
public class StructureMapControllerFactory : DefaultControllerFactory {
protected override IController GetControllerInstance(
RequestContext rc,
Type ct) {
return (ObjectFactory.GetInstance(ct) as Controller);
}
}
I don't understand exactly what this does, but it's in the examples, so I'm replicating it. Can someone explain it to me?
Now from what I understand, there's supposed to be registries which if I understand correctly, globalize object instances such as the DataContext. Is that correct? If so, how do I go about writing the registry for StructureMap 2.6.1? The example code I've seen seems obsolete because when I write it I don't have the same options available to me (via IntelliSense), so I'm not sure how to write it...
I will really appreciate any help in filling in the gaps that I have.
P.S. My experience with Dependency Injection and Repositories is about 8 hours total.
UPDATE/CONCLUSION
Having read through #Pure's excellent explanation below and watching the tekpub video he referenced in a sub-comment I've opted out for Ninject over StructureMap.
I don't know if Ninject is better than StructureMap, but from my stand point it's definitely much easier to start out with and get going.
OK,
I'm sure Jeremy Miller will correct my post and give you the real truth, but the idea of having that custom Controller factory which uses StructureMap to create the controllers, is because the Controller class is the key class where the majority of the logic kicks off and takes place (Yes, there's action filters and stuff that happens before, but lets keep this simple) - and this needs to have all the dependencies pre-setup before any logic begins.
So the idea is this. If all the logic and magic-unicorn stuff happens in the Controllers methods, then when we first enter the method ... we need to have all our requirements already setup. More importantly, each method in any Controller shouldn't care about what requirement (ie. instances) it has .. just that someone, from somewhere. .. has already made this decision and given me all the important objects that we might require.
This is core of what DI/IoC is all about.
So lets use some really simple code to explain this, cause I'm not good at explaining things.
Lets assume we have the following method in the Controller :-
public ActionMethod Index()
{
// List all Products.
}
Pretty simple. Just lists some products to the browser. So the first thing you need to ask is this -> what are Products? where do they come from? Well, the controller method doesn't ask this question at all. In fact, it DOESN'T CARE where they came from. It only cares that it has something that is a Product.
So when we are in this method, we also shouldn't care about where the product information exists at. We just want to do something with this things called Products'.
Ok .. so lets do something with it ...
public ActionMethod Index()
{
var products = _myProductService.Find().ToList();
// .. rest snipped.
}
Ok .. so far we now are asking some Service to find all the products and then list them. Kewl. Still, we don't care where these products originate from. Or even, what is this Product Service. That's the key -> We leave the DI/IoC to worry about that. All we care about is the fact that we have some ProductService which does some stuff with some products. In this case, it's going to Find all the products and then we ask it to List all the products, found.
So where does DI/IoC come into play?
This is the unicorn-magic part :)
When this controller was instanciated, it asked StructureMap :
"Oi! StructureMap! I need to create a
HomeController. But The HomeController
has at least one constructor.. and the
most complex constructor it has (note:
DI/IoC call this the most greedy
constructor) lists a number of
objects which it requires. So ... I
need to create those objects first,
then create my HomeController .. and
pass those objects in.pass those objects in.
Lets look at the code...
public class HomeController : Controller
{
private IProductService _productService;
private ILoggingService _loggingService;
public HomeController(IProductService productService, ILoggingService loggingService)
{
_productService = productService;
_loggingService = loggingService;
}
public ActionMethod Index()
{
var products = _productService.Find().ToList();
// rest snipped.
}
}
whoa -- there's a few things going on here.
Lets recap -> So StructureMap says:
I need an instance of a IProductService and an ILoggingService .. which I pass to the HomeController constructor
... can u give me those please?"
And StructureMap then says:
Ok .. first up -> an IProductService. Lets see here, U've mapped an IProductService to a
custom class you made, called ReallyFastProductService. Kewl, i'll create one of those bad boys.
Next, u've mapped an ILoggingService to an NLogLoggingService class ... nice!
NLog wroxs, dude. So i'll also create one of those bad boys. Ok, i've now made those two instances.
Finally! I can now make an instance of the HomeController you're after ..
and then i'll pass those two objects i just made, into the HomeController constructor... and viola! here's the Controller instance.
... so now, u have the Controller instance.
.... and when u step into the Index() method, if u use the mouse and hover over the instances, they will be a ReallyFastProductService and an NLogLoggingService.
Awesome! So this means that the Index() method is never tightly coupled to a particular implementation of a class.
Now, u decided that u didn't like all the code you did in the ReallyFastProductService and decided to code up another one, that takes use of some new tricks and skills you just picked up. So now you make a 2nd class called, PewPewProductService, because it pwns. Now, if u change your StructureMap mapping from...
ObjectFactory.Configure(x =>
{ x.For<IProductService>().Add(new ReallyFastProductService());});
to
ObjectFactory.Configure(x =>
{ x.For<IProductService>().Add(new PewPewProductService());});
... suddenly, all the methods in that HomeController now refer to the logic in the new class you just built. No need to change any code in the Controller.
Catch the penny as it drops :)
Welcome to DI/IoC and why it kicks serious butt.
I frequently use AutoMapper to map Model (Domain) objects to ViewModel objects, which are then consumed by my Views, in a Model/View/View-Model pattern.
This involves many 'Mapper.CreateMap' statements, which all must be executed, but must only be executed once in the lifecycle of the application.
Technically, then, I should keep them all in a static method somewhere, which gets called from my Application_Start() method (this is an ASP.NET MVC application).
However, it seems wrong to group a lot of different mapping concerns together in one central location.
Especially when mapping code gets complex and involves formatting and other logic.
Is there a better way to organize the mapping code so that it's kept close to the ViewModel that it concerns?
(I came up with one idea - having a 'CreateMappings' method on each ViewModel, and in the BaseViewModel, calling this method on instantiation. However, since the method should only be called once in the application lifecycle, it needs some additional logic to cache a list of ViewModel types for which the CreateMappings method has been called, and then only call it when necessary, for ViewModels that aren't in that list.)
If you really don't want to use a bootstrapper, then at least a static constructor is an easy way of ensuring your CreateMap is called at most once. (With less messing around and more thread proof than Jonathon's answer.)
public class AccountController : Controller
{
static AccountController()
{
Mapper.CreateMap<Models.User, ViewModels.UserProfile>();
Mapper.CreateMap<Models.User, ViewModels.ChangePassword>();
}
}
If you use profiles, you can place all of your "CreateMap" calls there. Additionally, you can create a static bootstrapper class that contains your configuration, and have the startup piece just call the bootstrapper.
OK, the way I'm currently doing it is this:
I add some logic to the constructor of my BaseController, which runs the 'CreateMappings' method, but only once per Controller Type:
public abstract class BaseController : Controller
{
public BaseController()
{
if (!controllersWithMappingsCreated.Contains(GetType()))
{
CreateMappings();
controllersWithMappingsCreated.Enqueue(GetType());
}
}
protected virtual void CreateMappings() { }
}
In each concrete controller, I use CreateMappings to declare the mappings for all the Models/ViewModels relevant to that controller.
public class AccountController : BaseController
{
public AccountController() : base() { }
protected override void CreateMappings()
{
Mapper.CreateMap<Models.User, ViewModels.UserProfile>();
Mapper.CreateMap<Models.User, ViewModels.ChangePassword>();
}
}
I also found some interesting alternatives involving Attributes here and here, however they strike me as a bit overcomplicated.
I have a search form that can search in different provider.
I started out by having a base controller
public SearchController : Controller
{
protected readonly ISearchService _searchService
public SearchController(ISearchService searchService)
{
_searchService= searchService;
}
public ActionResult Search(...)
{
// Use searchService to query and return a view.
}
}
And child controllers
TwitterController : SearchController
{
...
}
NewsController : SearchController
{
...
}
I use StructureMap to insert all my dependencies in the controller. With this setup, I was able to change the SearchService depending on the type of the controller being instanciated.
x.For<ISearchService>().ConditionallyUse(o =>
{
o.TheDefault.Is.OfConcreteType<NewsSearchService>();
o.If(c => c.ParentType == typeof(TwitterController))
.ThenIt.Is.OfConcreteType<TwitterSearchService>();
...
});
That even allowed me to set different Views for each controller, (just putting the corresponding folder (Twitter, News...) and the Parent controller is still handling all the Search, with a simple
return View(results)
which is displaying the correct view specific to twitter, news, or other
Now that was cool and looked great, I a single form and the different views are displayed in tabs on the same page. That's where it starts to get complicated with this approach. The form has to post to /Twitter to search in twitter, to /News to search in news... which means I should change the action parameter of the form depending on which tab I am and display the correct tab on when the form returns depending on.. the url? craziness follows.
If you have built something like this already or know what's the best approach to this, please advices are welcome.
Now I think I would have less pain using a parameter in the form and posting to a single controller. I am thinking of injecting the correct SearchService depending on this parameter. What would be the best approach? I thought of using a model binder,
So I would have my ActionMethod that look like this:
public ActionResult Search(ISearchService service, Query query)
{
var results = service.Find(query);
}
But I think would need to make a call like this in the ModelBinder
ObjectFactory.GetInstance(...);
Based on the querystring parameter that describe which provider to use, and that doesn't seem more elegant to me. I feel stuck, help :(.
Whenever you need to vary a dependency based on a run-time value, Abstract Factory is the general solution.
Instead of injecting ISearchService into your Controllers, inject an ISearchServiceFactory:
public SearchController : Controller
{
private readonly ISearchServiceFactory searchServiceFactory;
public SearchController(ISearchServiceFactory searchServiceFactory)
{
if (searchServiceFactory == null)
{
throw new ArgumentNullException("searchServiceFactory");
}
this.searchServiceFactory = searchServiceFactory;
}
public ActionResult Search(...)
{
// Use searchServiceFactory to create an ISearchService based on
// run-time values, and use it to query and return a view.
}
}
It is not entirely clear to me which run-time value you need to vary on, but assuming that it's the Query, ISearchServiceFactory might be defined like this:
public interface ISearchServiceFactory
{
ISearchService Create(Query query);
}
I was trying to figure out how to use the abstract factory pattern and still let structuremap resolve all the dependencies of my components.
I believe that is the way I am going to implement it, but I submit this here to get some feedback if someone would read this.
As explain in the previous answer, I do not want to build the whole object graph depending on which provider I need in the Abstract factory.
ie :
class StatServiceFactory : IStatServiceFactory
{
public IStatService Create(string provider)
{
switch(provider)
{
case "blog":
return new StatService(IFacetRepository,ISearchManager,IConfigManager,BooleanQueryBuilder);
//How to resolve the Config, the SearchManager, and BooleanQueryBuilder?
//Add more abstract factories? It starts to get messy in my opinion...
}
}
}
What I can do is have the abstract factory use my container to create an instance of my search managers depending on a parameter (coming from the querystring in my case)
Structuremap allows to create named instances this way :
x.For<ISearchManager>().Use<AbcSearchManager>().Named("Abc");
x.For<ISearchManager>().Use<DefSearchManager>().Named("Def");
I need a way to inject the container in my Abstract factory.
I would probably wrap the container in a wrapper defined like this. That would keep me from leaking Structuremap into my project. I dont need more that those 2 features within the abstract factory anyway, but it is not necessary:
public interface IContainerWrapper
{
object GetInstance<T>();
object GetNamedInstance<T>(string key);
}
and the implementation :
public class ContainerImpl : IContainerWrapper
{
private readonly Container _container
public ContainerImpl(Container container)
{
_container = container;
}
...
}
And setup StructureMap to resolve dependencies to my abstract factory like that :
x.For<IContainer>.Use(new ContainerImpl(this));
x.For<IFactory>.Use<Factory>()
My factory would be then much simpler and would create my instance like that :
public class SearchmanagerFactory
{
private readonly IContainerWrapper _container;
public SearchmanagerFactory(IContainerProvider containerProvider)
{
_container = containerProvider;
}
public ISearchManager Create(string provider)
{
//eed to handle the bad input for provider.
return (ISearchManager)
_container.Resolve<ISearchManager>(provider);
}
}
That seems pretty clean this way :).
Thoughts?
This is more an extensive comment than an answer to explain why an AbstractFactory seems complicated. Here is something that looks closer from the reality:
class StatServiceFactory : IStatServiceFactory
{
public IStatService Create(string provider)
{
switch(provider)
{
case "blog":
return new StatService(IFacetRepository,ISearchManager,IConfigManager,BooleanQueryBuilder);
//How to resolve the Config, the SearchManager, and BooleanQueryBuilder?
//Add more abstract factories? It starts to get messy in my opinion...
}
}
}
The FacetRepository is the same for any provider, but the SearchManager changes, the ConfigManager changes, and the BooleanQueryBuilder is an abstract class with different implementation for different provider (because every API doesnt use the same keyword for their queries) All those dependencies are currently resolved by structuremap, based on the type of the controller.
I would really like to keep the benefit of StructureMap here, rather than using factories all the way, for each different pieces.'
Please see my edit at the end of my question for another suggestion to my problem.
I'm using a masterpage in my ASP.NET MVC project. This masterpage expects some ViewData to be present, which displays this on every page.
If I don't set this ViewData key in my controllers, I get an error that it can't find it. However, I don't want to set the ViewData in every controller (I don't want to say ViewData["foo"] = GetFoo(); in every controller).
So, I was thinking of setting this in a base controller, and have every controller inherit from this base controller. In the base controller default constructur, I set the ViewData. I found a similar approach here: http://www.asp.net/learn/MVC/tutorial-13-cs.aspx. So far so good, this works... but the problem is that this data comes from a database somewhere.
Now when I want to Unit Test my controllers, the ones that inherit from the base controller call its default constructor. In the default constructor, I initialize my repository class to get this data from the database. Result: my unit tests fail, since it can't access the data (and I certainly don't want them to access this data).
I also don't want to pass the correct Repository (or DataContext, whatever you name it) class to every controller which in turn pass it to the default controller, which I could then mock with my unit tests. The controllers in turn rely on other repository classes, and I would end up passing multiple parameters to the constructor. Too much work for my feeling, or am I wrong? Is there another solution?
I've tried using StructureMap but in the end I didn't feel like that is going to fix my problem, since every controller will still have to call the base constructor which will initialize the repository class, so I can't mock it.
This is a similar question but I find no satisfactory answer was given. Can I solve this in a neat way, maybe using StructureMap as a solution? Or should I jsut suck it and pass a Repository to every controller and pass it again to the base controller? Again, It feels like so much work for something so simple. Thanks!
I see two options:
First:
Set the ViewData for MasterPage in YourBaseController.OnActionExecuting() or YourBaseController.OnActionExecuted():
public class YourBaseController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Optional: Work only for GET request
if (filterContext.RequestContext.HttpContext.Request.RequestType != "GET")
return;
// Optional: Do not work with AjaxRequests
if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
return;
...
filterContext.Controller.ViewData["foo"] = ...
}
}
Second:
Or create custom filter:
public class DataForMasterPageAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Optional: Work only for GET request
if (filterContext.RequestContext.HttpContext.Request.RequestType != "GET")
return;
// Optional: Do not work with AjaxRequests
if (filterContext.RequestContext.HttpContext.Request.IsAjaxRequest())
return;
...
filterContext.Controller.ViewData["foo"] = ...
}
}
and then apply to your controllers:
[DataForMasterPage]
public class YourController : YourBaseController
{
...
}
I think the second solution is exactly for your case.