I've inherited a project in which I'm the fifth proverbial 'cook in the kitchen'. The project is too mature for extensive changes on my timeline, but I'm thinking I can at least get rid of some of the "where was that code again!?" issues I'm having.
All of the controllers are dumped in the same Controller folder, but there are enough with similiar names to be a bit cumbersome. Additionally some of these controllers are solely for partial views. The admin page for instance has its own controller, but each of the four tabs on its view have their own model/view/controller. What are some recommended approaches I should take to get this under control?
If you're looking to organize your MVC project, I find Areas an invaluable way to keep things from getting out of control.
It might mean changing some of your paths, but I'll leave it to you to determine the value to your particular project.
Have a read of this: http://msdn.microsoft.com/en-us/library/ee671793%28v=vs.100%29.aspx
Related
I have an ASP.NET application that was developed by "programmers". This application contains all things which you should not do:
Hardcoded settings
Copy/paste anywhere (code not re-used)
Make a lot of small SELECT requests to the DB for each row instead of doing JOIN
Model, view and controller in one function
Etc.
Now, my goal is not to throw everything away and start over, but I want to separate different aspects of the MVC of the application. I do not want to start a new MVC project, I would like to evolve the existing solution into something modular.
For the controller, there is no problem, I can create classes that will manage DB connections, send mails etc. On the other hand I do not know how to separate the view and the controller.
The problem that traditional ASP pages myPage.aspx have an associated file myPage.aspx.vb and in this vb file there are both view management part(page elements, like dropdowns) and also the Business part (controller) which is executed on the button click.
I thought about making a call to a myPageControl.vb class that will contain the business part from the file myPage.aspx.vb, which will call the Model (db, mail, other).
(View: myPage.aspx.vb) -> (Control: myPageControl.vb) -> (Model: Db.vb, Mail.vb)
The problem is: how should I do to modify the page content from the controller, for example change a list value or display a text on it. I have to make a call to the View (to the other direction) and pass by parameter the class MyPage (.asp.vb)
I have already tried to find an answer to my question, but I've found only answers taking about MVC projects.
Does anyone have any idea how I should do it?
Seperation of Concerns was one of the main problems with webforms, and one of the advantages of MVC. In my opinion the best you could probably do is seperate the business logic into classes like you are doing now so code could be reused throughout the application, but completely "seperating" everything may require rebuilding the application as an MVC app.
The only answer I've found to this is to have the controller send the "data to bind to" to the page as XML. then all the page has is its page_load of course, and then a method to receive the XML and update itself from it. You can use smart naming structures so that you can do reflection and autobind from the xml to page elements.
Then on an action, have the page generate an xml of all the elements on it and their values, and send that through a "ProcessAction" method that determines the correct controller and calls the right method on the controller.
But as suggested, doing it over as an MVC project probably makes the most sense if that's the pattern you are going for. What I suggested works, but it will be as much or more work than just starting from scratch with MVC. Besides, remember that "support" for web forms is disappearing soon. It's not in (and won't be in) .NetCore, so it's days are numbered.
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.
My question is similar to "ASP.NET 2 projects to share same files", but with an ASP.NET MVC slant.
Basically, we have two sites, one being based mostly on the other (roughly 90% views, controllers, images, in the second are identical to the first). However, in some cases, the views may be different, or a controller in the second site may be different to the first.
Are there any simple ways of achieving this in ASP.NET MVC?
So far, we've looked at using linked files to have two totally seperate projects where the second project shares the files it needs from the first.
One problem with this approach is that most pages in the second project don't literally exist in the virtual directory, it makes debugging a pain - you have to publish in order to generate the files so you can debug.
Does anyone have any better approaches, or ways this approach can be simplified?
This article might help: http://dotnetslackers.com/articles/aspnet/storing-asp-net-mvc-controllers-views-in-separate-assemblies.aspx
Essentially, it involves creating your own WebFormViewEngine which tells MVC where to look for the Views.
If they are 90% the same and you want to keep them in sync as functionality evolves I would consider making them into a single web application and using the host header to differentiate and to change the images/links/text/functionality/etc. between the two sites.
You can do this in your BaseController: look at the host header and create a Brand object that every page and view has access to, just like it might have aUser object. That Brand object can include the name of the site, the canonical Url for the site, the location of the image directory for that brand, boolean values to turn certain features on or off, ...
Now in a Controller you can just ask if (Brand.SupportsPageX) {...} to decide what to show next. And if you make the brand object part of your base view model or put it in the view collection you can have views that use the brand's name, image directory, ... to customize how they look.
Put as much as possible into a shared non-UI library project. I do that on every project that I work on this, increased testability, shared code with Windows Services, and a host of other reasons.
I've found that if you're aggressive with this then quite often over two-thirds of the project would be in the non-UI shared library.
After doing this, you can take things a step further and create a second library with some shared MVC/UI elements.
Depending on your opinion of it, RenderAction may help a bit here. As you know, RenderAction will allow you to group up those controller/view components and pass in variable arguments at runtime.
A project I'm working on currently has a similar requirement and we have started looking at using portable areas. I personally haven't delved very deeply into them at the moment, but it may be worth you taking a look.
I've been working with areas to create multiple websites that I can host with one hosting account. I would think you could use a similar approach. By implementing the common functionality in the base project, it will be available to each area. You can also override any of the base views or controllers by implementing them in the area. It may require some tweaking of the ViewEngine and Routing but I think it could be done.
maybe i am wrong but i seriously i don't like the current structure of MVC application, and i think on big projects it will cause trouble to maintain.
so is there a way to group related Controllers,Views, Models together, like if i have gallery Module i want all it's Controllers, Views, Models to be grouped under Gallery Folder.
Areas sound like what you are looking for. This will let you group controllers/views/etc. Unless I misunderstood the question?
Phil Haack discussed this here, it's the same issue I've faced and have yet to overcome correctly.
From the sound of it you're moving against the basic principals of MVC, that being the separation of Model, View and Controller rather than your desire to split at 90 degrees to that by using modules.
I'm not entirely sure what benefit you would get from splitting it in to modules any way since I would expect you to have one GalleryController. Where you are likely to have the most 'entities' needing grouping is with the views, possibly one or more for each GalleryController action, but they are in their own folder which gives the sort of functionality you are looking for anyway.
Finally there are the models. Obviously I don't know your project so I don't know how it is laid out, but the Models do not usually exist for the use of one Controller (or module in your case). For example - I have Models for Users, Companies, Vehicles, etc, etc. These models are a shared representation of my data structure and have nothing to do with modules as a user may see it looking at a web page. I can't split them in to modules because the whole point is that they are shared by the entire application.
So...in reality it is the Views which can get a bit messy, but they are already split in to folders based on their Controller. Having said that you can move them around a bit if that suits your needs better. For the rest of it there is no need, either because you shouldn't if you want to use 'proper' MVC (i.e. modular Models) or there's no need (i.e. only one Controller). And if your controller gets too big just create a separate module for any functionality in that you want to split out. I reckon that's as modular as you should ever need to get.
I found a relatively simple solution that uses IIS configuration to simulate areas. No extensions to the existing MVC framework are needed.
Create a new MVC project under your solution for each area you want in your site (ex. Root, Blog, Forum, App1, App2). If you need any common supporting code or a common model, put it in a seperate dll project that the MVC projects depend on.
In IIS, configure the site root to point at the root project directory. Create web applications under the site root that point to each of the sub-area project directories.
When configuring the route maps for each sub area, don't include the name of the application in the route. IIS seems to take care of this for you. (ex. "ShowPost/{postname}", not "/Blog/ShowPost/{postname}")
The benefit is that you can change the name of the web applications independent of the routing system, and each application believes it is running with the whole server to itself.
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)