I have an app that I need to white-label and deploy for a client. The functionality will be identical, all the pages will be nearly identical. The only real difference will the missing logo/styling and the use of a SSO-like system instead of regular forms auth. The authentication part is no problem, as that can just be injected. But what's the best way for me to do different master pages / config files by site?
'Best' means least likely to cause problems and maintenance headaches. Attributes that would be good: quick/easy to implement, quick/easy to maintain.
You could write your own view engine in ASP.NET which loads a different theme depending on the customer that logs in.
This way you can load different cascading style sheets, master pages, views....etc.
About a year ago I wrote a post on this:
https://github.com/geersch/ThemedViewEngine
Related
VS2013 update 4, MVC5
Still relatively new to MVC. To divide functional domains within an MVC project the use of Areas seems clear from these posts (olderSOlink, newerMVC5link).
Is there ever a reason that sub-domains would be integrated as part of a solution involving different functional domains of a given MVC project? I don't have a reason to want to make use of sub-domains, I'm just asking because I don't know if there is some advantage I should know about.
Is it even possible without great difficulty? For example, can logons transfer across sub-domains? Would there be other difficult issues to address?
At present the project I am building is 'relatively' small and will have around 5 major domains so I'm assuming Areas is the best architecture to isolate these domains, but I wanted to ask for guidance before I go too far and make decisions that would make the use of sub-domains difficult in the event there is a compelling reason to use them in a single MVC project.
I generally use subdomains to separate major application functionality or if I have multiple servers that I want to be on the same domain name.
To answer your login question, if you are using the same application you will remain logged in on the whole domain (depending on your method of using sessions, the cookie will be accessible to the domain as a whole).
If you are questioning using subdomains, they are really just a naming scheme so you could categorize your 5 major applications into one domain with different paths (eg. /portal, /store, /etc..) then later you could point store.domain.com -> domain.com/store. So it's pretty flexible in the end.
I'm building a new SAAS application and was looking for some advice on the most appropriate framework to use. I realize that no single framework will likely be able to do all this, but I thought I'd ask the community and try to find one that solves the hardest problems.
Requirements
Single code source. (each customer will have either a subdomain, or a distinct domain, but everyone should be running off the same code base and same servers)
Should be able to update the programming source once and have all the tenants pick it up
Session information should either be kept in a cached store, or just in cookies (no shared state)
Multi-tenant database functionality built in. (Based on the domain used to reach the application, the framework should automatically use the database connection information assigned to that domain)
Each customer/domain may have their own template for the web pages. Templates need to be assignable on a per-customer basis and kept outside the application code
Security and rapid prototyping is more important than speed
There will be a lot of CRUD type screens, so simple built in functionality for this is desired
I have pretty lengthy Java and PHP experience, but would only consider PHP as a last resort for this. My Scala, Python and Ruby experience is a bit rustier, but I would not mind coming up to speed if they offer a significant advantage. I've looked at the Play! Framework and like it (fulfills #1, #2,#6 very well), but the multi-tenant aspects are not very strong. I've done several projects using Grails and it handles everything except #3 and #5, and can be hacked to do the rest.
I would say that the third point is rather independent of grails/play/whatever in general. If you need a shared cache there is a multitude of providers for this and there are plugins for most of them in Grails.
The multi-tenancy in grails is pretty mature and much less intrusive than the solution from the blogpost in Sebastiens answer. Whether or not you use single tenancy (multiple databases) or multi tenancy is more or less transparent to your code and most of the headaches are abstracted away. Do be aware that you need to do some smart indexing (like including the tenant id in a multi column index etc) to not get very sad speeds when your data starts to grow.
As for externalized views, you can either slap them in the database or symlink them into your webapp and just keep them in separate numbered folders. Then from the tenant plugin, you can use TenantUtils.getCurrentTenant() and simply render from the appropiate folder "/" + (tenantID ?: "default") + "/whatever/view/path". This way, layouts etc can be shared across tenants if you so please and you simply put tenant specific stuff in the tenant specific folders.
You can probably do this in play too, or , but I don't see anything hindering you from doing this just fine in Grails.
My $0.02 on this question.
Actually Play! fits well to what you'r looking for.
Read this post:
http://www.lunatech-research.com/archives/2011/03/04/play-framework-writing-multitenancy-application-hibernate-filters
It works great. You can even make this filter work so that you can expose the crud module to customers and they'll only get their own data...
For very large applications, sharding seems not supported yet (no hibernate shards handled yet i think).
There's a multidb plugin to work with multiple db, but it seems not working very well yet...
I've heard that Grails' Multi-Tenant plugin offers some good tooling for several different methods of multi-tenancy.
"Each customer/domain may have their own template for the web pages.
Templates need to be assignable on a per-customer basis and kept
outside the application code"
I assume you mean they each have their own layout/skin. There are several techniques to execute this:
You could manually assign layouts based on tenant. <meta name="layout" content="${tenantName}/main" />
Write your own tenancy aware LayoutDecoratorMapper and override the default GrailsLayoutDecoratorMapper in sitemesh.xml
Figure out how to override and enhance Some internal tools dynamically resolve views(per tenant) or resources (GrailsViewResolver, GrailsConventionGroovyPageLocator, GrailsResourceLoader, etc.)
In PHP you can use Innomatic Platform for building multi-tenant (isolated databases) applications:
http://www.innomatic.org
My group is working on a new web application and is considering using MVC. However, there are members who would rather include pages than use master pages. Is this possible to do in ASP.NET MVC? In the small amount of time that I've poked around with MVC I have not yet been able to figure out how one might accomplish that.
Why the preference?
Having used both in the past, Master Pages are much easier to use. You just have to get over the (very small) learning curve.
ASP.NET MVC doesn't force you to do either one though...
If you like the Include method, then you would probably feel most comfortable using Partial Views to provide the same functionality. You would just add the Partial Views to each page instead of including another page.
No. It does not force you in any way.
You should really avoid server-side includes with anything newer than classic ASP. They're more difficult to debug, IIS has a hard time finding correct line numbers when there's a problem, etc. Also, I haven't looked at the order in which SSIs are processed in the request pipeline - they may not work at all with ASP.NET.
If you're moving into MVC, use RenderPartial() or RenderAction() instead. These perform essentially the same function as a server-side include, but are more inline with the spirit of the framework and provide some additional benefits, like passing models without having to declare a global variable (which should also be avoided, and I'm not sure if it is even possible under .NET scope rules).
And, no, master pages are not required, but you really should use them. Using includes to build your page layout works, but only if you don't and won't need to radically change the layout of your site at any point in the future. I'm in that boat now with a 350k line classic ASP app which used very nicely structured code and #includes to create the page layout. That was the best solution available at the time, but it's causing me a lot of headaches now (10+ years later).
With a master page you can move your ContentPlaceHolder blocks anywhere you want, whereas with #includes the final page really determines the format by the order in which the includes are placed. This also makes it pretty straightforward to create a mobile version of your site - you can create a mobile-specific master page and use the same content views.
Its a matter of choice,but for consistent look and feel across the web application, master pages give you just that. You have to take the team through the learning curve of good master page design, not only would it be useful for the current project at hand but also future projects. Good luck!
I would rather opt to go for Master pages due to the ease of use and built in support in MVC for this.
If you want to know more about it check out this tutorial: Creating Page Layouts with View Master Pages.
Grz, Kris.
This is a ASP.NET MVC beginner question (I'm in phase of developing NerdDinner)... I have assignment to create ASP.NET MVC cms (with its own design) and portal (also with its own design) that will display data that's being handled by CMS. I was wondering if I will have to make two individual projects in Visual Studio or I will have to use one project and place portal section in specific folder.
I know that my question is a bit premature (according to fact that I still haven't finished tutorial) but I'm bit impatient :)
On server (commercial hosting) I would use only one hosting account... this thing with URL routing is a bit confusing to me, CMS is practically also optimized for SEO.
I would like to the structure of URL to be:
---- PORTAL ----
www.domain.com
www.domain.com/Menu1/Submenu1
www.domain.com/Menu2/Submenu1/SubSubmenu1...
etc.
---- CMS ----
www.domain.com/CMS
www.domain.com/CMS/Whatever
Thanks,
Ile
It all depends on the functionality of the portal and the MVC cms.
For starters I would have a separate solution for the Model/Data Access that way you can have as many MVC projects without duplicating your data access.
From your desired url structure I would probably have the CMS as a separate controller and sub folder. Alternatively if your using MVC 2 you could look at the areas support which will probably give you a little more flexibility.
If you want the solution to be a bit more complex/flexible you have a number of options:
If both the portal and MVC cms are going to have he same functionality and page layout you have two master pages and determine which mater page to show when returning the view. You would specify this in the routing so multiple routes would point to different controllers.
If the layout/functionality differs slightly but one controller can still manage both you could have a separate controller project and two mvc projects which only contains the views, javascript and images so both mvc solutions look at your controller solution. With this option you would probable end up setting up two websites on your domain one under the root and the other under the CMS folder (in your MVC app you will prob need to block routes to /CMS so it will be processed by your CMS app).
Finally if both differ hugely have two separate projects but keep your common data access project, as above you may need to set up two sites on your hosting package.
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.