I've got a few controllers here at work that contain methods I can use in other controllers.
I considered moving out some of the common functionality to a base controller which these could then inherit from. The problem with this is that I’d have methods I need in multiple base controls which I’d not be able to access. (Because we can't inherit from multiple base controllers).
My other idea is to move out the common functionality into their own classes, outside of the Controller folder.
What would you do? Is there a great way in ASP.NET MVC to share code like this that I don't yet know about?
There's a rule of thumb about object-oriented programming that you should favor composition over inheritance, and it fits very well into this scenario.
I would make one or more services that encapsulate the methods in question, and then consume those services from the Controllers.
For extra points, extract an interface from the service(s) in question, and inject the interface into the Controllers for maximum Separation of Concerns.
I'd factor out in to a helper class or something. From what you have described the functionality helps the controllers/
The choices seem to be base controller or helper class. You could take control of controller creation and inject the helper into whichever controllers need it.
Related
I'm sorry if that question was already discussed, but I didn't find exactely what I wanted. The problem I'm facing is more about patterns and design choices than about .NET itself. I just would like to have your advice to know where to start my refactorings.
Today I opend one of the classes in my actual application and found that it has 13 dependencies injected by constructor !!! In fact each developper added the dependecy it needed in method that he was writing.
One point of my understanding of DI is that when we inject a dependency by constructor it means that it's a mandatory dependency and should be used in all methods of the class. If we need a particular dependency just in one method of the given class, what does it mean for you ?
The given class does too much ? I should consider to create a new type just with a needed dependency ?
I should inject by property ? But in that particular method a dependency is mandatory so I don't think it's a good choice.
I should inject by method ?
What's difficult is to find the right balance. In reallity sometimes it's not possible to encapsulate the bahaviour in the clean way.
I was considering to create something like service aggregator to hind related dependency behind one of them but would like if you have other advices. Thanks in advance.
You are correct: if you need to inject 13 dependencies into a class, it's a pretty sure sign that you are violating the Single Responsibility Principle. Switching to Property Injection will not help, as it will not decrease the number of dependencies - it will only imply that those dependencies are optional instead of mandatory.
Basically, there are two ways to deal with this type of problem:
Refactor to Facade Services. This is basically a non-breaking refactoring as it maintains the functionality of the Controller. However, it changes the responsibility toward coordinating/orchestrating the interaction between services instead of managing the nitty-gritty details of the implementation.
Split up the class into independent classes. If each of the services were introduced by different developers to support a subset of the methods, it's a sign of low cohesion. In this case, it would be better to split up the class into several independent classes.
Specifically for ASP.NET MVC you may not want to split up an Controller because it will change your URL scheme. That's fair enough, but consider what this implies: it means that the single responsibility of the Controller should be to map URLs to application code. In other words, that's all a Controller should do, and it then follows that the correct solution is to refactor to Facade Services.
Just because a dependency is mandatory doesn't mean it should be used in all the methods of a class, IMO. It should just be logically part of the configuration of the class itself.
On the other hand, if a class has 13 dependencies it may well be doing too much. Do any of those dependencies logically belong together? Perhaps the dependencies themselves should be "chunkier" - or quite possibly your class should do less.
This sounds like a case of a class having too many dependencies i.e. it's a God class. Try and break it down into more discrete responsibilities.
If your class has 13 dependencies you definitely have a problem. Clearly your class serves too many responsibilities. Marc Seemann has discussed this problem in his book "Dependency injection in .NET" paragraph 6.4. If your class starts to have 3 parameters in the constructor you must start to wonder. Is my class still serving one responsibility? If you start to have 4 or more parameters in your constructor refactor your class by start using the facade or composition pattern.
Its just the way DI works. Its a fact. So accept it. Its fully legit in a service like a Pdf Service, Look at this code:
public PdfService(ILocalizationService localizationService,
ILanguageService languageService,
IWorkContext workContext,
IOrderService orderService,
IPaymentService paymentService,
IDateTimeHelper dateTimeHelper,
IPriceFormatter priceFormatter,
ICurrencyService currencyService,
IMeasureService measureService,
IPictureService pictureService,
IProductService productService,
IProductAttributeParser productAttributeParser,
IStoreService storeService,
IStoreContext storeContext,
ISettingService settingContext,
IAddressAttributeFormatter addressAttributeFormatter,
CatalogSettings catalogSettings,
CurrencySettings currencySettings,
MeasureSettings measureSettings,
PdfSettings pdfSettings,
TaxSettings taxSettings,
AddressSettings addressSettings)
I currently have all my common utility function methods in a base controller, which all of my controllers inherits from. These are methods for functionality like uploading files, resizing pictures, deleting files, sending e-mails, generating random passwords, hashing passwords, etc.
What is the recommended structure for these kinds of things?
In that case you shouldn't put all these utility functions inside your base controller. You will face a lot of problems if your project grows. Changes and testing of these methods can become difficult, all your inherited classes need to use the same utility methods, etc. Have a look at Composition over inheritance to see another approach.
Somethimes I tend to organize my projects in the following manner if that might help you:
Simple helper methods: Create a folder and a namespace (e.g. namespace [...].Common") inside your web project and put one or more public static classes inside it (e.g. class "FileHelper.cs", "StringHelper.cs", etc). If you need one of these methods in a controller action simply put a "using ...Common" statement at the top of your controller class and call e.g. FileHelper.MethodName.
If I can define a closed subject area with a group of methods I try to encapsulate these methods in a service class (maybe even outside the web project if I have a feeling that I might need this functionality in other projects too), define an interface for that class and plug that functionality into controller classes by using dependency injection. If you don't know about that concept you should definitely read Dependency injection in ASP.NET Core. Dependency injection is a vastly used major concept in ASP.NET Core projects that brings you a lot of advantages and - if used correctly - stears your work into well-organized projects.
More complex organizations are always possible depending on your needs. Have a look at multitier, hexagonal or onion architecture if your projects grow.
Is it possible to create a Partial class for the controller in MVC?
Reason : I have a controller which contains too many code. This controller contains the code for different reports and due to too many code it reduces the readability of the code. I want to keep controller name same for all reports so I want to distribute code for the different reports.
If i can do any other way than do let me know.
Thanks
Alok Shah
Yes you can use a partial class - the compiler just merges them all up a compile-time to produce one.
However, you mention you want to 'distribute' code - if the code is to go into multiple projects then partials are not going to help.
You can instead create base controller classes (that inherit from System.Web.Mvc.Controller in a class library project, with the necessary action methods, and then simply use routing to route similar urls to different controllers. Here's a link to the Asp.Net Tutorial 'Creating Custom Routes' which might be useful for that. I hightly recommend looking through the rest of the tutorial if there are other core aspects of MVC you're not sure about. It doesn't cover everything, but it does the basics.
A web application that needs to use those then simply has its own controllers inherit from those redistributable ones. Even better, you can now create extensibility points through virtual methods etc if there are elements of these reports which different web apps might need to customise.
So "Reports/Customers" could route to a CustomerReportsController and "Reports/Orders" could route to an OrdersReportsController:
routes.MapRoute("CustReports",
"Reports/Customers/{action}",
new { controller = "CustomerReports", action = "Index", id = "" } );
routes.MapRoute("OrderReports",
"Reports/Orders/{action}",
new { controller = "OrdersReports", action = "Index", id = "" } );
This is the most simplistic approach to this problem - but I think using Areas (link is to MSDN walkthrough) would most likely also be applicable, in which case you might not need to use routing at all because the default route would probably do it all.
Of course!
Partial classes are a feature of the C# language and bare no relation to MVC or any other framework you may be using.
Yes. Partial classes are really just a feature of the language, and the compiled class is a regular .NET class like any other.
I would suggest though that you split the controller into multiple controllers, to ensure proper separation of concerns (having a class that is so big you need to split it up into multiple files will surely smell bad.)
"If I can do any other way than do let me know"
How about:
Abstract away the "doing" parts to various report generators for the discrete report types, all of which conform to an Interface. These report generators will be classes sat outside of the MVC tier of the application.
Clean up the controller so that the dependencies (Report generators) are injected in the constructor, using Ninject, StructureMap or Castle Windsor
Clean up all of the report generation code out of the controller and into concrete implementations of the Report generator abstractions
You will then not need to split up your controllers into separate classes. The downside is that this will take a reasonable amount of time to conceptualize and implement, but you'll end up with a better codebase.
I found this Post (How to extend where MVC looks for views) about changing the location of the View.
I was wondering if there's something similar for changing the location of the controller.
I just want to change the location of the class inside project and don't want to affect the url.
For example Instead of placing the Controller into
MyMvcProject\Controllers\
MyController1.cs
MyController2.cs
MyController3.cs
I want to achieve something like
MyMvcProject\MyGroup1\
MyController1.cs
MyController2.cs
MyMvcProject\MyGroup2\
MyController3.cs
and also support Areas:
MyMvcProject\Areas\MyGroup3\
MyController4.cs
Is it possible to achieve this? And if yes, where can I find documentation about it?
You can do what you want, and it doesn't require any special configuration, because ASP.NET MVC does not care about where you put your controllers. First, controllers are located using reflection, so the name of the folder where you put your controllers is irrelevant. Controllers are searched by type name and optionally by namespace (for disambiguation). You can even have controllers in separate projects/assemblies. As long as the controller ends up in an assembly in the bin folder then it's searchable by the framework.
As mentioned above, you'll need to create a controller factory to support your custom resolution. Here's an example:
http://develoq.net/2010/custom-controller-factory-in-asp-net-mvc/
As others have already stated you need to do one of the following:
Derive from IControllerFactory interface and provide an implementation of the CreateController and ReleaseController methods.
Derive from DefaultControllerFactory and override the default behaviours.
Here are some links to get you started:
Custom controller factory in ASP.Net
Inside the ASP.NET MVC Controller factory
Dive deep into MVC - IControllerFactory
Also, if you're willing to spend a bit of money I would also recommend the book Pro ASP.NET MVC 3 Framework as this explains almost every aspect of how the MVC framework can be customised (including an example on how to create a custom controller factory - the source code for which can be freely downloaded from the publishers website).
I think it is impossible to do this. ASP.NET MVC have defined the convention that we have to follow.
Controllers are in Controllers folder, views are in Views{ControllerName}\
I believe you cannot change the convention unless you create your own ControllerFactory.
If you really want to do that, just implement IControllerFactory interface (or try to derive from DefaultControllerFactory).
Then your Application_Start register your controller factory using ControllerBuilder.Current.SetControllerFactory method.
Look at the ControllerFactory documentation and to the MVC source code for details.
What you're asking and what your example shows are two different things; depending on which one you want to achieve, you may or may not need to do any work.
There are two requirements for a class to be a controller in the MVC Framework:
It has to have a class name of Name + "Controller"
It has to have a parameterless public constructor.
Your sample "normal" MVC layout is actually not valid:
MyMvcProject\Controllers\
MyController1.cs
MyController2.cs
MyController3.cs
Those classes wouldn't be found by MVC because they don't have the correct name, regardless of which folder they are in.
If all you want to do is change the namespace/folder names, that "just works", assuming you name them the same as the appropriate route segment(s):
MyMvcProject\MyGroup1\
Page1Controller.cs
Page2Controller.cs
MyMvcProject\MyGroup2\
Page3Controller.cs
MyMvcProject\Areas\Area1\
Area1Page1Controller.cs
This walkthrough (written for MVC 2 but works just as well in MVC3) shows you how to support Areas with the default controller behavior.
If you actually want to name them SomethingController1 or SomethingElseController5, or otherwise change the route -> classname mappings, then you do need to implement a custom ControllerFactory, and inject it into the MVC pipeline.
There are plenty of examples on the web on how to do this, including the one posted earlier.
I'm in the process of developing an ASP.NET MVC project, and after several weeks of research, I have a pretty good framework in place using StructureMap to register my dependencies at bootstrap time, create my controllers with the correct implementations, a custom model binder for passing data to my controller, etc.
After thinking about the data objects being passed to my controller actions, I began to wonder... should controller actions take in interfaces or concrete types?
It makes perfect sense that when my controller is being constructed by the controller factory, the dependencies should be passed into my constructor as interfaces, but what about the data objects created by the model binder? Should they be registered into my IoC container as well?
In code, it's only a few extra lines to hook it all up so the engineering overhead is pretty low. On the other hand, based on the nature of the framework, I'm not going to need to handle different implementations in the final product. But with everything I've learned about "future-proofing" my code, interface-driven design, designing for testability, loose coupling, and any other buzz words you can think of on this topic, my gut still tells me that interfaces should be the way to go.
I hope I've made some sense in my dilemma. Does anyone have any strong opinions one way or another on this topic?
TIA, -J
No way. You wouldn't be solving the problem IoC is meant to solve.
Viewmodels should be dumb as dirt. IoC is good for swapping implementation details. Since your view models are dumb what kind of implementation details can you possible swap? View Models also have narrow and non-orthogonal responsibilities very unlike traditional injectable classes like ILogger or IRepository.
IMHO this would be some serious over-engineering and the resulting complexity ( I'd anticipate service location responsibilities in your controllers for edit scenarios ) wouldn't be worth it.