ASP.NET MVC Patterns for Multiple Tenants and Plugins? - asp.net-mvc

I am trying to understand how I can create an ASP.NET MVC site that exists as a VS2010 project in a solution, and then for multiple "tenants" I would create a site that inherits from that one. That would give the flexibility of adding modular features to one without affecting another one, and both could benefit from core library optimizations.
Is that a crazy idea? What patterns exist for that kind of thing? I have done something similar for a webform-based site (adding DLLS as plugins), but not in MVC.
A "tenant" is a business client. Each already has their own MSSQL database and seperate processing around them, each client is in its own silo. The databases are similar with a few features added here and there, they are versioned and deployed seperately, that whole process works well. A client has n logons. I want to develop a single "base site" that can then be used to give function to a tenant, and all activities are segerated for a tenant to a single database. Where things get ugly is how I can add a new component (say a forum) to one tenant site without mucking up the site experience for other tenants.
All ideas appreciated. Thanks.

I have worked extensively on the development of a multi-tenant web application. Here are three basic pointers to help you get started:
Security
The TenantId is part of the login credentials. These are stored in the Thread.CurrentPrincipal. This effectively binds each request (thread) to a specific user and thus tenant. Thread.CurrentPrincipal can be easily accessed from any code.
Database
We used a single database to store all data. A separation was made between tables (entities) that were specific for one tenant (multi-tenant), and tables that were not (cross-tenant). Tables that were multi-tenant had a column called 'TenantId'. In our entity model, we made sure these entities inherited from a special IMultiTenant interface. This interface contained the C# equivalent of the TenantId field. We extended the architecture of Entity Framework to provide default filtering on TenantId for multi-tenant entities. This ensured that one tenant could never access or modify the data of another tenant.
Plugins
We used a bit of Dependency Injection trickery in order to support the implementation of tenant specific code. Based on the current TenantId, our DI container injects a tenant-specific implementation of that interface.

Related

How to use Identity membership with existing database (n-tier)

I've been reading various other questions about using asp.net-identity but I don't see anything concrete with regards to using it with an existing database when the project is developed in tiers. For argument's sake, say the following is true:
Solution
WebUI
Services
UserService
Data
MyDbContext
Core
User
How can I specify User (from the Core project) to be the IUserStore for the new identity provider? Am I missing something, or does this all assume that the website and the membership database always reside in the same project(or there are strict references to the Microsoft.AspNet.Identity.* libraries wherever the models reside)?
Setting up a DbContext at the WebUI layer just for authentication (and tie it in to the "MyDbContext" with a service) seems hacky. Am i missing something, or was the team just planning on this being only used in simple applications?
And feedback would be appreciated.
More Information
if it's worth mentioning:
This would be a completely new solution; I do not have old/existing aspnet_* or webpages_* tables to worry about. I'm trying to take various other custom solutions and tie them in to one solid solution, so I'm open to a lot of options. However, I would like to keep things broken out by layer (if at all possible).
Asp.net Identity Framework is set of components helping application to work with User Identity. Core framework blocks are in Microsoft.AspNet.Identity.Core assembly. The second Microsoft.AspNet.Identity.EntityFramework is the data persistence implementation for the Core framework.
Now for the n-tier application, you can define your AppUser model in any project/assembly. You need to inherit it from the Microsoft.AspNet.Identity.EntityFramework.IdentityUser. So based on your approach, you need to reference particular assembly.
Same is for the MyDbContext. You must inherit from the currently only available Persistence Microsoft.AspNet.Identity.EntityFramework.IdentityDbContext<TUser>. Your MyDbContext can be in other project/assembly. You need to refer to your AppUser assembly too in this project/assembly.

MVC Simple Membership Web Site Administration Tool

I must have missed this somewhere (or slept through the class)... the standard ASP security tool for managing users and roles seems to be absent when using the new simple security version. That is, the original is there and working, just points to traditional ASP security... NOT to the new "simple" system.
In my project I can log in, I can look at the webpages_ tables but can find no method of accessing them in my project... I would be happy to manage roles and get the USERID and maybe ROLEID so I could tie the user to other functions in my project.
I've looked through hundreds of posts and articles... normally I find I am missing some minor config entry or something but this time I am a little more stuck.
Advice is appreciated.
Thanks!
SimpleMembership does not work with the Web Site Administration Tool (WSAT). There is a good overview of SimpleMembership in this blog. Here is a quote from it.
WSAT is built to work with ASP.NET Membership, and is not compatible with Simple Membership. There are two main options there:
Use the WebSecurity and OAuthWebSecurity API to manage the users and
roles.
Create a web admin using the above APIs.
Since SimpleMembership
runs on top of your database, you can update your users as you would
any other data - via EF or even in direct database edits (in
development, of course)
I would also add that you can seed some of this information at application start-up, such as what roles are available, as shown in this article.

Umbraco 5 how to get all roles and users

I want to get all the membership roles in the system and all the members in the system.
I've tried using
System.Web.Security.Roles.GetAllRoles();
System.Web.Security.Roles.GetUsersInRoles(roles[0]);
and a couple of others, but they all throw the not implemented error.
I'm using a clean VisualStudio Umbraco template of V5.1 running locally on IIS Express and SQL Express.
Any thoughts would be much appreciated.
I noted that the provider was not queried in populating the role listing from the backoffice and came to the conclusion that not only was getallroles not called, it was never implemented.
Instead, the hive is queried for the list of roles.
Despite the claim that membership services was baked-in again starting with 5.1, it comes with some particularly serious limitations.
If you're committed to 5.1 and you need a custom roleprovider, then you'll need to come up with a solution that occasionally syncs roles to Umbraco.
If you don't need a custom roleprovider, then you can query the hive to pull the related content. The special urls are:
security://profiles
Used to store profile data by the Hive Membership Wrapper. Profile data is additional data for any member/user that cannot be stored in the ASP.Net MembershipProvider
security://user-groups
Used to store the data for back office user groups/roles.
security://member-groups
Used to store the data for members' groups/roles.
security://member-types
Used to store the schema data for member types
security://membership-data
Used by the UmbracoMembershipProvider to store the ASP.Net MembershipProvider information
security://users
Used to query the Hive membership provider wrapper for back office users
security://members
Used to query the Hive membership provider wrapper for Umbraco members
Finally, be aware that membership services are now abstracted. There's a completely new separate interface for Umbraco's take on membership.
Rather than using the 'baseline' .net membership provider and role provider, you use the membership service available in your current IRoutableRequestContext:
e.g. rather than using Membership.ValidateUser(), you would use _context.Application.Security.Members.Validate() which wraps the supplied MembershipProvider.
Good luck, and post any findings of your own as the community trudges through this release together.
EDIT: An example for getting a list of the member roles
using (var securityUow = context.Application.Hive.OpenReader<ISecurityStore>())
{
return securityUow.Repositories.GetEntityByRelationType<UserGroup>
(
FixedRelationTypes.DefaultRelationType,
Umbraco.Framework.Security.Model.FixedHiveIds.MemberGroupVirtualRoot
).OrderBy(x => x.Name).ToList();
}

Where is the best place to put validation logic given this application design?

Consider an ASP.NET MVC 2 web application project that uses EF4 POCO entities and the repository pattern to store information in a SQL Server database. So far there are 3 projects, 4 if you count the database:
1.) Domain.dll, has no dependencies, exposes POCO's and repository interfaces.
2.) Storage.dll, depends on Domain, implements repository interfaces (using EF 4).
3.) Mvc.dll, depends on both #1 and #2, provides UI layer.
4.) SQL Server database + connection, dll agnostic (no dependencies).
Let's say I add another web application to host a WCF Data Service, which provides an OData feed of the database using Domain.dll and Storage.dll:
5.) Provider.dll, depends on Domain & Storage, provides OData service layer.
Where does the domain validation logic belong in this solution? If the domain POCO classes are decorated with validation attributes, does the WCF data service need anything else to protect the data? Is it ever a good/bad idea to put validation logic into stored procedures, and why?
I would say put DataAttributes on the Domain and use the validation in MVC for the MVC part and use Ent Lib to do the validation in the WCF Service. Alternatively you could use the Ent Live validation in both MVC and WCF, but thats not what this is about. I dont know that this needs to come down to DDD semantics. MVC does validation on the Models when they have DataAttributes, so follow that and do the same in WCF.
I marked this as subjective and argumentative because even the DDD community can't make up its mind about this.
How many layers do you need to change if a new validation requirement for Customer.LastName comes in? Can the UI layer inform the user the domain, wcf, web, database layers have rejected their commands? How is a LastName restriction that a LastName can't exceed 50 characters part of the business domain?
You can see that this is really a discussion and not a answerable question.
Also if your using OData as a Database feed for your services you are not using DDD. You are using Persistance-As-Model or DDD-Lite. This is actually harmful and results in questions like this that try to resolve the problems with using two incompatible patterns together.

Adopting the "aspnet_ ..." sql tables from ASP.NET MVC

I'm just starting a new project on ASP.NET MVC and this will be the first project actually using this technology. As I created my new project with Visual Studio 2010, it created to my sql server a bunch of tables with "aspnet_" prefix. Part of them deal with the built-in user accounts and permission support.
Now, I want to keep some specific information about my users. My question is "Is it a good practice changing the structure of this aspnet_ tables, to meet my needs about user account's information?".
And as i suppose the answer is "No." (Why exactly?), I intend to create my own "Users" table. What is a good approach to connect the records from aspnet_Users table and my own custom Users table.
I want the relationship to be 1:1 and the design in the database to be as transparent as possible in my c# code (I'm using linq to sql if it is important). Also, I don't want to replicate the usernames and passwords from the aspnet_ tables to my table and maintain the data.
I'm considering using a view to join them. Is this a good idea?
Thanks in advance!
EDIT: From the answer, I see that I may not be clear enough, what I want. The question is not IF to use the default asp.net provider, but how to adopt it, to my needs.
I would create custom membership provider and omit those aspnet_x tables completely. I've seen what happens when one joins these tables and custom ones with nhibernate mappings - pure nightmare.
If you are choosing to use the Membership API for your site, then this link has information regarding how to add extra information to a user.
I was faced with the same scenario recently and ended up ditching the membership functionality and rolled my own db solution in tandem with the DotNetOpenAuth library.
Using the membership system in asp.net has its advantages and drawbacks. It's easy to start, because you don't have to worry about validation, user registration, resetting passwords. (Be careful if you plan to modify the table structures, you will have to change them in the views/store procedures generated
However there are drawbacks to using Membership
You will have to maintain 2 separated systems, because the Membership API has restrictions, for example, you cannot perform operations inside a transaction with the membership api. (Unless you use TransactionScope i think, but you don't have other choices).
A valid alternative would be to implement your own security validation routines, and using FormsAuthentication. This way you will have total control over your users tables, and remove dependency to the membership API.

Resources