I have an winforms application that was built using MVC. The controller is subscribing to all of the events from the view (button clicks, etc) and connects multiple views with the model.
The problem is that the controller is now about 3000 lines of (hard to unit test) code.
What is the best practice to avoid getting controllers to do everything and become so big?
One obvious thing to point out might be that one controller does not have to be implemented as one class. The MVC design pattern simply states that M, V and C are separate components, but not that each must be one, and only one, class.
Sub controller
Controller can be split in various sub-controller without broking the MVC pattern.
At 3k lines, it's for sure that the cohesion is broken somewhere. Try to group together same behavior and create new controller. This way, you will have a "main" controller that will invoke "sub" controller.
Method without sub:
For my own experience, I do not have 1 controller for the whole WinForm application. How I created it is that I have mutiple module that are loaded from the menu. When those module are loaded (Form->View) it comes with its own Controller. This way, I only have 1 controller for each module. Those controller aren't over 500 lines of code usually.
Depends on the situation, but assuming you are not at a point where a new controller should be created there are several approaches.
Much depends on your setup. One common approach is to have a service layer or service agent which would do work for the controllers that is not specific. The use of interfaced helpers or even static ones should remove some of the repetition. 300 lines does not sound to bad at all assuming it is broken into testable methods.
I would be interested too to hear of other opinions other than the oft repeated mantra of creating more controllers. We use MVP and have experimented with sub controllers but this does rely on careful usage and is probably a bad idea.
It is common to have one controller per module in MVP, which would relate to a logical part of your application. There should be a few clear ones within your domain and a few that are maybe a bit more difficult to distinguish.
Related
Where is the best place in the project directory for the controllers for Shared partial views?
I have found similar question to: ASP.NET MVC: Correct place for Partial Views?
I can't decide if it is better to do something like /Controller/Shared/CONTROLLER_FOR_PARTIAL_VIEW or just create its separate folder like /Controller/CONTROLLER_FOR_PARTIAL_VIEW
The partial view is specifically for dropdownlistfor, and the model wont be used for anything other than to populate the dropdown. So if a site has many dropdown lists or just partial views in general, a shared folder seems to be the best option. If the preferred way it the Shared folder, do you use one controller for each partial view, or one controller for all partials? I appreciate any thoughts or feedback, thanks!
EDIT: To be clear, I m specifically asking about the directory for the CONTROLLERS not the VIEWS. Thanks!
In one sense, it doesn't matter. There is no true standard or convention for this, so you have the freedom to do it however it makes the most sense to you and your application.
Having it under something like Controllers/Shared could make sense, if there's enough of these that that is worthwhile and it adds value to keep them separate from regular controllers. However, in terms of a project, everything is essentially shared, so there's no true distinction here. Personally, simply having it named something distinctive is probably the best route. For example, I have a number of child actions in one of my projects that are used in various parts of my layout. As a result, I created a LayoutController to house these.
The one thing to keep in mind is that, if you're using standard routing, any controller will be available to the routing infrastructure, regardless of where it's located in your project tree. You'd have to pretty much just know how to get to it, but if you named your shared controller something like SharedController, then with standard routing, its actions would be available via /shared/action. For things like child actions, this is easily solved by using [ChildActionOnly]. By adding that attribute to your child action, it will be divorced from the routing infrastructure for URL requests. Internally, MVC will still be able to get to it for the purposes of rendering it for a view, though.
Projects I've been on it was at /Area/Controllers/SharedPartialController.cs and with that naming the view was at /Area/Views/SharedPartial/_MenuDropdown.cshtml
Hopefully you're using "areas" in your MVC project, in which case I would suggest doing one shared controller per Area.
I.e. /Order/Controllers/TabsPartialController.cs for one that relates to Order area, and then /User/Controllers/NavTabsPartialController.cs etc.
I am in the starting stages of moving from NET c# to MVC, and am wondering about something. I see all of these examples and cases where the code is not organized in any manner within the three primary directories (Model, View, Controller). For example, is it bad practice to have my project design such as "root/Controller/Employee/[multiple controllers for employee, and then root/Controller/ProjectPhase/[multiple controllers for project phase objects], or is it assumed that this need should not be necessary according to the already efficient design implementation of the standard MVC project. Maybe I am overlooking/complicating this or prematurely asking this question, and should give it some more time and or reading/research, but was curios on the topic.
Thanks in advance
All controllers should be directly below controller folder. If you want to segment your controllers, you need to use Areas. With Areas you can have multiple trees of models views and controller.
My site has multiple public pages showing some lists like news,products etc... everyone can see. So I have a NewsController and ProductController. The Create/Edit action can only be/must only be executed by the admin. When I separate the admin stuff (Create/Edit) from the public stuff(List) I would create 2 areas public/admin each having its own controller. That means I would have TWO ProductController one with List action and one with Create/Edit action and TWO NewsController same game...
Would that make sense? I looks like DRY - don`t repeat yourself!
How would you handle that scenario concerning the new asp.net AREA feature?
I'm not sure how you are repeating yourself? I always create an admin area for crud operations. You should be moving all of your logic outside of your controllers into a separate class, and depending on how big this site, maybe a separate project altogether. Take a look how the Raccoon Blog structures their project. I have learnt a great deal from studying their code. If you are having questions on how to structure your code, I suggest looking over there to - https://github.com/ayende/RaccoonBlog/tree/master/RaccoonBlog.Web. I believe they have an excellent example of how to implement admin areas correctly.
AuthorizeAttribute is how I'd handle it, I wouldn't use Areas to partition permissions.
I'm working in a C# project and we are , in order to get some unity across the different parts of our UI, trying to use the MVC pattern. The client is windows form based and I'm trying to create a simple MVC pattern implementation.
It's been more challenging than expected, but I still have some questions regarding the MVC pattern. The problem comes mostly from the n-n relationships between its components: Here is what I've understood, but I'm not sure at all of it. Maybe someone can correct me?
Model: can be shared among different Views. 1-n relationship between Model-View
View: shows the state of the model. only one controller (can be shared among different views?). 1-1 relationship with the Model, 1-1 relationship with the controller
Controller: handles the user actions on the view and updates the model. One controller can be shared among different views, a controller interacts only with one model?
I'm not sure about the two last ones:
Can a view have several controller? Or can a view share a controller with another view? Or is it only a 1:1 relationship?
Can a controller handle several views? can it interact with several models?
Also, I take advantage of this question to ask another MVC related question. I've suppressed all the synchronous calls between the different members of the MVC, making use of the events and delegates. One last call is still synchronous and is actually the most important one: The call between the view and the controller is still synchronous, as I need to know rather the controller has been able to handle the user's action or not. This is very bad as it means that I could block the UI thread (hence the client itself) while the controller is processing or doing some work. How can I avoid this? I can make use of the callback but then how do i know to which event the callback comes from?
PS: I can't change the pattern at this stage, so please avoid answers of type "use MVP or MVVC, etc ;)
Thanks!
Model, View, and Controller are conceptual layers, not individual objects, so honestly it doesn't make a whole lot of sense to be thinking of them in terms of multiplicities. Nevertheless, I can try to approximate an answer for you.
A Controller returns a single result for a single action; that result may be an actual view or it may be something else. However, the Controller doesn't really actually have any interaction with the view; all it does is provide one or two pieces of information in its result: The name of the view that should be used and (optionally) the model used to populate. It's up to the View Engine to actually create and bind the view, which is a considerable departure from normal Smart Client UI logic.
A Controller may interact with several different pieces of the Model, or not interact with it at all in some cases; there is no rule for that side of the relationship. In an action result, a Controller has to give back either 0 or 1 instances of a "model", but this may not be the true Domain Model, it could be a View Model.
A View is generally bound to exactly one Model (or View Model), although in some cases a View might simply be content and therefore not bound to anything.
So, in the very crude UMLesque parlance:
Controller:Model = 0..* : 0..*
Controller:View = 0..* : 0..1 (request) or 0..* : 0..* (overall)
View:Model = 0..* : 0..1
This is all specific to ASP.NET MVC. If you were designing your own MVC implementation then obviously you could choose to implement it any way you like. Good luck implementing MVC in WinForms, though; Forms don't behave like Views at all, even patterns like MVP/MVVM are quite difficult (though not impossible, c.f. Microsoft's CAB/SCSF) until you move to WPF.
I´ve implemented the MVC pattern in C#. Don´t know very much about theory, or how it should be, or shouldn´t be. I just think that the pattern is the base idea, and then, you can use this idea in many different ways, depending on your own needs. I´ll tell you about my implementation, and hope it helps you.
**The Model**
Your description is pretty clear, so don´t have much more to said. Here is where I define my bussiness objects. I take advantage of this layer to include objects validation rules.
**The Controller**
In addition to handle the user actions and update the view, I have a Unit Of Work for each controller. I check that the objects in the view pass the validations (defined in the model layer) before commit changes in the Unit Of Work.
In my case, one controller can manage many models, and I like to have only one view in each controller.
Like a suggestion, I´d like to use my Framework with diferent UI, so I have an abstract implementation of Controller, and then I have specific controller implementations for different interfaces (WebForms, WinForms, ...).
**The Views**
In your case, we could call them, simply, the forms, the UI, ... I like to organize my desktop applications as if they were web applications, using tabs. One tab represents one controller, and so on, one view, and one or more models.
In conclussion, and in my case:
n models - 1 controller
1 controller - 1 view
--
n models - 1 view
You're probably over-thinking and over-formalizing it a bit.
Here's how I look at it:
Model: This is the actual thing that does real work.
Controller: This is the thing that sends inputs into the model, so it will do work.
View: This displays the results.
That's it. The easiest analogy to use is a console application - the app is the model, STDIN is the controller, and STDOUT is the view.
Extending that analogy, many GUI apps are built on top of command-line apps by attaching to STDIN/STDOUT. In that case, the things sending data to STDIN are the controller, the things taking data from STDOUT and putting on the window are the View, and the console app is still the model.
It's CS 101 again - input, processing, output. It's only trickier for a GUI app because the input and output are typically on the same window.
You (obviously) don't need to actually have a console app to do this - the separations can be done even in a single process. All the other weird wiring stuff that takes place is just whatever is needed to get this relationship between the parts to work. But the wiring isn't the important bit - the important bit is the separation of responsibilities and logical organization of the code.
So, whether 1 view must map to 1 controller, or any other orthognality issues are secondary. In fact, you should probably just do whatever your problem domain requires, but I'd (as typical) argue against over-eager generalization of code - IOW, don't mush things together that aren't really the same.
So I'm embarking on an ASP.NET MVC project and while the experience has been a good one overall, I'm not quite as pleased with the spaghetti mess that my controllers have become. I've looked around online (CodeCampServer, etc...) and they all seem to suffer the same issue wherein controller methods violate SRP (single responsibility principle) pretty consistently - such as a controller method that simply renders the view if the request is a GET but updates the model if it's a POST. Now I've got controller methods responsible for multiple logical routes throughout the application - say it checks for which button was clicked on the form and acts accordingly. I could redirect each button click to a different form action using JavaScript, but something doesn't feel right there either... The other big issue is the proliferation of magic strings - ViewData["foo"] = blah; Long story short, how do you guys structure your controller logic? One giant model object per view? Lots of little controller methods and JavaScript is the router? My goal is maintainable code - as features get piled on I'm starting to slide down that slippery slope...
ASP.NET Preview 5 (available on CodePlex) has an answer for this: the [AcceptVerbs] attribute. Phil Haack has a blog post discussion how it's used.
As for the view data magic key question, it's an interesting problem. If you think of a view as being a bunch of semi-independent components (especially in light of the new partial view support), then making a strongly-typed model becomes less ideal, as the several pieces of the view should be relatively independent of one another.
How are different people handling this issue? I know that i just spent a couple hours reviewing the jumble inside of the model folder. I'm finding creating folders is helpful in reducing the visual clutter, using matching namespaces helps alot too.
But my controllers are monoliths at the moment. the trouble is that i've been focused on learning to this point in the project (still lots to sort out as well).
I'm getting a good handle on MVC now, so it is time to review the complexity and consider modifying the controllers up into better named and cleaner functions.
Are other people breaking their controllers up into sub controllers? (If there is such a thing)