I am looking to add multi-tenancy to an .net core MVC application i am developing.
My aim is to have a core project which contains the base features, including controllers, views, assets etc.
Then I would like to have a separate project per tenant which can override the defaults from the core project. At the moment i am trying to tackle the task of overriding controllers, not just at the controller level but the ability to override individual actions within a controller.
What are should i be looking to to do this, I was thinking about the IControllerFactory but not sure if this is the correct place in .net core?
I'm assuming there may be a away to achieve this with IoC but need pointing in the right direction.
Anyone have any thoughts on this?
This is the way I designed it on my current project, my requirement is slightly different to yours in that its multi-tenated but a tenant can operate in mutiple countries, the functionality is the same per tenant but different per country, the design below will hopefully give you a few ideas to help you on your way.
I treat the controllers as nothing more than a navigation mechanism, keep them thin and light. I have an area per country (in your scenario this could be an area per tenant)
Each areas controllers simply reference a base controller
The base controller is very light because we want be able to implement custom logic per country using our DI container. Lets run through the Edit scenario for a permit.
Intellisense playing up view shouldnt be red :)
Edit permit calls _editPermitManager which is of type IEditPermitManager injected into our controller. I have two implementations of this in the system one for New Zealand because its a special case and one all other countries use (but you could easily have an implementation per country).
I manage this injection with ninject
The flow is user navigates to /blah/NewZealand/Permit/Edit/4 clicks submit this is directed to Permit controller in NewZealand therefore ninjects injects the New Zealand edit manager and this is invoked on the edit flow, I also inject in a INavigationService (_navigationService.Route) enabling me to potentially direct to different views on a per country basis.
Hopefully that gives you a starting point.
Related
I have to set up a Asp.net demo using MVC 4 in a web application in order to help decision for a product that currently don't use this pattern. The model, view and controller should be simple, I just have two or three entities and a few pages.
I suppose I don't have to implement the whole infrastructure with services, repositories, etc. So how could I simplify the MVC components without loosing those advantages?
The MVC components aren't related to the data access strategy which you can use. To put together a quick demo (or a simple application) you can leave the data access in the same project but eventually split that out etc.
You can use something like AutoMapper to map from your entities to your view models if you want to put that level of abstraction in. You can also use EntityFramework contexts in the controllers to avoid additional levels of abstraction and only put in a simple interface/abstraction into one controller to show unit test ability.
Small examples of different patterns which could be used in the application is probably the way to go for the demo/presentation and not worry too much about putting them in all over the place. Remember the presentation and the delivery of information is as important, it not more, than the demo code itself.
I am interested in general approach for building interactive GUI using MVC3.
The idea is to build set of different components that can be integrated (plugged in) into various scenarios.
Each Component MUST have it's own model definition, controller and views.
Component encapsulates not just the view but also behavior through it's controller.
All internal implementation details, model, behavior, etc... must reside inside component,
so that component becomes independent, modular - black box.
This allows component to be changed without breaking anything in context in which component is used.
Context in which component runs must not make any assumptions about internal details of component implementation.
On the other side the component does not make any assumptions about context in which it will be used.
Finally, the component must provide mechanism to "communicate" or "interact" with outside world. Beside internals, component must provide some kind of "external" interface (like parameters, data, functions, events whatever...) which would allow component to be integrated into execution context.
The Context (or scenario) is part which contains components.
Now, the basic challenge for the context is to manage interaction between components.
Real-world Categories component example:
Component displays list of categories and allows user to perform various actions such as sorting, paging and record selection.
Internally, it has it's own model which stores relevant information like current page, sort, selection, etc...
Internally, it implements all required actions (for basic render, for user actions response, etc...) in it's own controller.
Internally, it handles model state persistence in the view and model state restore in it's own controller.
Real-world Products component example:
Component displays list of products and allows user to perform various actions such as sorting, paging and record selection.
Internally, it has it's own model which stores relevant information like current page, sort, selection, etc...
Internally, it implements all required actions (for basic render, for user actions response, etc...) in it's own controller.
Internally, it handles model state persistence in the view and model state restore in it's own controller.
Real-world Dashboard page (context, scenario) example:
Page displays both Categories and Products components.
Products component displays all products for the currently selected category and thus must provide external interface (parameter or something) to receive selected category identifier from the context.
Categories component must provide some kind of external interface so that context can act when selected category changes and provide selected category identifier for the products component.
Technically, communication approach for page updates would mostly go through AJAX but if this is possible without AJAX, it would be even better.
In the case of AJAX, I would like solution which uses server side controller(s) which decides and renders what should be updated on the client (JSON or something).
I would not like solution in the client script (client side "like" controller) which decides what actions to call and what parts of page to update - this as said in previous paragraph must be decided by controller(s) on the server.
Important: It is not necessarily for the components to work when directly called via some route.
How would you generally implement described system?
I think you need to investigate real projects and see, what approach do you need to use. Try following project and u can find many best practices:
Here u can find implementing of security measures, services, auth and many many useful.
Kigg
http://www.nopcommerce.com/downloads.aspx
http://orchard.codeplex.com/
It's hard to say for me how it's should be implemented. Better to code it. But using of Dependecy Injectction of Views, Controllers, Services, and Repositories are must in your case.
Each controller handles a whole user-machine pattern. That is, roughly, each controller is responsible for orchestrating the user-machine interaction for a user-case(the user-machine patterns that are the result of the analysys phase).
Now if you put "standard behaviours" in controllers who will coordinate the user-machine interaction pattern?
This way you will have "components" without something that coordinate their execution.
In web forms you have pages that coordinates the execution of components put in them...but in Mvc thi coordination role is played by the Controllers themselves.
You can do black-boxes composed of Controllers and Views just if each of them is responsible of a whole user-machine interaction pattern. That is a "Big Components" not a small building blocks, as its is the case when you implement a CMS.
The Orchard CMS use a similar approach. However what you call components are actually pre-defined blocks that play the role of whole sections of the websites being built by the user.
It seems to me that you are trying to achieve something which may not be out-of-the-box compatible with the philosophy of web MVC (other implementations of MVC might support it).
However, if you wanted to go to the trouble of writing a framework on top of ASP MVC, I am sure you could achieve what you want. For example, by using Areas, you could achieve a form of encapsulation of your controllers, view models, and views.
To compose different areas for the same master view, you could write the equivalent of a front controller with its own view that took in a view model - that view model would be primed by the front controller to render actions from the different areas.
You might achieve more mileage by using a client framework such as Backbone.js on top of ASP MVC.
I am a bit new to ASP.NET MVC and I have a bit of an ordeal. I am developing a website with several roles in it and of course the logic and gui that the user gets depends on the role (duh).
There are 10 separate roles in this application. They do share most of the same functionality but some screens will be different depending on which roles they are in.
Heres my question. All examples and tutorials I've read on the internet and the Apress book that I have been reading show an example how to implement roles with one role (Admin) in which the common way is to provide an Admin Controller (or even Admin area) for the authorized section of the site. However, what if there are 10 roles? Do I really need to code up 10 separate controllers?
Let me help the question by giving detail what is being developed. There will be a menu and the menu items will be filtered by role of what views(or pages) they can and cannot get.
The from what they select, it will provide them a restricted view(or authorized page) which from within will provide a plethora of functionality limited to just that role.
I know there are several different ways to do this, I just want to know what is the recommended or "clean" way.
Have any of you been in this situation and if so, how did you organize the logic for multiple roles? Separate all roles to separate controllers? Have few controllers but just apply authorize filtering on the action methods? Apply the role filtering within the views or partial views and leave the controllers alone?
Unfortunately there are little resources for how to implement several roles out there, I just want to know how to do it the "correct" way in terms of separating the logic.
I would put the pieces of functionality into partial views. Have one controller per piece of website and load partial views based on the role and what should be exposed.
I would only stray from that if you have an excessive amount of differences, like an administrator would possible have. Then I typically make an area to encapsulate that functionality.
Regardless of the controller separation I would definitely use partial views to minimize duplication of similar code. You will reap the benefits when you need to maintain that code.
Use Authorize on the action methods and apply the roles allowed for the operation.
Depending on what's appropriate for the scenario, build a list of available actions from the controller and send that to the view as part of the view model. In some cases its more appropriate to send a simpler view model that tells the view whether each operation is allowed i.e. CanDelete, CanEdit, CanViewDetailedInfo etc.
I'd start with that, and depending on the actual complexity re-factor to any combination of:
An ActionFilter that populates the available actions / instead of explicitly doing it in the controller
Use reflector to look for the list of roles applied in authorize / so you only specify roles once
Your own html helpers that take authorization into account. So when you declare an action link, its only output when the action is supported.
If my site has several user roles say Admin, User, Manager and there are several modules of functionality that may be used by one particular user or by all users how should I go about naming my controllers?
Is it OK to have role based controllers such as an Admin, User and Manager controller as well as controllers for shared functionality such as Products controller?
And for small parts of functionality that is used by only one user role can I keep that inside the user based controller e.g. having all the add/remove/update functionality for product categories can I have that inside the Admin controller or should it have its own controller even though it will only be a few lines of code?
When searching the net for conventions on doing this I am only provided with ways to name the actual file and other sources only explain the controller functionality and not what should and should not be a controller.
If this is subjective I am also happy to take that as an answer, but as it currently stands I am unsure of what is acceptable and whether or not role based controllers are acceptable in the MVC framework.
Personally, I have upgraded my ASP.NET MVC project to version 2-beta release 2 and moved admin related stuff to different area.
This way you can keep your controller names related to their function but run them from dedicated area.
We're building about 10 ASP.NET MVC sites which have a common set of features (and corresponding URLs, Routes, Controllers, Actions, and Views). The sites will also all share a base set of domain objects (e.g. users, companies) and base attributes on those objects (e.g. name, address, etc.).
But each site will also be highly customized and extended from the base. For example, our site for large, public companies will have "Subsidiary" and "Stock Symbol" fields on the Company domain object, while our site for startups will have a "Venture Firm" and and "Funding" attributes. Look and feel will also vary considerably, although we're trying to keep HTML as consistent as possible (modulo extra form fields for extra domain object attributes, etc.). We'll also be overriding images sparingly, so we can, for example, re-use the same button graphics across sites.
Anyway, we're trying to figure out how best to factor and architect things so that we can reuse as much code and as many tests as possible without limiting our freedom to add per-app attributes and vary the UI between apps.
I'm familiar with how to handle limited-customization multi-tenancy like you find in StackOverflow/SuperUser/ServerFault (or MSDN/TechNet for that matter), where the UI is a little different and the data model is more-or-less identical. But when the models and UI are very different (but inherit from a common base), I'm less sure how to proceed.
I'm less worried about operational issues, since we'll probably be running each site in a separate appdomain and hosting them on separate databases. I'm more worried about reducing long-term code maintenance costs, increasing agility (e.g. easy to add new features to the base without breaking derived apps), and realizing short-term dev-/test-cost savings as we build our 2nd, 3rd, 4th, etc. site.
I'm looking both for high-level guidance and suggestions, but also concrete suggestions for how to make that guidance real using modern ASP.NET MVC practices.
I realize this is a very general question, but for starters I'm looking for both high-level guidance as well as concrete tips-n-tricks for how to apply that guidance with ASP.NET MVC, including things like:
recommendations where to split base/derived across Visual Studio projects
source control tips to avoid forking
database schema tips (FWIW, our databases are all small-- under 10K rows per table, so dev/test cost is more of an issue than DB perf)
tips about re-using Controllers/Views/etc. corresponding to the "base" model attributes, especially re-using UI for things like "new customer" forms which will have a mix of base and derived attributes.
Anyone have good advice for how to architect a multi-tenant app like this?
Here's what we do, and it works pretty well for about 8 sites currently.
Define a core MVC project for your Controllers, ViewModels, HttpApplication, routes, etc. This will compile into a DLL and compromise the bulk of your site.
Create a basic set of default views, scripts, images, etc. for your site. These will server as defaults for your individual sites.
Per client, create any custom controllers, routes, etc that you'll need in a project that compiles to another dll.
Also per client, recreate any views, scripts, images that you'll want to use.
To make the above steps work together you'll need to write a little glue. The first piece of glue is a custom view engine. You'll want to customize the standard view engine to first look for views in your client-specific folder, and then the default folder. This lets you easily override the default layout per client.
The second method of getting everything working is to have your core application load the routes, controllers, etc from your client specific assembly. To do this I use the Managed Extensibility Framework (MEF) to expose a single Register method. Calling this method on my client assembly code registers the routes and any other client-specific needs.
Here's a general view of what my site folder structure looks like, with SiteContent being checked for views first:
- AppContent
- AppContent/Static
- AppContent/Static/Images
- AppContent/Static/Scripts
- AppContent/Static/Styles
- AppContent/Views
- AppContent/Views/Shared
- SiteContent
- SiteContent/Static
- SiteContent/Static/Images
- SiteContent/Static/Scripts
- SiteContent/Static/Styles
- SiteContent/Views
- SiteContent/Views/Shared
- web.config
- Global.asax
I have helpers that I can use like SiteImage and AppImage for use in my views. Also, I make each of my client sites use certain specific names for their master pages, that I don't ever define in my AppContent defaults.
I realize this is a rough overview, but it is working well enough for us right now.
I'm involved in a similar type of "suite" of projects currently which is focused on allowing customers to apply for products online but have very similar requirements for what information to collect, where the only differences are around product specific pieces of information or slightly different legislative requirements.
One thing that we have tried to do is create pages (model, view and controller combinations) that are reusable in themselves, so any application can use the page to capture information but redirect to the next page which may be different depending on what type of product is being applied for. To achieve this we are using abstract base controllers in the form of the template method pattern that contain basically all the required controller logic (including action methods with their applied action filters) but then use abstract methods to do the specific stuff such as redirecting to the next page in the process. This means that the concrete implementation of the controller used by specific application page flows may contain only one method which returns a RedirectToActionResult corresponding to the next page in the flow.
There is also quite a bit of other stuff that handles going backwards and those kinds of navigational things, but with the help of action filters you can get it set up that you don't have to worry about it once you get it up and working.
There are also base model objects which contains common functionality, be it validation logic or state persistence logic.
The data captured during the application process is persisted in database as xml serialized model objects which can then be pulled out and de-serialised once the application is completed and spat out in whatever format to whatever system the backend operations staff use to process applications.
The implications of this is that we have a project structure that consists of a base dll that contains top level abstract classes, interfaces and utility classes as well as html helpers, action filters etc. Then we have mvc projects which contain the concrete implementations of the base controllers, models etc as well as the views and masterpages.
The hardest thing is sharing views and I don't think we have properly got this sorted yet. Although with MVC 2.0 containing Areas I think this will become less of an issue but I haven't had a good play with it yet. (see Scott Gu's post on 2.0: http://weblogs.asp.net/scottgu/archive/2009/07/31/asp-net-mvc-v2-preview-1-released.aspx)
One thing I have POCed that looks like it will work is using a base MVC project to contain common views and then extending the default view engine to search that project on the web server when looking for a view to render (which is quite easy to do). Areas though is a far nicer solution.
As for source control, we are using svn and I think you are reasonable in being concerned about branches. It is not something that we have had to deal with yet, but we are probably going to go with git as it seems to make the process of branching and merging much less painful.
Not sure whether this helps you much but I would definitely recommend keep in mind abstract controllers and models, and also look at how you can use html helpers and and partial views to group similar pieces of functionality.
Mike Hadlow goes into good detail on how to accomplish this:
http://mikehadlow.blogspot.com/2008/11/multi-tenancy-part-1-strategy.html
One way to do this is to use branching in a source control system.
The main branch is for the common functionality. You then have a branch for customization and can merge changes out to the customization or back to the main branch.