Friday, January 10, 2014

Using MvcScaffolding Packages to Generate Repositories for your LoB Applications

ASP.NET MVC’s tooling support goes a long way in making it a LOB Application friendly platform. However the default Controller scaffold contains direct references to the DBContext. This is a little smelly when it comes to separation of concerns and can often lead to ending up with ‘fat-controllers’. Instead, if our Scaffolder could generate a Repository Interface and its corresponding implementation, our LoB apps would not only achieve better ‘separation of concerns’ but also becomes more testable. The MvcScaffolder extension that comes as Nuget Package enables us to do precisely this type of scaffolding. Let’s see how we can use it in a simple Contact app.

Getting Started – Installing MvcScaffolder

Step 1: We start off by creating a new MVC 4 Application in Visual Studio. We use the Basic Application template for now.
Step 2: Install the MvcScaffolder using Nuget Package Manager

installing-mvc-scaffolding

This will install the T4Scaffolding dependency as well.

Adding a Model entity and generating the CRUD Screens

Now that we have the MvcScaffolding package installed we are ready to setup our Model and then run the scaffolder on it.

Step 3: Add the following Contact class in the Model folder and build the application.

public class Contact
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}

  
Step 4: Right Click on the Controller folder and select Add Controller. It brings up the standard Add Controller dialog but if you look at the DropDown, it has two additional options thanks to MvcScaffolding.

mvc-scaffolding-option-in-add-controller

Step 5: Now setup the Add Controller dialog as follows to generate CRUD screens for Contact model object.

- Controller Name: ContactController
- Template as MvcScaffolding: Controller with read/write action and views, using repositories.
- Model Class: Contact (ScaffoldingRepositories.Model)
- Data Context Class: ScaffoldingRepositories.Models.ScaffoldingRepositoriesContext

mvc-scaffolding-option-in-add-controller

Click on Add to complete the scaffolding process.

Step 6: On completion of the Scaffolding process you will see the following files added to your solution

generated-files-and-folders

Controller – ContactController.cs

Models –
a. ContactRespository.cs: This has the Interface and the Implementation for persisting Contact Data. The implementation uses the next generated class i.e. ScaffoldingRepositoriesContext
b. ScaffoldingRepositoriesContext.cs: Contains the EF DbContext implementation used for persisting the data to LocalDb.

Views – Views has the standard CRUD views generated. One thing to note here is that there is a partial view called _CreateOrEdit.cshtml. This view as we will see shortly, is common to both Create and Edit screens and hence separated out into its own partial.

Applying Script References

The generated views have one minor gotcha, as in the script references for jQuery Validation are added at the top of the Create and Edit views.

Our jQuery references are added at the bottom of the _Layout.cshtml. As a result of this the jQuery Validation scripts fail when trying to load ‘before’ the jQuery script itself.

The solution is simple.

Move the jQuery Validation references to the bottom of the page inside a Script section as follows

@section scripts{


}

  
The Script section is important because in the _Layout.cshtml we have the following code


@RenderBody()
 
@Scripts.Render("~/bundles/jquery")
@RenderSection("scripts", required: false)


  
What this means is, Razor view engine will add reference to the jQuery bundle to the Scripts section and then try to render the Scripts section if present in any other child views. The contents of the Scripts section in child view will be after the jQuery bundle has been rendered.

With the Script references fixed, we are ready to run the application.

Running the Application

When we run the application, now we should be able to save data to the database

index-create-index

Neat! So our application is up and running as if it were built using the default MVC Scaffold tool. Time to dig in and see what’s different with the MvcScaffolding extension.

Digging deeper into generated code

Now that everything is working fine, let’s pop the hood and see how things are running. First up the repository.

The Repository

The ContactRepository.cs has the Interface and the implementation for Contact Repository.

generated-contact-repository
Note that the IContactRepository inherits from IDisposable. The implementation uses an instance of the ScaffoldingRepositoriesContext object that uses EF to persist data.

There is an interesting Repository method called AllIncluding and as we can see in the code below, it can accept a parameter consisting of an array of Model properties. This way we can limit the amount of data loaded if required. It can also be used for excluding Navigation properties etc.

The InsertOrUpdate method checks if the Id property has the default value, if it does, it saves it as a new entity. If the Id already has a non-default value, attempt to Update the entity.

generated-contact-repository-impl

The ContactController

The ContactController is also generated a little differently, as in, instead of an instance of DbContext, we have a direct assignment of an Interface to its concrete class hardcoded in the constructor.

private readonly IContactRepository contactRepository;
// If you are using Dependency Injection, you can delete the following constructor
public ContactController() : this(new ContactRepository())
{
}

  
To resolve this, we have to introduce an IoC Container to inject the dependency instance into the controller via the constructor. At this point, we can go ahead and integrate our favorite IoC container/DI framework as we want.

Other MvcScaffolding features

The MvcScaffolding package also has the ability to let you create your own Scaffolds. It creates a bootstrap set of files when you use the following command at the Package Manager Console

PM> Scaffold CustomScaffolder MyScaffolder

What this does is, it adds T4 templates required for Scaffolding into a CodeTemplates folder. All T4 files are in a folder by the name of the scaffolder you created (MyScaffolder).

custom-scaffolder

Now you can update the t4 template to generate a particular type of file and then run the Scaffolding as

PM> Scaffold MyScaffolder

This will generate the file ExampleOutput.cs as follows

namespace ScaffoldingRepositories
{
public class ExampleOutput
{
  // Example model value from scaffolder script: Hello, world!
}
}

  
Essentially the Scaffolding plugin is not only helping generate CRUD screens, but if you have repetitive code that you want to automate, you can very well use the Custom Scaffolder feature to make life easier for yourself.

Conclusion

MvcScaffolding is a nifty extension that adds additional scaffolding capabilities to the default MVC tooling that comes out of the box.

Caveat is that it’s not an officially supported Microsoft plugin. It was developed by Steve Sanderson and Scott Hanselman and you can find more information on Steve’s blog at http://blog.stevensanderson.com/?s=scaffolding

Working with Roles in ASP.NET MVC 4+

In this article, We'll look into how to create a new role, delete a role and attach a user to a specific role in ASP.NET MVC using default Role provider under System.Web.Security namespace.


Introduction


Authentication (Login and Registration) is simple in ASP.NET MVC as the default project template provides all the necessary controller code, model and view to register and login. However adding roles and assigning roles to a particular user seems to be lost in all these stuffs. In this article, we will learn all that is related with Roles for a particular user in ASP.NET MVC 4.

Objective


The objective of this article is to explain how to work with Roles in ASP.NET MVC 4 +.

Assumption


Here we are assuming that we have used the default ASP.NET MVC template (ASP.NET MVC 4  Web Application project type and Internet Application template) that automatically creates a database for us when we try to register for the first time and the default database tables it creates for roles are following


  1. webpages_Roles
  2. webpages_UserInRoles

Creating a new role in ASP.NET MVC


In order to create a new Role, the default template doesn't provide any UI, so we have to build it our self. Below is the simple UI we have built in Razor under Views/Account folder (In fact all views we are going to work with in this article are in this folder). In this case we have used a different Layout page as we do not want the default website Layout to appear.

@{
    ViewBag.Title = "RoleCreate";
    Layout = "~/Views/Shared/_LayoutAdmin.cshtml";
}
<div class="spacerBody">
    &nbsp;</p>
    @Html.ActionLink("Roles", "RoleIndex") | @Html.ActionLink("Add Role to User", "RoleAddToUser")

Role Create</h2> @using(Html.BeginForm()){     @Html.AntiForgeryToken()     @Html.ValidationSummary(true)    
    Role name</
div>             @Html.TextBox("RoleName")     </p>     > }     </div>

Picture - 1

Notice that we have a simple TextBox in the above View with the name as  "RoleName" that we are going to use to create a new Role into our database.

Below are two methods in our AccountController.cs responsible for creating a new Role.

        [Authorize(Roles = "Admin")]
        public ActionResult RoleCreate()
        {
            return View();
        }

        [Authorize(Roles = "Admin")]
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult RoleCreate(string RoleName)
        {
            
                Roles.CreateRole(Request.Form["RoleName"]);
                // ViewBag.ResultMessage = "Role created successfully !";
            
            return RedirectToAction("RoleIndex", "Account");
        }
The first method simply renders the view provided the logged in user has Roles as "Admin" assigned to the database (because of Authorize attribute in this method). So to get started first go to your database table "webpages_Roles" and insert and "Admin" role then map this role to the user id you are logged in with in the "webpages_UsersInRoles" table.


In above case, I am logged in to the application as "SheoNarayan" that has UserId as "2" in the "UserProfile" table that is created by default by ASP.NET MVC project.

Now when Save button is clicked in Picture - 1, the 2nd method of the above code snippet fires and calls the "Roles.CreateRole" method to create a role that is entered into the Textbox.


Listing Roles in ASP.NET MVC


To list roles created in ASP.NET MVC, we have created another view called "RoleIndex" and here is the Razor code for this.

@{
    ViewBag.Title = "Role Listing";
    Layout = "~/Views/Shared/_LayoutAdmin.cshtml";
}
&nbsp;</p>
<div class="spacerBody">
    @Html.ActionLink("Create New Role", "RoleCreate") | @Html.ActionLink("Add Role to User", "RoleAddToUser")

Role Index</h2>    
            @foreach (string s in Model) {    
       
            @s         </
div>         <div class="td">             <span onclick="return confirm('Are you sure to delete?')">         <a href="/Account/RoleDelete?RoleName=@s" class="delLink"><img src="/images/deleteicon.gif" alt="Delete" class="imgBorder0" /> Delete</a>                            </span>         </div>     </div> }         </div> </div>


In this view, we are simply looping through the Model we are receiving from the controller. The controller method that is responsible to render all the roles are below.
        [Authorize(Roles = "Admin")]
        public ActionResult RoleIndex()
        {
            var roles = Roles.GetAllRoles();
            return View(roles);
        }

The above code simply executes Roles.GetAllRoles() method that gives all roles from the webpages_Roles database table in the form of string array and returns to the view. The same is being used to list the roles on the view.

You must have noticed that we have also added a Delete link against each Role so that we can delete a role too. The Delete link passes the Role name as querystring to the RoleDelete method of the controller, lets see that too.

Delete a Role in ASP.NET MVC


To delete a role, we have just created a method in the controller named "RoleDelete" and making sure that it gets executed only when an Admin user is trying to browse it.

        [Authorize(Roles = "Admin")]
        public ActionResult RoleDelete(string RoleName)
        {
            
                Roles.DeleteRole(RoleName);
                // ViewBag.ResultMessage = "Role deleted succesfully !";
            
            
            return RedirectToAction("RoleIndex", "Account");
        }
This method takes "RoleName" as parameter and calls Roles.DeleteRole method to delete a role.

Note that there is no method in the Roles class called "EditRole" or "UpdateRole" so be careful while creating a new role and deleting a new role.


Assigning a Role to the User in ASP.NET MVC


Now, lets see how to assign a role to the user, to do that we have created a simple form that has a TextBox to accept username and a DropDown that lists all the roles from the database and it looks like below. In the same view, we have also created another form that accepts username and list all the roles associated with that username.

@{
    ViewBag.Title = "Role Add To User";
    Layout = "~/Views/Shared/_LayoutAdmin.cshtml";
}
<div class="spacerBody">
    &nbsp;</p>
    @Html.ActionLink("Create New Role", "RoleCreate") | @Html.ActionLink("Roles", "RoleIndex")
        

Role Add to User</h2> @using(Html.BeginForm("RoleAddToUser", "Account")){     @Html.AntiForgeryToken()     @Html.ValidationSummary(true)    
@ViewBag.ResultMessage</
div>             Username : @Html.TextBox("UserName")         Role Name: @Html.DropDownList("RoleName", ViewBag.Roles as SelectList)             </p>         > } <div class="hr"></div> @using(Html.BeginForm("GetRoles", "Account")){     @Html.AntiForgeryToken()     Username : @Html.TextBox("UserName")         <input type="submit" value="Get Roles for this User" />     </p> }         @if(ViewBag.RolesForThisUser != null) {        

Roles for this user </

h3>    
    @foreach (string s in ViewBag.RolesForThisUser){    
  1. @s</li>   }                 </ol>     </text> }         </div>



    The Controller code for this view page looks like below

            /// 
            /// Create a new role to the user
            /// 

           
    ///
           
    [Authorize(Roles = "Admin")]
           
    public ActionResult RoleAddToUser()
           
    {
               
    SelectList list = new SelectList(Roles.GetAllRoles());
               
    ViewBag.Roles = list;

               
    return View();
           
    }

           
    ///
           
    /// Add role to the user
           
    ///
           
    ///
           
    ///
           
    ///
           
    [Authorize(Roles = "Admin")]
           
    [HttpPost]
           
    [ValidateAntiForgeryToken]
           
    public ActionResult RoleAddToUser(string RoleName, string UserName)
           
    {

                   
    if (Roles.IsUserInRole(UserName, RoleName))
                   
    {
                       
    ViewBag.ResultMessage = "This user already has the role specified !";
                   
    }
                   
    else
                   
    {
                       
    Roles.AddUserToRole(UserName, RoleName);
                       
    ViewBag.ResultMessage = "Username added to the role succesfully !";
                   
    }
               
               
    SelectList list = new SelectList(Roles.GetAllRoles());
               
    ViewBag.Roles = list;
               
    return View();
           
    }

           
    ///
           
    /// Get all the roles for a particular user
           
    ///
           
    ///
           
    ///
           
    [Authorize(Roles = "Admin")]
           
    [HttpPost]
           
    [ValidateAntiForgeryToken]
           
    public ActionResult GetRoles(string UserName)
           
    {
               
    if (!string.IsNullOrWhiteSpace(UserName))
               
    {
                   
    ViewBag.RolesForThisUser = Roles.GetRolesForUser(UserName);
                   
    SelectList list = new SelectList(Roles.GetAllRoles());
                   
    ViewBag.Roles = list;
               
    }
               
    return View("RoleAddToUser");
           
    }
    The first method of above code snippet simply gets all the roles from the database using "GetAllRoles()" method into SelectList and sets into the ViewBag.Roles. The same is being populated as DropDown into the view.

    Clicking on Save method fires the 2nd method that first checks whether this user is already in the selected role, if not then calls "Roles.AddUserToRole" method to adds the username entered into textbox to associate with the role selected in the DropDown.

    Listing Roles associated with a particular user in ASP.NET MVC

    To list roles associated with a particular username, we have created another form in the same view that executes GetRoles method of the controller and calls "Roles.GetRolesForUser" method to get all roles associated with the username entered into the textbox. These roles are converted into SelectList and then set as "Roles into the ViewBag that ultimately renders the roles associated with a particular username.


    How to remove a user from a role in ASP.NET MVC?


    In order to remove a user from a particular role, I have again created a small form in the same above view (RoleAddToUser.cshtml) and here is the view code for this.

        

    Delete A User from a Role


    @using (Html.BeginForm("DeleteRoleForUser", "Account"))
    {
        @Html.AntiForgeryToken()
        @Html.ValidationSummary(true)

       

            Username : @Html.TextBox("UserName")
            Role Name: @Html.DropDownList("RoleName", ViewBag.Roles as SelectList)
           
       

       
       
    type="submit" value="Delete this user from Role" />
    }
    Writing the username in the TextBox, selecting a role from the DropDown and clicking Save button submit this form to the DeleteRoleForUser action method in the Account controller.


    In the Account controller, my action method looks like this 

            [HttpPost]
            [Authorize(Roles = "Admin")]
            [ValidateAntiForgeryToken]
            public ActionResult DeleteRoleForUser(string UserName, string RoleName)
            {
    
                    if (Roles.IsUserInRole(UserName, RoleName))
                    {
                        Roles.RemoveUserFromRole(UserName, RoleName);
                        ViewBag.ResultMessage = "Role removed from this user successfully !";
                    }
                    else
                    {
                        ViewBag.ResultMessage = "This user doesn't belong to selected role.";
                    }
                    ViewBag.RolesForThisUser = Roles.GetRolesForUser(UserName);
                    SelectList list = new SelectList(Roles.GetAllRoles());
                    ViewBag.Roles = list;
                
    
                return View("RoleAddToUser");
            }
    In the above code snippet, I am checking whether the given username exists for that role or not, if yes then calling "Roles.RemoveUserFromRole" method. Following code is to write proper message and to make sure that the form is again getting loaded with the default data in the Role DropDown.


    Checking for a particular role before performing any action in ASP.NET MVC


    Now, there might be scenario where you need to check into the code block for a particular role for the  user before performing certain activity, to do that use below code

    if (User.IsInRole("Admin"))
                {
    
                    // Code to execute only when the logged in use is in "Admin" role
    
                }
    The above code gets executed only when the logged in user belongs to "Admin" role.

    Dig more methods of the "Roles" class and you will find many more interesting methods that helps you working with user roles in ASP.NET MVC.


    Conclusion


    Working with roles in ASP.NET MVC default project template is little tricky and this article explains that. Hope this article would be useful for people looking for working with Roles and managing roles in ASP.NET MVC.

    Thanks for reading, do let us know your feedback and share this article to your friends and colleague if you liked. Do vote for this article.

    Thursday, January 9, 2014

    SimpleMembership, Membership Providers, Universal Providers and the new ASP.NET 4.5 Web Forms and ASP.NET MVC 4 templates

    The ASP.NET MVC 4 Internet template adds some new, very useful features which are built on top of SimpleMembership. These changes add some great features, like a much simpler and extensible membership API and support for OAuth. However, the new account management features require SimpleMembership and won't work against existing ASP.NET Membership Providers. I'll start with a summary of top things you need to know, then dig into a lot more detail.
    Summary:
    • SimpleMembership has been designed as a replacement for the previous ASP.NET Role and Membership provider system
    • SimpleMembership solves common problems developers ran into with the Membership provider system and was designed for modern user / membership / storage needs
    • SimpleMembership integrates with the previous membership system, but you can't use a MembershipProvider with SimpleMembership
    • The new ASP.NET MVC 4 Internet application template AccountController requires SimpleMembership and is not compatible with previous MembershipProviders
    • You can continue to use existing ASP.NET Role and Membership providers in ASP.NET 4.5 and ASP.NET MVC 4 - just not with the ASP.NET MVC 4 AccountController
    • The existing ASP.NET Role and Membership provider system remains supported, as it is part of the ASP.NET core
    • ASP.NET 4.5 Web Forms does not use SimpleMembership; it implements OAuth on top of ASP.NET Membership
    • The ASP.NET Web Site Administration Tool (WSAT) is not compatible with SimpleMembership
    The following is the result of a few conversations with Erik Porter (PM for ASP.NET MVC) to make sure I had some the overall details straight, combined with a lot of time digging around in ILSpy and Visual Studio's assembly browsing tools.

    SimpleMembership: The future of membership for ASP.NET

    The ASP.NET Membership system was introduced with ASP.NET 2.0 back in 2005. It was designed to solve common site membership requirements at the time, which generally involved username / password based registration and profile storage in SQL Server. It was designed with a few extensibility mechanisms - notably a provider system (which allowed you override some specifics like backing storage) and the ability to store additional profile information (although the additional  profile information was packed into a single column which usually required access through the API). While it's sometimes frustrating to work with, it's held up for seven years - probably since it handles the main use case (username / password based membership in a SQL Server database) smoothly and can be adapted to most other needs (again, often frustrating, but it can work).
    The ASP.NET Web Pages and WebMatrix efforts allowed the team an opportunity to take a new look at a lot of things - e.g. the Razor syntax started with ASP.NET Web Pages, not ASP.NET MVC. The ASP.NET Web Pages team designed SimpleMembership to (wait for it) simplify the task of dealing with membership. As Matthew Osborn said in his post Using SimpleMembership With ASP.NET WebPages:
    With the introduction of ASP.NET WebPages and the WebMatrix stack our team has really be focusing on making things simpler for the developer. Based on a lot of customer feedback one of the areas that we wanted to improve was the built in security in ASP.NET. So with this release we took that time to create a new built in (and default for ASP.NET WebPages) security provider. I say provider because the new stuff is still built on the existing ASP.NET framework. So what do we call this new hotness that we have created? Well, none other than SimpleMembership. SimpleMembership is an umbrella term for both SimpleMembership and SimpleRoles.
    Part of simplifying membership involved fixing some common problems with ASP.NET Membership.

    Problems with ASP.NET Membership

    ASP.NET Membership was very obviously designed around a set of assumptions:
    • Users and user information would most likely be stored in a full SQL Server database or in Active Directory
    • User and profile information would be optimized around a set of common attributes (UserName, Password, IsApproved, CreationDate, Comment, Role membership...) and other user profile information would be accessed through a profile provider
    Some problems fall out of these assumptions.

    Requires Full SQL Server for default cases

    The default, and most fully featured providers ASP.NET Membership providers (SQL Membership Provider, SQL Role Provider, SQL Profile Provider) require full SQL Server. They depend on stored procedure support, and they rely on SQL Server cache dependencies, they depend on agents for clean up and maintenance. So the main SQL Server based providers don't work well on SQL Server CE, won't work out of the box on SQL Azure, etc.
    Note: Cory Fowler recently let me know about these Updated ASP.net scripts for use with Microsoft SQL Azure which do support membership, personalization, profile, and roles. But the fact that we need a support page with a set of separate SQL scripts underscores the underlying problem.
    Aha, you say! Jon's forgetting the Universal Providers, a.k.a. System.Web.Providers! Hold on a bit, we'll get to those...

    Custom Membership Providers have to work with a SQL-Server-centric API

    If you want to work with another database or other membership storage system, you need to to inherit from the provider base classes and override a bunch of methods which are tightly focused on storing a MembershipUser in a relational database. It can be done (and you can often find pretty good ones that have already been written), but it's a good amount of work and often leaves you with ugly code that has a bunch of System.NotImplementedException fun since there are a lot of methods that just don't apply.

    Designed around a specific view of users, roles and profiles

    The existing providers are focused on traditional membership - a user has a username and a password, some specific roles on the site (e.g. administrator, premium user), and may have some additional "nice to have" optional information that can be accessed via an API in your application.
    This doesn't fit well with some modern usage patterns:
    • In OAuth and OpenID, the user doesn't have a password
    • Often these kinds of scenarios map better to user claims or rights instead of monolithic user roles
    • For many sites, profile or other non-traditional information is very important and needs to come from somewhere other than an API call that maps to a database blob
    What would work a lot better here is a system in which you were able to define your users, rights, and other attributes however you wanted and the membership system worked with your model - not the other way around.

    Requires specific schema, overflow in blob columns

    I've already mentioned this a few times, but it bears calling out separately - ASP.NET Membership focuses on SQL Server storage, and that storage is based on a very specific database schema.
    aspnet_tutorial04_MembershipSetup_vb_figure10[1]
    Update: This schema has been improved a lot with Universal Providers. The views and stored procedures have been removed, and the tables are simplified.
    2012-09-05_16h12_30
    Still, the main issues are unchanged: you're not in control of the schema, and any profile data is stored in property value blobs in the Profiles table:
    2012-09-05_16h14_31

    SimpleMembership as a better membership system

    As you might have guessed, SimpleMembership was designed to address the above problems.

    Works with your Schema

    As Matthew Osborn explains in his Using SimpleMembership With ASP.NET WebPages post, SimpleMembership is designed to integrate with your database schema:
    All SimpleMembership requires is that there are two columns on your users table so that we can hook up to it – an “ID” column and a “username” column. The important part here is that they can be named whatever you want. For instance username doesn't have to be an alias it could be an email column you just have to tell SimpleMembership to treat that as the “username” used to log in.
    Matthew's example shows using a very simple user table named Users (it could be named anything) with a UserID and Username column, then a bunch of other columns he wanted in his app.
    UsersTable[1]
    Then we point SimpleMemberhip at that table with a one-liner:
    WebSecurity.InitializeDatabaseFile("SecurityDemo.sdf", "Users", "UserID", "Username", true);
    No other tables are needed, the table can be named anything we want, and can have pretty much any schema we want as long as we've got an ID and something that we can map to a username.

    Broaden database support to the whole SQL Server family

    While SimpleMembership is not database agnostic, it works across the SQL Server family. It continues to support full SQL Server, but it also works with SQL Azure, SQL Server CE, SQL Server Express, and LocalDB. Everything's implemented as SQL calls rather than requiring stored procedures, views, agents, and change notifications.
    Note that SimpleMembership still requires some flavor of SQL Server - it won't work with MySQL, NoSQL databases, etc. You can take a look at the code in WebMatrix.WebData.dll using a tool like ILSpy if you'd like to see why - there are places where SQL Server specific SQL statements are being executed, especially when creating and initializing tables. It seems like you might be able to work with another database if you created the tables separately, but I haven't tried it and it's not supported at this point.
    Note: I'm thinking it would be possible for SimpleMembership (or something compatible) to run Entity Framework so it would work with any database EF supports. That seems useful to me - thoughts?
    Note: SimpleMembership has the same database support - anything in the SQL Server family - that Universal Providers brings to the ASP.NET Membership system.
    UPDATE: Newer updates of Universal Providers - I believe starting with the 1.2 release on 8/16 - are now really database agnostic, so they'll work on any database that has an Entity Framework provider.

    Easy to with Entity Framework Code First

    The problem with with ASP.NET Membership's system for storing additional account information is that it's the gate keeper. That means you're stuck with its schema and accessing profile information through its API.
    SimpleMembership flips that around by allowing you to use any table as a user store. That means you're in control of the user profile information, and you can access it however you'd like - it's just data. Let's look at a practical based on the AccountModel.cs class in an ASP.NET MVC 4 Internet project. Here I'm adding a Birthday property to the UserProfile class.
    [Table("UserProfile")]
    public class UserProfile
    {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int      UserId { get; set; }
        public string   UserName { get; set; }
        public DateTime Birthday { get; set; }
    }
    Now if I want to access that information, I can just grab the account by username and read the value.
    var context = new UsersContext();
    var username = User.Identity.Name;
    var user = context.UserProfiles.SingleOrDefault(u => u.UserName == username);
    var birthday = user.Birthday;
    So instead of thinking of SimpleMembership as a big membership API, think of it as something that handles membership based on your user database. In SimpleMembership, everything's keyed off a user row in a table you define rather than a bunch of entries in membership tables that were out of your control.

    How SimpleMembership integrates with ASP.NET Membership

    Okay, enough sales pitch (and hopefully background) on why things have changed. How does this affect you? Let's start with a diagram to show the relationship (note: I've simplified by removing a few classes to show the important relationships):
    2012-08-29_16h59_20
    So SimpleMembershipProvider is an implementaiton of an ExtendedMembershipProvider, which inherits from MembershipProvider and adds some other account / OAuth related things. Here's what ExtendedMembershipProvider adds to MembershipProvider:
    ExtendedMembershipProvider
    The important thing to take away here is that a SimpleMembershipProvider is a MembershipProvider, but a MembershipProvider is not a SimpleMembershipProvider.
    This distinction is important in practice: you cannot use an existing MembershipProvider (including the Universal Providers found in System.Web.Providers) with an API that requires a SimpleMembershipProvider, including any of the calls in WebMatrix.WebData.WebSecurity or Microsoft.Web.WebPages.OAuth.OAuthWebSecurity.
    However, that's as far as it goes. Membership Providers still work if you're accessing them through the standard Membership API, and all of the core stuff  - including the AuthorizeAttribute, role enforcement, etc. - will work just fine and without any change.
    Let's look at how that affects you in terms of the new templates.

    Membership in the ASP.NET MVC 4 project templates

    ASP.NET MVC 4 offers six Project Templates:
    • Empty - Really empty, just the assemblies, folder structure and a tiny bit of basic configuration.
    • Basic - Like Empty, but with a bit of UI preconfigured (css / images / bundling).
    • Internet - This has both a Home and Account controller and associated views. The Account Controller supports registration and login via either local accounts and via OAuth / OpenID providers.
    • Intranet - Like the Internet template, but it's preconfigured for Windows Authentication.
    • Mobile - This is preconfigured using jQuery Mobile and is intended for mobile-only sites.
    • Web API - This is preconfigured for a service backend built on ASP.NET Web API.
    2012-08-29_17h26_24
    Out of these templates, only one (the Internet template) uses SimpleMembership.

    ASP.NET MVC 4 Basic template

    The Basic template has configuration in place to use ASP.NET Membership with the Universal Providers. You can see that configuration in the ASP.NET MVC 4 Basic template's web.config:
    
      
        
      
    
    
      
        
      
    
    
      
        
      
    
    
      
        
      
    
    This means that it's business as usual for the Basic template as far as ASP.NET Membership works.

    ASP.NET MVC 4 Internet template

    The Internet template has a few things set up to bootstrap SimpleMembership:
    2012-08-29_17h45_32
    • \Models\AccountModels.cs defines a basic user account and includes data annotations to define keys and such
    • \Filters\InitializeSimpleMembershipAttribute.cs creates the membership database using the above model, then calls WebSecurity.InitializeDatabaseConnection which verifies that the underlying tables are in place and marks initialization as complete (for the application's lifetime)
    • \Controllers\AccountController.cs makes heavy use of OAuthWebSecurity (for OAuth account registration / login / management) and WebSecurity. WebSecurity provides account management services for ASP.NET MVC (and Web Pages)
    WebSecurity can work with any ExtendedMembershipProvider. There's one in the box (SimpleMembershipProvider) but you can write your own. Since a standard MembershipProvider is not an ExtendedMembershipProvider, WebSecurity will throw exceptions if the default membership provider is a MembershipProvider rather than an ExtendedMembershipProvider.
    Practical example:
    1. Create a new ASP.NET MVC 4 application using the Internet application template
    2. Install the Microsoft ASP.NET Universal Providers for LocalDB NuGet package
    3. Run the application, click on Register, add a username and password, and click submit
    You'll get the following execption in AccountController.cs::Register: To call this method, the "Membership.Provider" property must be an instance of "ExtendedMembershipProvider".
    2012-08-29_18h34_13
    This occurs because the ASP.NET Universal Providers packages include a web.config transform that will update your web.config to add the Universal Provider configuration I showed in the Basic template example above. When WebSecurity tries to use the configured ASP.NET Membership Provider, it checks if it can be cast to an ExtendedMembershipProvider before doing anything else.
    So, what do you do?
    Options:
    If you want to use the new AccountController, you'll either need to use the SimpleMembershipProvider or another valid ExtendedMembershipProvider. This is pretty straightforward.
    If you want to use an existing ASP.NET Membership Provider in ASP.NET MVC 4, you can't use the new AccountController. You can do a few things:
    1. Replace  the AccountController.cs and AccountModels.cs in an ASP.NET MVC 4 Internet project with one from an ASP.NET MVC 3 application (you of course won't have OAuth support). Then, if you want, you can go through and remove other things that were built around SimpleMembership - the OAuth partial view, the NuGet packages (e.g. the DotNetOpenAuthAuth package, etc.)
    2. Use an ASP.NET MVC 4 Internet application template and add in a Universal Providers NuGet package. Then copy in the AccountController and AccountModel classes.
    3. Create an ASP.NET MVC 3 project and upgrade it to ASP.NET MVC 4 using the steps shown in the ASP.NET MVC 4 release notes.
    None of these are particularly elegant or simple. Maybe we (or just me?) can do something to make this simpler - perhaps a NuGet package. However, this should be an edge case - hopefully the cases where you'd need to create a new ASP.NET but use legacy ASP.NET Membership Providers should be pretty rare. Please let me (or, preferably the team) know if that's an incorrect assumption.

    Membership in the ASP.NET 4.5 project template

    ASP.NET 4.5 Web Forms took a different approach which builds off ASP.NET Membership. Instead of using the WebMatrix security assemblies, Web Forms uses Microsoft.AspNet.Membership.OpenAuth assembly. I'm no expert on this, but from a bit of time in ILSpy and Visual Studio's (very pretty) dependency graphs, this uses a Membership Adapter to save OAuth data into an EF managed database while still running on top of ASP.NET Membership.
    2012-08-29_19h13_13
    Note: There may be a way to use this in ASP.NET MVC 4, although it would probably take some plumbing work to hook it up.

    How does this fit in with Universal Providers (System.Web.Providers)?

    Just to summarize:
    • Universal Providers are intended for cases where you have an existing ASP.NET Membership Provider and you want to use it with another SQL Server database backend (other than SQL Server). It doesn't require agents to handle expired session cleanup and other background tasks, it piggybacks these tasks on other calls.
    • Universal Providers are not really, strictly speaking, universal - at least to my way of thinking. They only work with databases in the SQL Server family.
    • Universal Providers do not work with Simple Membership.
    • The Universal Providers packages include some web config transforms which you would normally want when you're using them.

    What about the Web Site Administration Tool?

    Visual Studio includes tooling to launch the Web Site Administration Tool (WSAT) to configure users and roles in your application.
    image102[1]
    WSAT is built to work with ASP.NET Membership, and is not compatible with Simple Membership. There are two main options there:
    1. Use the WebSecurity and OAuthWebSecurity API to manage the users and roles
    2. Create a web admin using the above APIs
    3. 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)
    2012-08-29_19h34_46

    Could not find a part of the path ... bin\roslyn\csc.exe

    I am trying to run an ASP.NET MVC (model-view-controller) project retrieved from TFS (Team Foundation Server) source control. I have added a...