I am using ASP.NET MVC and have to develop and deploy multiple websites based on a first website.
There are variation in some controllers, some views, some scripts and some models, and the Database are different on each website (mainly columns are differents but table names remains the same).
Is there a way to handle such a thing in a single Visual Studio Project, in order to make maintaining easier, and be able to add common feature easily on every website ?
Currently, I copy the pilote project into a new VS project, and change all the variation. But I find it's not an ideal situation (because of maintaining/improving).
I have implemented something like that years ago and can give some general advice you might find useful.
First of all developing app with such "multitenancy" has nothing to do with MVC pattern itself. You can do that without MVC :D. Second, if the websites supposed to work with different business domains I am afraid there is no generic way to do what you want. In my case it was just a number of e-commerce platforms.
Anyway, consider next things.
1.Think about using sub-domain approach if you can. It will free you from stupid routing and cookies shenanigans. Basically you can map *.yourdomain.com to one app and handle the necessary logic related to tenant easily. So in my case it was an application that behaved differently depending on provided url, not route, but sub-domain, 'superclient.yourdomain.com' for example. Its not always possible or good idea, but think about it.
2.Dependency Injection everywhere. Well, its useful in general but in your case is absolute must have - try abstract any tenant specific logic in separate types and init them in one place. Its everything related to localization, timezone settings, app theme, branding info on the app header etc. Just initialize and inject where its needed. If you have something like
if (website1) {
showBlockOne();
} else if (website2) {
showBlockTwo();
} else if (website3) {
showBlockThree();
}
then you doing something wrong, its a road to insanity. It should be something like
_currentTenantViewContext.ShowBlock();
So its polymorphism over conditional operators in most cases.
3.In my case the requirement was to create an app which can work with any language so I had to handle that issue on database side as well. The problem is that if usually you have lets say for example ProductType table in database with Id and Name, in multitenant application its not that simple. My solution was to create two tables - ProductType with Id and Code fields and ProductTypeLocalization table with Id, ProductTypeId, LanguageId, Value fields to handle this problem. Requirement also was to make this values editable from admin panel...
I don't know is it the case for you, but if yes think about it before the shit hits the fan in future.
4.For situations where you need some specific fields in some database table only for one site its not a good idea to spawn them freely (in general). Consider using some generic format for that, like JSON or XML. If you have few additional text fields for specific website in some table just create one field (call it ExtraSettings or something) and store this strings as JSON in that one field. Of course you have to handle this data in separate way, but its about dependency injection again.
Also you can use NoSQL for that.
5.Provide feature toggling, different websites requires different blocks to be displayed, rules applied etc. You have to have some way to on/off them for particular website(tenant) without recompile/redeploy.
Hope it helps.
I'm working on a pretty big project, which have insane ammount of methods in each controller. Same with Views, one folder contains about 150 .cshtml files, what makes this hard to explore. I wanted to create separate folder for each part of window, but that changes my routing adress from ./Tavern/Shop to /Views/Tavern/Tavern/Shop. Tavern controller have 3000+ lines of code, and even with (Ctrl+F) its hard to find and edit some functionality.
Any ideas how can i improve this without changing many files in solution?
It is hard to help without viewing your code but these should be your guidelines:
Controllers should be as 'skinny' as possible, all the code should be done in your BL layer. (external lib)
Controller should be very specific - i.e. product, contact, home, etc...
The routing is done via the controller, and not the location of the view - you can specify on your return View("~/AnyPath/GoesHere/AndTheRouting/IsTheSame.cshtml") (it will be controller/action) (or however you defined it in the routing.config)
You can consider working with Areas.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I'm developing an app and I am pondering over something. So I figured I would ask here for people with experience to tell me what they think about it.
So I have this controller (Store controller) which is huge and has a lots of methods, Get and Post actions, and so on in it. It works fine, but I'm still in development stage.
I am wondering what would be the best practice: to have this controller which holds so many methods and actions, or splitting the methods to many controllers? Is it ideal to have one controller deal with almost all of the methods, or many controllers?
And before you ask, yes, everything in my store controller is "store related". But in my store I have items, packages, and so on.
Edit
Thanks everyone! Following your advice, I have broken my huge Store controller into smaller controllers: one for the Items, one for the Packs, and so on. This indeed made the code more readable. Also, a lot of comments provided will put me on track for upgrade, so thanks a lot!
It is definitely better to divide all your controller's actions into some logical packages - so to move them to separate controllers. Thanks to this it all becomes much more readable and intuitive for you also for other developers who will work on the project.
The question is: how to divide it?
There are in fact a few criterias that can influence such a decision for e.g.:
A controller should be connected with a certain set of logically connected pages. So for e.g. in case of an e-commerce platform you would probably have a CheckoutController, ProductController, UserAccountController etc.
You should also take into account which business concepts should be taken into account. In your case you have a concept Store, but as you are probably aware of this that it is a very broad concept in itself. So instead you should probably distinguish some more details in the business concepts.
A quite common approach is to divide controllers by CRUDs, although it is not always applicable.
On the other hand your controllers should not be too granulated - so you should not exaggerate with it.
Please remember that ASP.NET MVC uses CoC (Convention over Configuration) approach which is also applicable to controllers and views naming conventions and the way they are grouped and placed in appropriate directories. When dividing your controller you should take this into account.
You should have a controller per discrete unit you're working with. So, if your controller manages multiple entities, then yes, I'd say it's time to break it out. However, length of the controller, otherwise, makes no difference.
Now, the only problem you'll have using separate controllers is your routes, but that can be easily fixed by either of the following:
Use Areas. Areas allow you to sort of create a sub-MVC project. It'll give you Controller, Model, and View directories all under a new prefix. So, if you had a controller named ItemsController in your Store Area, the default route would end up being Store/Items. However, C# developers have very mixed feelings regarding Areas: some love them, some hate them with a burning passion.
Use Attribute Routing. MVC 5 has a new feature called attribute routing. This allows you to specify the route directly on your controller and its actions instead of relying on the default route or adding tons of custom routes to your route config. So, you could then easily have as many controllers as you want and specify that they should all be prefixed with "store" in the URL. As long as there's no conflict in the rest of the URL, you'll be fine. If you aren't working with an MVC 5 project and don't want to upgrade, there's also a Nuget package called AttributeRouting that offers these features (and actually more). For what it's worth, the author of that package is also the author of attribute routing in MVC 5.
I prefer multiple controllers than a single controller with many actions. I would do it this way - Let a BaseStoreController derive from Controller, this controller is going to have the common functionality and properties. Then have StorePackageController, StoreItemsController etc be derived from BaseStoreController.
And inside each controller I will have corresponding Actions related to packages, items etc. Inside each action I will make sure I will use Command Pattern and Facade pattern to ensure proper code separation.
The standard way I approach it is to have one controller per menu option
For example, say you have a site with the menu options
Home, Products, Blog, FAQ etc
I would have a HomeController, ProductContsController, BlogController and FAQController
You could also potentially create one or two generic controllers that handle shared actions used by several sections of your website and a base controller than handles generic tasks such as tracking and logging page visits.
One other thing to be aware of is SSL, especially if you decide to do some shared controllers actions or decorate an entire controller (For example shoppingcart etc) with SSL
If your methods are truly "Store" related and bind your model to the View, then that's one thing. But if some of your "Store" methods are essentially helper classes, that is, methods that don't directly interact with your view but do serve a purpose when working with your Store model, then create a separate "Store" helper class and place this in, for example, a "HelperClasses" folder in your root. In my opinion, and I'm sure opinions of others, you want to try to only keep methods in your controller that directly tie into the model (the Store model) that your View renders and works with. This encourages "separation of concerns". If your Store methods don't do that, send them to a helper class. Basically - your controller acts as the middle man when rendering your model to the view. It helps control the process, so every method in your Store controller should really have something to do with how your controller sends your model to the View. Hope that makes sense.
And as Chris Pratt mentioned, if your controller manages multiple objects, then yes separate them into separate controllers, OR, create a ViewModel to handle the multiple objects, but from what you said, I don't think this is the case because you mentioned everything in your Store controller is "Store" related.
you might consider using a partial controller and split methods by logical meanings.
public partial class StoreController: Controller
{
public ActionResult Index()
{
return View();
}
}
in in some other .cs or .vb file:
public partial class StoreController
{
public ActionResult Show()
{
return View();
}
}
take a look at: http://msdn.microsoft.com/en-us/library/wa80x488.aspx
The problem seems rather simple... I'm sure thousands of people have already figured this out, so maybe I'm overthinking it. How can I hide or show a link in my navigation bar based on the user's permission level? I am using custom roles (not MVCs) and storing that information in a database. The effect I want is pretty simple
_Layout.cshtml
...
#if(user.IsAdmin)
show link
...
There are several solutions to this I've found on the web and here on SO, but most seem to violate the MVC constructs.
Most of the solutions I found involved probing for data from within the view, which I'm pretty sure is bad practice. Other solutions involve utilizing the session variables from within the view to decide what is shown and what isn't. Isn't this also against best practices as views should not be able to decide on content?
The only "pure MVC" way I can think of doing this is to incorporate the value of IsAdmin into each of my view models, which seems like more hassle than it's worth. I suppose it's also possible to create a javacript solution where I use AJAX to figure out the admin status, then have it inject an html element into my navigation bar.
What is the proper way to handle this? Am I simply misunderstanding the best practices?
Maybe use a partial view within the layout? Something like this:
#Html.Partial(actionName: "NavigationLinks", controllerName: "Navigation")
That way, you can preserve the MVC conventions: the view can be stand-alone, and the navigation controller injects the model (whether from session data, or wherever).
We are in the process of moving our application to .NET. One of the main goals is to allow modifications to the application, per client, but not to the source code. We resolved this in the core framework by programming to interfaces and using a Dependency Resolver (having an option to override the base registration) and MEF.
Now when it comes to views (the UI the client sees) the templates seem static and if the client wants to add a new field to the screen it seems they would need to modify the view itself.
The only two things that I can think of is modifying the search path of viewengine. This would allow a copy of the base and changes to it would be picked up. Not really liking this as it's a copy of the code.
The other way, what we are doing now, is that we create a class that is a container to other objects that output HTML. Basically we have a PageObject, LabelObject, InputObject..ect that we can call render on and output HTML. Since they are classes we can use the same methodology as for the rest of the application of giving slice in points. Going this route we really are not using the viewengine for rendering but just for combining all the partial views. Seems kind of clunky.
Is there a different way to accomplish this goal or a different viewengine that I can use to meet the goal of allowing customization for clients without touching the base view? I know HTML is not an object but seems there has to be something in between ASP.NET WebForms and ASP.NET MVC when dealing with HTML and allowing for customizations.
I would create a strongly typed partial view or template (DisplayTemplate or EditorTemplate based on requirements) whose #model is a collection of things that are rendered as inputs and labels. Allow the client to add/remove items from the persisted collection (i.e. in a database) and your problem is solved using the built in ViewEngine.