I have been trying to mock grails' convention over configuration paradigm in a spring mvc application and i am finding it difficult to automate handler mappings.
Basically i have a controller like this.
#Controller
#RequestMapping(value = {"/", "/contact"})
public class ContactController {
#Autowired
private ContactService contactService;
#RequestMapping(value = {"/","/index"})
public String listContacts(Map<String, Object> map){
map.put("contact", new Contact());
map.put("contactList", contactService.listContact());
return "contact";
}
#RequestMapping(value = "/add", method = RequestMethod.POST)
public String addContact(#ModelAttribute("contact")Contact contact, BindingResult result){
contactService.addContact(contact);
return "redirect:/contact/index";
}
#RequestMapping(value = "/delete/{contactId}", method = RequestMethod.GET)
public String removeContact(#PathVariable("contactId")Long contactId){
contactService.removeContact(contactId);
return "redirect:/contact/index";
}
}
Now, i have tried "ControllerClassNameHandlerMapping", but it seems to have a limitation with three part url.
I basically want all the requests to be automatically mapped to the appropriate controller and actions, without using #RequestMapping
Any pointers will be great help
That won't be easy. Grails framework has written bunch of ASTTransformers where they inject annotations and other properties in to the class which is controller. Take a look at the source code for grails-plugin-controllers and you cans see the code under compiler.web and see what they are doing. Also if you take a look at ControllersGrailsPlugin you will see that its watching the directory grails-app under the parent folder. It won't be that easy to do. Hope this helps
UPDATE
Making AST transformations via ASM in your case, is probably the fastest way, maybe post-compilation step?
Hope it helps
It won't be that simple but what you want is likely to perform the following :
Write an annotation processor(scan classpath from classloader) to collect Controllers annotations and matching class
Hook into Spring mvc API to inject the Request Mapping based on your conventions.
Then you would also need to collect the method parameters to auto-inject pathVariables, etc.
If Spring MVC is not expecting to play with the RequestMapping annotation as soon as the Controller annotation is found (or defaults to something), then you're good to go (Post Bean Definition processors or similar mechanisms)...
Not that simple, but definitely possible...
Related
So I have a need for injecting a number of different services into an authorization attribute I'm using. For simplicity I will leave this to show the configuration manager.
public class FeatureAuthorizeAttribute : AuthorizeAttribute
{
public IConfigurationManager ConfigurationManager;
private readonly string _feature;
public FeatureAuthorizeAttribute(string feature)
{
_feature = feature;
var test = ConfigurationManager.GetCdnPath();
}
}
Which would be used as follows
[FeatureAuthorize("Admin")]
I have tried to use constructor injection
public FeatureAuthorizeAttribute(string feature, IConfigurationManager configurationManager)
{
ConfigurationManager = configurationManager;
_feature = feature
}
However this just causes an error when I attempt
[FeatureAuthorize("Admin", IConfigurationManager)]
Which seems like the wrong way to go about it in the first place. I'm assuming that I need to register my custom authorization attribute with the container to get it to start picking up
Instead of trying to use Dependency Injection with attributes (which you can't do in any sane, useful way), create Passive Attributes.
Specifically, in this case, assuming that this is an ASP.NET MVC scenario, you can't derive from AuthorizeAttribute. Instead, you should make your Authorization service look for your custom attribute, and implement IAuthorizationFilter. Then add the filter to your application's configuration.
More details can be found in this answer: https://stackoverflow.com/a/7194467/126014.
To begin with two things.
I am trying to achieve an action filter that logs when and action begins and when it end
I am well aware of the .AsActionFilter() method in Autofac 3.0 BUT...
The project that this is using is based in Orchard 1.6 which is known to be compatible with autofac 2.6.xxx. We do not want to go through a potentially lengthy process of upgrading to Autofac 3.0 at this time so the .AsActionFilter() option is not available to us.
The other option is to set the filter (which extends ActionFilterAttribute) as an attribute on our base controller (from which all other inherit btw). The problem is that the filter itself has two dependencies:
A service of our own that holds information on the context
An implementation of an ILoggingService
What I cannot find is a way to inject these into the actual property at the head of the class. Does anyone know a way in which to achieve this either through the [Attribute] line itself of some function of Autofac during registation?
The ActionFilterAttribute:
public class GRMSActionLoggingFilter : ActionFilterAttribute {
private readonly IGRMSCoreServices _grmsCoreServices;
private readonly ILoggingService _loggingService;
public GRMSActionLoggingFilter(IGRMSCoreServices grmsCoreServices, ILoggingService loggingService) {
_grmsCoreServices = grmsCoreServices;
_loggingService = loggingService;
}
public GRMSActionLoggingFilter() { }
public override void OnActionExecuting(ActionExecutingContext actionContext) {...}
public override void OnActionExecuted(ActionExecutedContext actionContext) {...}
}
Assigning the attribute to the base controller:
// This currently compiles but will fail during run time as the IGRMSCoreSerivces and ILoggingService will both be null. Need to property inject these services somehow.
[GRMSActionLoggingFilter]
Anyone have any idea to achieve this?
You cannot (easily) inject runtime values to attributes.
This is how attributes work in C# - you can only pass constant values of certain types. You can read more about it here.
In order to achieve desired functionality in Orchard you need to split your code into two components:
a marker attribute class you put on your action
an action filter class inheriting from FilterProvider and implementing IActionFilter
The way it works is that you put an attribute on some action and then use the action filter to check existence of that attribute (using filterContext.ActionDescriptor.GetCustomAttributes(...)). If an attribute exists, do your stuff.
There are lots of examples of this technique in Orchard core. Check eg. the ThemedAttribute and ThemeFilter action filter classes.
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.
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.
Background
I am trying to move business logic out from the controllers into their own services.
Controller
public class AccountController : Controller
{
private readonly IAccountService _accountService;
public AccountController(IAccountService accountService)
{
_accountService = accountService;
}
....
}
I'm using Unity to inject dependencies. I'd like to use the Url.GenerateUrl() helper method within the implementation of IAccountService but Url is a property against the controller.
I looked at the MVC source to see how this is done but it requires me to access the RequestContext from outside of the controller, and I don't know how to do that.
Question
How do I access the RequestContext from outside the controller? If that won't solve my problem, how do I solve the problem given my setup?
This might not be quite right because I'm unable to test it at the moment, but I think that you can do something like this in .NET 4+:
using System.Web;
using System.Web.Mvc;
// ...
var helper = new UrlHelper(HttpContext.Current.Request.RequestContext);
string url = helper.GenerateUrl(/* ... */);
It might make more sense to pass the context from the controller to your IAccountService implementation rather than grabbing it directly from HttpContext.Current.
However i'd like to use the Url.GenerateUrl helper methods within my implementation of IAccountService
Simply pass this information as parameter. Example:
public ActionResult Index()
{
var someUrl = Url.Action("about");
_accountService.Foo(someUrl);
}
Now you no longer need UrlHelper inside your service classes. Everything that needs interacting with MVC infrastructure shouldn't be placed in your service classes. They shouldn't depend on any Request, Response, Session, ... It's the controller's responsibility to work with those objects and glue them together with your service classes.