I’ve been Googling over the weekend and so far didn’t find any articles out there on how integrate EF5 CodeFirst nicely with SimpleMembership and at the same time, seeding some of your users, roles and associating users to roles while supporting custom fields/properties during registration, hence this blog post.
I think this is a nice to have, especially during PoC development where you could be developing features that depend on authentication and authorization while making schema changes with EF CodeFirst. The last thing you want to do is run update-database for migrations and have to manually re-insert/re-seed all your users, roles and associating the two every time you ran migrations (e.g. update-database -force from the Package Manager Console).
First, create an “Internet Application” ASP.NET MVC4 Project, because this is the only out of the box MVC template that has the new SimpleMembershipProvider wired up out of the box. One of the features I like the most about the SimpleMembershipProvider is it gives you total control of the highly requested “User” table/entity. Meaning you integrate SimpleMembershipProvider with your own user table, as long as it has a UserId and UserName fields in your table.
Obviously there are many more features in SimpleMembership provider, here are some links in this regard:
- http://weblogs.asp.net/jgalloway/archive/2012/08/29/simplemembership-membership-providers-universal-providers-and-the-new-asp-net-4-5-web-forms-and-asp-net-mvc-4-templates.aspx
- http://blog.osbornm.com/archive/2010/07/21/using-simplemembership-with-asp.net-webpages.aspx
Explicitly wire up the providers even though this is implied, so that when do run the “update-database” command from the Package Manager Console for migrations we can use the native “Roles” Api.
In the “System.Web” Section add:
<roleManager enabled="true" defaultProvider="SimpleRoleProvider"> <providers> <clear/> <add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData"/> </providers> </roleManager> <membership defaultProvider="SimpleMembershipProvider"> <providers> <clear/> <add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" /> </providers> </membership>
Let’s add a custom field to the User table by adding a Mobile property to the UserProfile entity (MVC4SimpleMembershipCodeFirstSeedingEF5/Models/AccountModel.cs).
[Table("UserProfile")] public class UserProfile { [Key] [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] public int UserId { get; set; } public string UserName { get; set; } public string Mobile { get; set; } }
Enable EF5 CodeFirst Migrations
Seed your Roles and any Users you want to provision, also note the WebSecurity.InitializeDatabaseConnection method we are invoking. This method is what tells SimpleMembership which table to use when working with Users and which columns are for the UserId and UserName. I’m also going to demonstrate how you can hydrate additional custom columns such as requiring a User’s mobile number when registering on the site.
#region using System.Data.Entity.Migrations; using System.Linq; using System.Web.Security; using MVC4SimpleMembershipCodeFirstSeedingEF5.Models; using WebMatrix.WebData; #endregion namespace MVC4SimpleMembershipCodeFirstSeedingEF5.Migrations { internal sealed class Configuration : DbMigrationsConfiguration<UsersContext> { public Configuration() { AutomaticMigrationsEnabled = true; } protected override void Seed(UsersContext context) { WebSecurity.InitializeDatabaseConnection( "DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true); if (!Roles.RoleExists("Administrator")) Roles.CreateRole("Administrator"); if (!WebSecurity.UserExists("lelong37")) WebSecurity.CreateUserAndAccount( "lelong37", "password", new {Mobile = "+19725000000"}); if (!Roles.GetRolesForUser("lelong37").Contains("Administrator")) Roles.AddUsersToRoles(new[] {"lelong37"}, new[] {"Administrator"}); } } }
Now, run the update-database -verbose command from Package Manager Console, we are using the -verbose switch so that we can get better visibility on what’s getting executed on SQL. Notice the Mobile field is being created.
Let’s go ahead and do a sanity check and make sure all of our Users and Roles were provisioned correctly from the Seed method in our migration configuration, by executing a few queries.
SELECT TOP 1000 [UserId] ,[UserName] ,[Mobile] FROM [aspnet-MVC4SimpleMembershipCodeFirstSeedingEF5].[dbo].[UserProfile] SELECT TOP 1000 [RoleId] ,[RoleName] FROM [aspnet-MVC4SimpleMembershipCodeFirstSeedingEF5].[dbo].[webpages_Roles] SELECT TOP 1000 [UserId] ,[RoleId] FROM [aspnet-MVC4SimpleMembershipCodeFirstSeedingEF5].[dbo].[webpages_UsersInRoles]
Results
- Users were inserted
- Roles were provisioned
- The user “LeLong37” was added and associated to the Administrator role
Finally for a sanity check, let’s go ahead and run the app and sign-in with the provisioned user from our Seed method.
Successfully authenticated with our seeded provisioned user (thought I’d add a blue star badge to the screenshot to add some humor 😛 )!
One last thing, let’s go ahead and modify our Register view, Register model and AccountController to gather the user’s mobile number during registration.
Register View (Register.cshtml)
@model MVC4SimpleMembershipCodeFirstSeedingEF5.Models.RegisterModel @{ ViewBag.Title = "Register"; } <hgroup class="title"> <h1>@ViewBag.Title.</h1> <h2>Create a new account.</h2> </hgroup> @using (Html.BeginForm()) { @Html.AntiForgeryToken() @Html.ValidationSummary() <fieldset> <legend>Registration Form</legend> <ol> <li> @Html.LabelFor(m => m.UserName) @Html.TextBoxFor(m => m.UserName) </li> <li> @Html.LabelFor(m => m.Password) @Html.PasswordFor(m => m.Password) </li> <li> @Html.LabelFor(m => m.ConfirmPassword) @Html.PasswordFor(m => m.ConfirmPassword) </li> <li> @Html.LabelFor(m => m.Mobile) @Html.TextBoxFor(m => m.Mobile) </li> </ol> <input type="submit" value="Register" /> </fieldset> } @section Scripts { @Scripts.Render("~/bundles/jqueryval") }
Register model (AccountModel.cs)
public class RegisterModel { [Required] [Display(Name = "User name")] public string UserName { get; set; } [Required] [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] [DataType(DataType.Password)] [Display(Name = "Password")] public string Password { get; set; } [DataType(DataType.Password)] [Display(Name = "Confirm password")] [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] public string ConfirmPassword { get; set; } [Required] [DataType(DataType.PhoneNumber)] [Display(Name = "Mobile")] public string Mobile { get; set; } }
Register Action (AccountController.cs)
[HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public ActionResult Register(RegisterModel model) { if (ModelState.IsValid) { // Attempt to register the user try { WebSecurity.CreateUserAndAccount( model.UserName, model.Password, new { Mobile = model.Mobile }, false); WebSecurity.Login(model.UserName, model.Password); return RedirectToAction("Index", "Home"); } catch (MembershipCreateUserException e) { ModelState.AddModelError("", ErrorCodeToString(e.StatusCode)); } } // If we got this far, something failed, redisplay form return View(model); }
Finally, let’s register.
Let’s go ahead and run our SQL queries again and make sure the mobile number was actually saved to our UserProfile table during the registration.
Sweet! Registration successful, with mobile number saved to the UserProfile table.
Happy Coding…!
Download Sample Application: http://blog.longle.net/2012/09/26/multi-step-asp-net-mvc-4-registration-with-sms-using-twilio-cloud-communication-and-simplemembershipprovider-for-increased-user-validity/
I read this piece of writing completely concerning the comparison of
newest and preceding technologies, it’s awesome article.
LikeLike
I’ve learn a few just right stuff here. Certainly worth bookmarking for revisiting.
I surprise how so much effort you put to make this
sort of wonderful informative website.
LikeLike
Hi there, its fastidious paragraph on the topic of media print, we all
understand media is a impressive source of data.
LikeLike
Pingback: [RESOLVED]Asp.net Membership and Entity Framework | ASP Web Form Data Control
Pingback: [RESOLVED]Asp.net Membership and Entity Framework | ASP Questions & Answers
I read this post completely concerning the comparison of
hottest and earlier technologies, it’s awesome article.
LikeLike
I have been surfing online more than 3 hours today, yet I never
found any interesting article like yours. It is pretty worth enough for me.
Personally, if all site owners and bloggers made good content as you did,
the net will be much more useful than ever before.
LikeLike
It’s a shame you don’t have a donate button! I’d without a doubt donate to this fantastic blog!
I suppose for now i’ll settle for book-marking and adding your RSS feed to my Google account.
I look forward to brand new updates and will share this website with my Facebook group.
Chat soon!
LikeLike
When i run the update command it gives me an error ‘Invalid Column Name Mobile ‘
Help Me i am stuck . thanks in advance
LikeLike
Problem Solved.. Great tutorial .. Cheers []>
LikeLike
Excellent items from you, man. I have keep in mind your stuff
previous to and you’re just too great. I actually like what you’ve bought here, really like
what you’re saying and the way wherein you assert it.
You are making it enjoyable and you still care for to keep it sensible.
I cant wait to learn much more from you. This is actually a wonderful website.
LikeLike
I don’t even know how I ended up here, but I thought this post was good.
I do not know who you are but certainly you are going to a famous blogger if you are not
already 😉 Cheers!
LikeLike
This is exactly what I was looking for, thanks very much. I’m sure it’s saved me a lot of time!!
LikeLike
What does it mean “Seed your Roles and any Users you want to provision, also note the WebSecurity.InitializeDatabaseConnection method we are invoking.”?
I have no idea what you mean. Also, where does the code below that line go? New file?
LikeLike
I get an error when I followed ur tutorial: Cannot attach the file ‘C:.…\MvcApplication7\MvcApplication7\App_Data\MvcApplication7’ as database ‘MvcApplication7’. Is it because I moved public DbSet UserProfiles { get; set; } to my own Contextclass? I want to add some more DbSets.
LikeLike
Pingback: Good To Know: ASP .NET MVC Reference Guide | For the love of problems :)
Thanks a bunch for sharing this with all of us you really
realize what you are talking approximately! Bookmarked.
Please also consult with my website =). We may have a hyperlink exchange agreement
among us
LikeLike
What a data of un-ambiguity and preserveness of valuable familiarity regarding unexpected feelings.
LikeLike
Read on for little ways to save money, aand see
how your efforts caan really add upp over time. >>Here you juust
need to duscuss yyour preferences annd design of the cards.
It is not prwctical to find families that don’t have an idea about
this wonderful soft drink that works just like soda.
LikeLike
Thanks what a great post! Worked a treat, except I had to add the following to the “system.web” section of my app’s web.config:
Hope this helps someone else in future…!
LikeLike
Thanks. Just what I was looking for 🙂
LikeLike
Thanks what a great post! Worked a treat, except I had to add the following to the section of my app’s web.config:
Hope this helps someone else in future…!
LikeLike
Thank you very very Much!!! I wish more people would put out easy to comprehend information like this piece. So many of us try to answer with incomplete articles or comments with little how to detail information. Everyone should remember it someone is looking for and answer then they don’t know. 🙂 Once again fantastic piece keep it up. Helped me gain a day of work back. I hope to be able to return the favor some day.
Cheers!
LikeLike
Thanks JGills, for the positive feedback!
LikeLike
Great article!
LikeLike
Thanks Jeremy, for the positive feedback.
LikeLike
I changed my UserProfile table from userID to userGUID
Getting this error.
Cannot convert type ‘System.Guid’ to ‘int’
LikeLike
Pingback: Redundant explicit property name in C# warning - C# Questions Solutions - Developers Q & A
Awesome post, thanks for writing this up!
LikeLike
Thx for the positive feedback!
LikeLike
Hey there! Do you use Twitter? I’d like to follow you
if that would be ok. I’m definitely enjoying your blog and look forward to
new posts.
LikeLike
Hi cameronlucero, yes I’m on Twitter, https://twitter.com/LeLong37, thanks for the positive feedback and please follow me for updates…!
LikeLike
Pingback: H-Li | ASP.NET MVC 4使用技巧记录2: 如何进行Migrations和使用Simplemembership
Hello, I think your blog might be having browser compatibility issues.
When I look at your blog site in Ie, it looks fine but when opening in Internet Explorer, it has some overlapping.
I just wanted to give you a quick heads up! Other then that,
wonderful blog!
LikeLike
Wow, that’s what I was searching for, what a material! existing here at this website, thanks admin of this web page.
LikeLike
Hi
Thanks for the blog. Can you please tell how can I display a user’s first name instead of the username in the logged in view?
LikeLike
This is awesome!! really helpful for me. Thanks for sharing with us. Following links also helped me to complete my task.
http://www.mindstick.com/Articles/63bce1d2-3d08-48a1-a325-57754b1f000e/?Creating%20a%20simple%20model%20using%20ASP%20NET%20MVC4
http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-model
LikeLike
Undeniably believe that which you said. Your favorite justification seemed to be on the net
the easiest thing to be aware of. I say to you, I definitely get annoyed while people consider worries
that they just do not know about. You managed to hit the nail upon the top and also defined out the whole thing without having side-effects
, people could take a signal. Will likely be back to get more.
Thanks
LikeLike
Thank you, that was very helpful 🙂
LikeLike
Is it the file starting ‘building a composite mvc3….’?
That doesn’t seem right as I know SimpleMembership changed a lot between MVC3 & 4 no?
LikeLike
thanks for this – skydrive link is now dead?!
LikeLike
Nick,
I’ve updated the download link in the post with the live link, let me know if you have any trouble downloading it.
LikeLike
thanks! It now links to some files – but can’t see any about seeding (indeed seems to have 1 file selected; the wrong one)
LikeLike
BTW, there some extra code in their from another blog that used this sample as a starting point, you can just ignore it or even better take a look at it as well.
LikeLike
Is it the file starting ‘building a composite mvc3….’?
That doesn’t seem right as I know SimpleMembership changed a lot between MVC3 & 4 no?
LikeLike
Here’s the exact link:
http://blog.longle.net/2012/09/26/multi-step-asp-net-mvc-4-registration-with-sms-using-twilio-cloud-communication-and-simplemembershipprovider-for-increased-user-validity/
LikeLike
thanks bro – this Twilio stuff is super useful too!…
LikeLike
Anytime Nick, sounds like your working on some fun stuff…!
LikeLike
Thanks Le! I had come across that before in another MVC project with multiple contexts and required only one context to be part of migrations. The console is really good about the error message about multiple contexts also.
I was trying to migrate two contexts in the same project and the console states migrations can be on for only one context in a project.
This whole experiment was to work out the kinks integrating simpleMemberhship and some usefull application data as well.
Again, great article which provides another vector to possible solutions 🙂
LikeLike
I refactored the UsersContext to hold any additional application entities and that works. I just learned migrations can be on for only one context in a project. Unless you have any insight. Thanks again.
LikeLike
Sam, you need to run migrations while explicitly specifying which context you are running it for, you can actually do migrations for more than one context.
example: (from the package manager console):
update-database -ConfigurationTypeName “”
LikeLike
Oops. I wanted to add …. I’ve tried your solution out and it works. I thought I would try adding some additional model classes and context class. I found that EF Add-Migration doesn’t see the new model classes and pops up with the changes being empty. Is there something with multiple DBcontexts that I am implementing incorrectly?
Cheers.
LikeLike
Sam,
You need to make sure you have all your Entity Framework mapping classes implemented and these mapping classes need to be registered and added in the YourDbContext.OnModelCreating(DbModelBuilder builder) event.
Example:
LikeLike
Great Article Le.
LikeLike
Thanks for positive feedback!
LikeLike
hi,
How do you move all database operations to a class library project? I’ve come far, but the webpages_roles etc are not created in the database.
LikeLike
Not sure I understand what you mean by move all database operations to a class library? Also please download the sample solution and make sure it runs correctly, webpages_roles should be created. You may want to start with a fresh new empty database first and run the project.
LikeLike
What i meant was, that i enabled migrations in a class library project. i’m trying to seperate database access and the web site. so i moved websecurity etc too. i also created a datacontext class. the problem i’m facing right now, is that ‘Roles’ doesn’t excist in the current context. Even though i added System.Web.Security. which is the namespace of it. Anything else i might be missing?
LikeLike
never mind, i didn’t referenced system.web in the project. somehow i thought i did.
LikeLike
Reblogged this on Anthony Trimble.
LikeLike
Thanks for the Reblog!
LikeLike
Le, many thanks – you have provided the most concise example of how to set up forms based security that I have found, saving a great deal of time.
For those that have had issues such as Satish and Txumari – I experienced both of your problems. The root problem seems to be setting up the visual studio 2010 Server Explorer to look at the database.
Following Le’s outline with out running Server explorer all works. However, depending on when you set up the Server Explorer I hit either Satish or Txumair’s issues. Simply put: Do not use Server Explorer with SQL Express in this example.
One other small point, I did have to use SQL 2008 express configuration manager to enable a user of the form hostname\username. That is your laptop network name and your sign on name. This eliminated the error that demanded the database be initialized prior to use.
Once again, many thanks
T
LikeLike
Thanks T for the tip! Had similar issues using SQL Express.
LikeLike
Pingback: .Vb? Of .C# | Thomas Site Building
Hi. Thank you very much! I’ve spent 3 days on this task until I found your article. I had the same problem as txumari, but I think the reason was due to using default database before manipulations with it. There are no errors in a new created project !!!
LikeLike
Pingback: Code first create tables
Hi,
Great tut!
Suppose i want to add a table, How would i do that? I already tried to set up a table like the user profile, and did the update-database command. But at no avail…
LikeLike
Hi Long,
Very nice article.
Your SKYDRIVE download is no longer available though.
Might I have a copy ?
Best, LA Guy
LikeLike
there is a link to it in the one of the comments! 🙂
LikeLike
Hi Le
thanks a million for your post, it was so helpfull. However i would like to ask you, if there is a way instead of adding fields to the Userprofile table to save information in fields in another table (for example a custom table or the webpages_membership table).
I added 2 new fields (first name and last name) in the webpages_Membership table, sumbittted them with migrations, but saving them is not possible since they cannot be saved directly with the model.firstname since they are not in the UserProfile table.
Any ideas?
Again thanks for the awsome post!
Tolis
LikeLike
Hello!
Thank you for this post – it was really helpful to me. Saved me a lot of time and nerve. 🙂
Thank you!
But, if we wanna add more “atributes” in dB, for example: BirthDate, LastName, FirstName ,… How to do that?
I did try like adding the same way u add in your example PhoneNumber:
AccountModel.cs
…..
[Table(“UserProfile”)]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserEmail { get; set; }
……..
Configuration.cs
if (!WebSecurity.UserExists(“user123”))
WebSecurity.CreateUserAndAccount(
“user123”,
“123456”,
new { FirstName = “John” },
new { LastName = “Kent” },
new { UserEmail = “example@example.com” });
…….
But iv got error:
“No overload for method ‘CreateUserAndAccount’ takes 5 arguments” – what I have to do that this code work?
LikeLike
Good post!
LikeLike
thanks Olafur for the positive feedback!
LikeLike
Long Le …
u r awessome
LikeLike
bilalfazlani, thanks for the positive feedback. 🙂
LikeLike
Hi,
In you example, how you added the new field for Mobile data, how can you add this into the Manage action so the user can update that details freely?
LikeLike
download link is dead. anyone still got the project?
LikeLike
Look at comment #69 it has the link, I just got it from there a few day ago.
LikeLike
Got it [Authorize( Roles=”Administrator” ) ]
Great tutorial.
LikeLike
Awesome!
LikeLike
Hi Lee,
I’m know is not part of this tutorial but i was wondering if you can point me in the right direction. I would like to show only part of the menu if the person does not have the right roles. Sorry if this post does not belong here.
Thank you
LikeLike
Seems like all I have to do is ask and then It comes to me.. Sorry about that.
LikeLike
Glad you found your solution!
LikeLike
Hi Le,
Sorry but I can keep answering my questions. The duplicate on the code worked. Should have tried before.
The only thing pending is the [Administrator] not sure how to approach this.
Thanks,
Mark
LikeLike
Hi le,
Great tutorial, I got it running fast. I was wondering what do I need to do if I wanted to create a second role such as clients? Would it be with a dupplicate of the code in the web system.web
and another basic question 🙂 remember I’m new at this.
You would use [Authorize] to allow regular users to that part of the code. How would you use the Administrator. would it be [Administrator]?
LikeLike
Hi Le,
Sorry if this is to basic but I’m new at this. On the first part of your tutorial ->
“In the “System.Web” Section add:”
How do you add code to the System. Web.
Thanks,
Mark
LikeLike
Hi Le,
I was looking at the sample and I see that you added the coded in the Web.config file. I got it.
Thanks,
Mark
LikeLike
Awesome, glad you found it!
LikeLike
Hi Le,
I’ve read your article and it helped me a lot to get started with SimpleMembership. I’ve managed to implement SimpleMembership from scratch into a ASP.NET MVC 4 Basic Application, but I have a little issue yet.
The problem is that to implement SimpleMembership I needed to use the InitializeSimpleMembershipAttribute that comes with the ASP.NET MVC 4 Internet Application and I’m not finding a cool way to use this with the Repository Pattern because it directly references one specific Context and specific name of table for users.
Then at first I have two options: the first option is that on every single project I copy the Filter and change the configuration, directly referencing the context (which is not good, since I want to use repository pattern and interact with the context through the repository).
The second option, I’ve tryed to generalize the filter to any context, passing it to the filter as a Type object, but it again directly references the context.
Is there any better way to work with SimpleMembership and Repository Pattern in such a way that we get a good generalization, at the point that we can even move the filter to a separate assembly and reference it in any project ?
Sorry if my question is silly, but I’m beginner with ASP.NET MVC and SimpleMembership and I’m still struggling with such issues.
Thanks again for the article, your help and attention.
LikeLike
Pingback: ASP.NET MVC4 – Restricting Access within your Web Site. | NoobSquad
Hi this post has been really helpful, but i have a problem, I need to set up the membership and roles using a ModelFirst DB on another project on my solution and my Context is there so im not able to use migrations and when i try to initialize the web security it thows InvalidOperationException teling me that it can only be called once and if I delete de DB to crate it later it works but then the Role manager doesn’t work. I did every thing like you said but no results what do you think it might be
LikeLike
You may want to take a look at Filters/InitializeSimpleMembershipAttribute.cs, it’s being called there as well if this is an MVC 4 project.
LikeLike
Anyone know where you configure the simplemembership (for password format etc?) is it to be done in web.config like before?
LikeLike
Hello Le, Great Tutorial,
I have a problem though. In your code example, you don’t declare your SimpleRoleProvider anywhere for the Seed method?
So for me, the object Roles doesnt exist? what am i doing wrong?
LikeLike
I’ve solved that issue, but I get the same fault as paablo, even after referencing the version 2.0 of the WebMatrix.WebData.dll????
LikeLike
I’ve since figured this, Ive had to reference :-
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
using WebMatrix.WebData;
using WebMatrix.Data;
using System.Web;
LikeLike
Thanks for sharing this!
LikeLike
the download is gone!
LikeLike
You should be able to get the code here https://skydrive.live.com/redir?resid=949A1C97C2A17906!2391
LikeLike
Great article but I also run into a problem where the Package Manager Console tells me that “To call this method, the “Membership.Provider” property must be an instance of “ExtendedMembershipProvider”.”
Which is strange to me because I believe this happens when you call a method that you’re not supposed to from SimpleMembership. This happens when I do the update-database. I have nothing special in the Configuration file, just checking if some Role and User exist, and if not create them. Any idea?
LikeLike
Great work Le
Many Thanks
LikeLike
Sure thing, thanks for stopping by 🙂
LikeLike
Pingback: Simple Membership Provider in MVC4 | knflinks
how to do this with custom membership
i.e
–>
where CustomMembership.Providers.Custom2 is
public class Custom2 : WebMatrix.WebData.ExtendedMembershipProvider
{
// implemenet here
}
I tried but getting error
LikeLike
Excelent Tutorial!!
Best regards from Germany
Kai G.
LikeLike
Vielen Dank für Ihren Besuch! 🙂
LikeLike
Hi Le! Excellent Work! can I ask, what if I need another role, and the administrator can change its (the new record one) role?
LikeLike
Thanks twisttwist, are you asking how you can change a user’s role?
LikeLike
I managed to fix the problem I was having. My project was referencing the wrong version of WebMatrix.WebData
LikeLike
paablo, yey….! I was worried there wasn’t a solution for your issue 🙂
LikeLike
Congrats!
LikeLike
The code works great. All I have to do is alter the userprofile table to add the additional columns and then re-run PM>update-database -verbose and the seed data gets in.
LikeLike
My answer to my question: using System.Web.Security in the Configuration.cs.
Answer to the WebSecurity.InitializeDatabaseConnection error:
Create _AppStart.cshtml file in the root and put only this code:ç
@using WebMatrix.WebData;
@{
WebSecurity.InitializeDatabaseConnection(
“Your_database”,
“Your_table”,
“UserId”,
“UserName”, autoCreateTables: true);
}
Hope this helps
LikeLike
Thanks for taking the time to help us out onbermejo.
I hope your advice helped Oscar.
Unfortunately adding the reference to _AppStart.html did not make a difference. WebSecurity.InitializeDatabaseConnection just does not seem to run at all. I can put it in twice and not get a “you can only call once” error. Anyone who solves this will be my hero!
LikeLike
I don’t know, it’s working for me…
I have followed the guide with the last update of the visual.
Have you changed the webconfig?
”
…
”
Have you done all the commands from Package Manager Console?
LikeLike
AutomaticMigrationsEnabled = true;
in the Configuration.cs?
LikeLike
Yeah I have done all that stuff. There is more information on my stack overflow questions.
Basically, if I hit debug, WebSecurity.InitializeDatabaseConnection is called as expected. If I run “Update-Database” it doesn’t seem to get called anywhere, hence the error.
The only difference with my project really is that my project is split into a Domain and a WebUI project for the separate layers.
LikeLike
After creating a new C# MVC4 application in VS 2012, for migrations and simplemembership, do the following
1. Check the Connection String in the web.config. If using Machine\SQLExpress
2. In Web.Config
3. After PM> enable-migrations, in Configuration.cs
#region
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
using System.Web.Security;
using TSBVISTP.Models;
using WebMatrix.WebData;
using System.Collections.Generic;
#endregion
namespace TSBVISTP.Migrations
{
internal sealed class Configuration : DbMigrationsConfiguration
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(STPDBContext context)
{
// This method will be called after migrating to the latest version.
// You can use the DbSet.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = “Andrew Peters” },
// new Person { FullName = “Brice Lambson” },
// new Person { FullName = “Rowan Miller” }
// );
//
WebSecurity.InitializeDatabaseConnection(“DefaultConnection”, “UserProfile”, “UserId”, “UserName”,
autoCreateTables: true);
if (!Roles.RoleExists(“Administrator”))
Roles.CreateRole(“Administrator”);
if (!WebSecurity.UserExists(“UserGA”))
WebSecurity.CreateUserAndAccount(“UserGA”, “password”,
new
{
FirstName = “User”,
LastName = “GA”,
userAddress = “123 something dr”,
userCity = “Austin”,
userZip = “78750”,
WorkPhone = “512-555-5555”,
AlternatePhone = “512-668-7898”,
FaxNumber = “512-232-1212”,
EmailAddress = “Simitt@gmail.com”
}, false);
if (!Roles.GetRolesForUser(“UserGA”).Contains(“Administrator”))
Roles.AddUsersToRoles(new[] {“UserGA”}, new[] {“Administrator”});
//var students = new List
//{
// new Student { FirstMidName = “Carson”, LastName = “Alexander”, EnrollmentDate = DateTime.Parse(“2005-09-01”) },
// new Student { FirstMidName = “Meredith”, LastName = “Alonso”, EnrollmentDate = DateTime.Parse(“2002-09-01”) },
// new Student { FirstMidName = “Arturo”, LastName = “Anand”, EnrollmentDate = DateTime.Parse(“2003-09-01”) },
// new Student { FirstMidName = “Gytis”, LastName = “Barzdukas”, EnrollmentDate = DateTime.Parse(“2002-09-01”) },
// new Student { FirstMidName = “Yan”, LastName = “Li”, EnrollmentDate = DateTime.Parse(“2002-09-01”) },
// new Student { FirstMidName = “Peggy”, LastName = “Justice”, EnrollmentDate = DateTime.Parse(“2001-09-01”) },
// new Student { FirstMidName = “Laura”, LastName = “Norman”, EnrollmentDate = DateTime.Parse(“2003-09-01”) },
// new Student { FirstMidName = “Nino”, LastName = “Olivetto”, EnrollmentDate = DateTime.Parse(“2005-09-01”) }
//};
//students.ForEach(s => context.Students.Add(s));
//context.SaveChanges();
//var Staffs = new List
//{
// new Staff { FirstMidName = “Kim”, LastName = “Abercrombie”, HireDate = DateTime.Parse(“1995-03-11”) },
// new Staff { FirstMidName = “Fadi”, LastName = “Fakhouri”, HireDate = DateTime.Parse(“2002-07-06”) },
// new Staff { FirstMidName = “Roger”, LastName = “Harui”, HireDate = DateTime.Parse(“1998-07-01”) },
// new Staff { FirstMidName = “Candace”, LastName = “Kapoor”, HireDate = DateTime.Parse(“2001-01-15”) },
// new Staff { FirstMidName = “Roger”, LastName = “Zheng”, HireDate = DateTime.Parse(“2004-02-12”) }
//};
//Staffs.ForEach(s => context.Staffs.Add(s));
//context.SaveChanges();
//var departments = new List
//{
// new Department { Name = “English”, Budget = 350000, StartDate = DateTime.Parse(“2007-09-01”), PersonId = 9 },
// new Department { Name = “Mathematics”, Budget = 100000, StartDate = DateTime.Parse(“2007-09-01”), PersonId = 10 },
// new Department { Name = “Engineering”, Budget = 350000, StartDate = DateTime.Parse(“2007-09-01”), PersonId = 11 },
// new Department { Name = “Economics”, Budget = 100000, StartDate = DateTime.Parse(“2007-09-01”), PersonId = 12 }
//};
//departments.ForEach(s => context.Departments.Add(s));
//context.SaveChanges();
//var programs = new List
//{
// new Program { ProgramId = 1050, Title = “ASE”, Credits = 3, DepartmentId = 3, Staffs = new List() },
// new Program { ProgramId = 4022, Title = “ESC2”, Credits = 3, DepartmentId = 4, Staffs = new List() },
// new Program { ProgramId = 4041, Title = “SWEAT”, Credits = 3, DepartmentId = 4, Staffs = new List() },
// new Program { ProgramId = 1045, Title = “ESE”, Credits = 4, DepartmentId = 2, Staffs = new List() },
// new Program { ProgramId = 3141, Title = “ASE2”, Credits = 4, DepartmentId = 2, Staffs = new List() },
// new Program { ProgramId = 2021, Title = “SWT”, Credits = 3, DepartmentId = 1, Staffs = new List() },
// new Program { ProgramId = 2042, Title = “ABC”, Credits = 4, DepartmentId = 1, Staffs = new List() }
//};
//programs.ForEach(s => context.Programs.Add(s));
//context.SaveChanges();
//programs[0].Staffs.Add(Staffs[0]);
//programs[1].Staffs.Add(Staffs[1]);
//programs[2].Staffs.Add(Staffs[2]);
//programs[3].Staffs.Add(Staffs[2]);
//programs[4].Staffs.Add(Staffs[3]);
//programs[5].Staffs.Add(Staffs[3]);
//programs[6].Staffs.Add(Staffs[3]);
//programs[7].Staffs.Add(Staffs[3]);
//context.SaveChanges();
//var enrollments = new List
//{
// new Enrollment { PersonId = 1, ProgramId = 1050, Grade = 1 },
// new Enrollment { PersonId = 1, ProgramId = 4022, Grade = 3 },
// new Enrollment { PersonId = 1, ProgramId = 4041, Grade = 1 },
// new Enrollment { PersonId = 2, ProgramId = 1045, Grade = 2 },
// new Enrollment { PersonId = 2, ProgramId = 3141, Grade = 4 },
// new Enrollment { PersonId = 2, ProgramId = 2021, Grade = 4 },
// new Enrollment { PersonId = 3, ProgramId = 1050 },
// new Enrollment { PersonId = 4, ProgramId = 1050, },
// new Enrollment { PersonId = 4, ProgramId = 4022, Grade = 4 },
// new Enrollment { PersonId = 5, ProgramId = 4041, Grade = 3 },
// new Enrollment { PersonId = 6, ProgramId = 1045 },
// new Enrollment { PersonId = 7, ProgramId = 3141, Grade = 2 },
//};
//enrollments.ForEach(s => context.Enrollments.Add(s));
//context.SaveChanges();
//var officeAssignments = new List
//{
// new ClassAssignment { PersonID = 9, Location = “Class 1” },
// new ClassAssignment { PersonID = 10, Location = “Class 27” },
// new ClassAssignment { PersonID = 11, Location = “Class 304” },
//};
//officeAssignments.ForEach(s => context.OfficeAssignments.Add(s));
//context.SaveChanges();
var menus = new List
{
new Menu {Id = 1, Name = “Main”, MenuItems = new List()},
};
menus.ForEach(s => context.Menus.Add(s));
context.SaveChanges();
var menuitems = new List
{
new MenuItem
{
Id = 1,
Name = “Home”,
ActionName = “Index”,
ControllerName = “Home”,
Url = “”,
ParentMenu = menus[0]
},
new MenuItem
{
Id = 2,
Name = “Student”,
ActionName = “Index”,
ControllerName = “Student”,
Url = “”,
ParentMenu = menus[0]
},
new MenuItem
{
Id = 3,
Name = “Staff”,
ActionName = “Index”,
ControllerName = “Staff”,
Url = “”,
ParentMenu = menus[0]
},
new MenuItem
{
Id = 4,
Name = “Programs”,
ActionName = “Index”,
ControllerName = “Program”,
Url = “”,
ParentMenu = menus[0]
},
new MenuItem
{
Id = 5,
Name = “Residential”,
ActionName = “Index”,
ControllerName = “Department”,
ParentMenu = menus[0]
},
new MenuItem
{
Id = 6,
Name = “About”,
ActionName = “About”,
ControllerName = “Home”,
Url = “”,
ParentMenu = menus[0]
},
new MenuItem
{
Id = 7,
Name = “Contact”,
ActionName = “Contact”,
ControllerName = “Home”,
Url = “”,
ParentMenu = menus[0]
},
};
menuitems.ForEach(s => context.MenuItems.Add(s));
context.SaveChanges();
}
}
}
4. update-database -verbose
5. In SQL run update query to add columns
GO
ALTER TABLE [dbo].[UserProfile]
ADD [FirstName] VARCHAR (50) NULL,
[LastName] NVARCHAR (50) NULL,
[userAddress] NVARCHAR (50) NULL,
[userCity] NVARCHAR (50) NULL,
[userZip] NVARCHAR (50) NULL,
[WorkPhone] NVARCHAR (50) NULL,
[AlternatePhone] NVARCHAR (50) NULL,
[FaxNumber] NVARCHAR (50) NULL,
[EmailAddress] NVARCHAR (50) NULL;
6. PM> update-database -verbose
you must see migrations working.now.
LikeLike
Some content got eaten up above.
2. In Web.Config
and
LikeLike
Hello!
In the Configuration.cs the Role(f.e Role.RoleExists) does not exist in this context.
Any ideas?
LikeLike
Your sample app works fine. I am currently running it on the side of my project trying to work out the differences with no luck.
LikeLike
I think my problem is that the “WebSecurity.InitializeDatabaseConnection” is simply not running. I can place 2 of them in my Seed method and still get the same error – where as two from the OOTB sample project give the “The “WebSecurity.InitializeDatabaseConnection” method can be called only once.”
LikeLike
I have a stack overflow article if anyone wants to help me – http://stackoverflow.com/questions/13565347/cannot-seed-users-roles
Thanks!
LikeLike
Any Idea why I cannot apply this code example (that I can confirm works) to my own project? This is starting to drive me insane. Something so simple should not be this complicated. I can place the InitializeDatabaseConnection code more than once and it won’t throw the “InitializeDatabaseConnection has already been called” error. Really need help with this one.
LikeLike
Hi paablo,
Could you first confirm that the sample application works before implementing this into your solution? After doing so let me know and I try to guide you to integrating it into your project.
LikeLike
The explanation refers to changing the ‘User’ table yet the code still refers to the ‘Userprofile’ table !!. So yes this will all work except when it comes to retrieveing the value of the additional profile fields. as this still points at the ‘Userprofile’ table which hasn’t been extended or populated !!.
Example Code of Retrieving Profile Fied Values::
if (oSettings.Alert_Required_Locations_Changes)
{
using (var context = new UsersContext())
{
var profile = context.UserProfiles.SingleOrDefault(x => x.UserName == User.Identity.Name);
if (profile.Email.IsNotNullOrEmpty())
{
EMail.sendEmail(CONFIRM_LOCATION_REQUIRED, CONFIRM_CREATE_TO_BE_VALIDATED, profile.Email);
}
}
}
LikeLike
Jit,
Thanks you for sharing this.
LikeLike
Many thanks for this tutorial! It was very useful for me 🙂
LikeLike
Hi grim,
I’m glad this was helpful, thanks for stopping by 🙂
LikeLike
I get the same “You must call the “WebSecurity.InitializeDatabaseConnection” method before you call any other method of the “WebSecurity” class. This call should be placed in an _AppStart.cshtml file in the root of your site.” if I try and seed users/roles inside my initiation method via Update-Database. This error does not appear if I remove the seeding code, and I already call the WebSecurity.InitializeDatabaseConnection method in my Global.asax.cs.
LikeLike
I try to pass the las paremeter false, but I get the same error. Furthermore if my database exists without the new field “email” and I put a “false” how can I update my database?
LikeLike
Hi txumari,
For a sanity check could you please download and run the sample application just to validate that it works first?
LikeLike
When i try to run i get the following error am i missing anything?
You must call the “WebSecurity.InitializeDatabaseConnection” method before you call any other method of the “WebSecurity” class. This call should be placed in an _AppStart.cshtml file in the root of your site.
I followed your steps
LikeLike
Here is the actual error
Running Seed method.
System.InvalidOperationException: You must call the “WebSecurity.InitializeDatabaseConnection” method before you call any other method of the “WebSecurity” class. This call should be placed in an _AppStart.cshtml file in the root of your site.
at WebMatrix.WebData.SimpleRoleProvider.get_PreviousProvider()
at WebMatrix.WebData.SimpleRoleProvider.RoleExists(String roleName)
at System.Web.Security.Roles.RoleExists(String roleName)
at StreamingAdmin.Migrations.Configuration.Seed(StreamingDBContext context) in C:\Satish\StreamingAdmin\StreamingAdmin\Migrations\Configuration.cs:line 35
at System.Data.Entity.Migrations.DbMigrationsConfiguration`1.OnSeed(DbContext context)
at System.Data.Entity.Migrations.DbMigrator.SeedDatabase()
at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.SeedDatabase()
at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration)
at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.RunCore()
at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.Run()
You must call the “WebSecurity.InitializeDatabaseConnection” method before you call any other method of the “WebSecurity” class. This call should be placed in an _AppStart.cshtml file in the root of your site.
LikeLike
Satish – did you every find a solution? I am having the same issue.
LikeLike
satish, paablo: I had the same issue but sorted by adding the following line of code (same as in Configuration.cs) in Application_Start() method in my Global.asax.cs WebSecurity.InitializeDatabaseConnection(“DefaultConnection”, “Users”, “Id”, “UserName”, false);
LikeLike
This post was a ‘SUPERGLUE’ for my work.
Saved me many days of frustration.
Thank you very very very much.
May God Bless You.
LikeLike
Hi Tarig, glad this helped and thanks for stopping by. 🙂
LikeLike
Sorry the error in english is “There is already an object named ‘UserProfile’ in the database.”
LikeLike
Hi txumari,
You will can pass in false for the last parameter if your table already exists.
LikeLike
I’m trying this but when I try to update-database -verbose, return and error “Ya hay un objeto con el nombre ‘UserProfile’ en la base de datos.”
LikeLike
Hi Le, thanks for this. This is very useful.
I have a question: is the InitializeSimpleMembership attribute in the AccountController class still needed or can it be deleted? Thanks
LikeLike
Hi Jeremiah,
You can delete it, as long as you are calling WebSecurity.CreateUserAndAccount method from you Seed method in your /MIgrations/Configuration.cs class as illustrated in this blog post.
LikeLike
Great article. thanks. I’m using Nhibernate, but this has been very informative to get me going.
LikeLike
Rob, thanks for the positive feedback and stopping by! 🙂
LikeLike
Pingback: The term ‘enable-migration’ is not recognized as the name of a cmdlet, function, script file, or operable program. | | Yasser ShaikhYasser Shaikh
Hi Le will you be able to help me a bit and advice me on the best way I should allow the user to vie his details and edit them later if he requires. Also give him the chance to unsubscribe. Thank you very much in advance!
LikeLike
Thank you Le I managed doing it as you say also adding
WebSecurity.CreateUserAndAccount(
model.UserName,
model.Password,
new {FirstName = model.FirstName,
LastName = model.LastName,
City = model.City,
ZIP = model.ZIP,
Street = model.Street,
StreetNumber = model.StreetNumber,
Country = model.Country}, false
);
and it works perfectly. Now I need to work on the admin being able to edit these parameters. Thanks for the reply.
LikeLike
itiali, thanks for the positive feedback and stopping by, good luck on the Admin…!
LikeLike
Thanks. Your recipe for newing up additional columns in the WebSecurity.CreateUserAndAccount call was EXACTLY what I needed.
LikeLike
Hi Craig, thanks for the positive feedback and for stopping by..! 🙂
LikeLike
Hi great work really helpful. Would you be so kind to let me know if i would like to input more fields how can i work around the WebSecurity.CreateUserAndAccount(…….) for example I would like to input
model.UserName,
model.Password,
model.FirstName,
model.LastName );
Please any suggestion would be helpful and thanks in advance for any help! Regards, Ilia
LikeLike
Hi Ilia,
You will need to create those fields in your the user table you are using.
You can get those values in by using a dynamic object/class as the last parameter in the WebSecurity.CreateUserAndAccount method.
LikeLike
Hi Lee
Thank you very much for this post
If I want to add Administrator from View What should I do?
LikeLike
Hi David, you will need to create a view that with with a minimum of two text fields e.g. Username and Password. In your controller action or service that your injecting to invoke the WebSecurity.CreatUserAndAccount method.
SimpleMembershipProvider does not support the ASP.NET Configuration Site, the out of the box Admin screens that you can use to manage User, Roles, and Permissions with the other providers.
LikeLike
Hi, thanks for the good post. I have made use of this in my work.
I would like to clarify, if I wanted to use the email field in place of the user name, would I change:
WebSecurity.InitializeDatabaseFile(“SecurityDemo.sdf”, “Users”, “UserID”, “Username”, true);
to:
WebSecurity.InitializeDatabaseFile(“SecurityDemo.sdf”, “Users”, “UserID”, “Email”, true);
Then, within my MVC 4 app, in the account controller, login action I would place:
if (ModelState.IsValid && WebSecurity.Login(model.Email, model.Password, persistCookie: model.RememberMe))
{
return RedirectToLocal(returnUrl);
}
I would continue this, matching up the web security username with the user model email e.g:
private static string ErrorCodeToString(MembershipCreateStatus createStatus)
{
// See go.microsoft.com/fwlink for
// a full list of status codes.
switch (createStatus)
{
case MembershipCreateStatus.DuplicateUserName:
return “An account with that email already exists. Please use a different email or contact info@moneydrainplug.com.”;
.
.
.
Apologies for the long post and all the code, I hope it is still legible.
Thanks
LikeLike
Thanks Darrel for the update!
LikeLike
I just tried the sample of your link and could not download could you please provide the sample code again thanks
LikeLike
Hi diin, apologize for the late response, was attending TwilioCON 2012.
I can’t seem to find the exact project for this blog post on my cloud SkyDrive anywhere, however I do have another blog post that was based on this exact project, which has all of the sourcecode for this blog as well.
You can download it here:
http://blog.longle.net/2012/09/26/multi-step-asp-net-mvc-4-registration-with-sms-using-twilio-cloud-communication-and-simplemembershipprovider-for-increased-user-validity/
Let me know if this helps.
LikeLike
Pingback: Patrick Desjardins' Blog » Asp.Net MemberShip with MVC4
Hi Le,
I’ve gone through, and created a project based on the membership samples you’ve given here and begun to expand on it to include related tables.. However it seems the WebSecurity.CreateUserAndAccount method chokes when we have a self-defined ‘User’ table with foreign keys.
I have one-to-one and many-to-many relationships defined, and both cause errors similar to this: System.Data.SqlClient.SqlException (0x80131904): Invalid column name ‘PlayingTeams’.
PlayingTeams is a virtual ICollection and I’ve set up mapping like this in the OnModelCreating method:
modelBuilder.Entity()
.HasMany(t => t.Players)
.WithMany(p => p.PlayingTeams)
.Map(mc =>
{
mc.ToTable(“TeamPlayers”);
mc.MapLeftKey(“UserProfileId”);
mc.MapRightKey(“TeamId”);
});
What do you think..? Is there something missing, or are you perhaps aware of a limitation in the design of this?
Cheers, Aaron
LikeLike
Hi Aron,
I’m unaware of why this might be happening, currently my User table has foreign keys, however just not with a many-to-many relationship, and instead a one-to-one relationship. However looking at your modelBuilder code, it looks like you can’t insert a Player without inserting the user into a PlayingTeam, the WebSecurity.CreateUserAndAccount will not do this. You can test this theory by temporarily removing the many-to-many.
LikeLike
Hi Le,
Sorry for not writing earlier, I just returned from a short and much-needed break 🙂
I will check this out in the evening and see what sticks with some different approaches and write back afterwards.
Perhaps you’re right about the model builder code and I need to learn a bit more about how this fluent API works.
Cheers,
– Aaron
LikeLike
Great sample!
Could you hint how to access the custom user property from code after login?
LikeLike
Peter,
Thanks! So far the only way I know of at the moment, is to actually access custom user properties using EntityFramework itself.
LikeLike
Hi Le,
I have implemented your sample, and it Works perfektly – thanks for sharing 🙂
Do you know of any way to get the Id of a user from inside MVC4 so that I can use the .Find method of the DBContext or do I have to create a query searching for the UserName…
/re. Peter
LikeLike
Peter,
You are on the right track, you will have to query the UserProfile table using EntityFramework (your DBContext) by username.
LikeLike
In MVC4 you can use WebSecurity.CurrentUserId, from the WebMatrix.WebData interface, to access the user id directly.
LikeLike
thx, for the tip!
LikeLike
Thanks, very helpful, saved me quite some time.
Regards, Hans
LikeLike
Hans,
Thanks for the positive feedback, and I’m glad you found the post helpful.
LikeLike
Pingback: Multi-Step ASP.NET MVC 4 Registration with SMS using Twilio Cloud Communication and SimpleMembershipProvider for Increased User Validity « Long Le's Blog