Please read the paragraph EDIT2 for the actual state of the question
I am trying to add an initial account to my database while a migration is running, to ensure access to my application.
Unfortunatly the table AspNetUsers is not changed after the Seed method is finished and I can't find a proper way to debug for possible errors.
Configuration.cs
internal sealed class Configuration : DbMigrationsConfiguration<ApplicationDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
ContextKey = "Namespace.Models.ApplicationDbContext";
}
protected override void Seed(ApplicationDbContext context)
{
var manager = new UserManager<ApplicationUser>(
new UserStore<ApplicationUser>(
new ApplicationDbContext()));
var user = new ApplicationUser()
{
UserName = "admin",
Email = "admin#admin",
LastName ="lname",
FirstName = "fname"
};
manager.Create(user, #"gibberish");
/* context.SaveChanges(); ?valid */
}
}
After issuing the update-database -force -verbose command the pm console writes The Seed method is being executed (free translation from German), but as stated above the table is not updated with a new user.
Where did I go wrong?
EDIT:
I just tried the following:
if (!context.Roles.Any(r => r.Name == "Administrator"))
{
var store = new RoleStore<IdentityRole>(context);
var manager = new RoleManager<IdentityRole>(store);
var role = new IdentityRole { Name = "Administrator" };
manager.Create(role);
}
which did work. So a role named Administrator has been created after Update-Database -Force was issued. The user however, not.
EDIT2:
So apparently I found the culprit.
I was trying to make sure that an admin account was always available. Therefor I tried to add a user username-admin. However this did not work. After some time I thought about trying it with a different approach and changed the username to username. Now this did the trick and the user was added and pushed into the role Administrator.
The question remains: why does it not work adding a user with a special character like -?
By default, UserName can only be alphanumeric, i.e. not even an email address is allowed. You need to turn off the validation or implement your own validator (as easily found on SO), e.g.
_userManager = new UserManager<IdentityUser>(_userStore);
_userManager.UserValidator = new UserValidator<IdentityUser>(_userManager) { AllowOnlyAlphanumericUserNames = false };
Related
I can't seem to find an answer for this anywhere. I'm using a custom membership provider and membership user with my own tables, which is appearing to be far too much hassle than it's worth. When updating a user record it appears that I need to update it's membership user instance as well, otherwise where I'm relying on data from membership user it isn't corresponding to the updated database.
I've created my own update membership user method, as the existing one only accepted it's own MembershipUser class:
public static void UpdateAccountUser(AccountUser accountUser)
{
// Custom MembershipUser
ToMembershipUser user = new ToMembershipUser(
"AccountUserMembershipProvider",
accountUser.FirstName + " " + accountUser.LastName,
accountUser.ID,
accountUser.Email,
"",
"",
true,
false,
DateTime.Now,
DateTime.MinValue,
DateTime.MinValue,
DateTime.MinValue,
DateTime.MinValue);
// Fill additional properties
user.ID = accountUser.ID;
user.Email = accountUser.Email;
user.FirstName = accountUser.FirstName;
user.LastName = accountUser.LastName;
user.Password = accountUser.Password;
user.MediaID = accountUser.MediaID;
user.Media = accountUser.Media;
user.Identity = accountUser.Identity;
user.CreatedAt = accountUser.CreatedAt;
user.UpdatedAt = accountUser.UpdatedAt;
UpdateCookie(user.Email);
}
private static void UpdateCookie(string email)
{
HttpCookie cookie = FormsAuthentication.GetAuthCookie(email, true);
var ticket = FormsAuthentication.Decrypt(cookie.Value);
// Store UserData inside the Forms Ticket with all the attributes
// in sync with the web.config
var newticket = new FormsAuthenticationTicket(ticket.Version,
ticket.Name,
ticket.IssueDate,
ticket.Expiration,
true, // always persistent
email,
ticket.CookiePath);
// Encrypt the ticket and store it in the cookie
cookie.Value = FormsAuthentication.Encrypt(newticket);
cookie.Expires = newticket.Expiration.AddHours(24);
HttpContext.Current.Response.Cookies.Set(cookie);
}
Now obviously this is just creating a new instance and not updating the existing one, which doesn't allow me to see the updated details without logging out and logging back in. Any ideas?
Edit
So I managed to find an example of someone else using their own custom update method, but all they appear to be doing is updating the database not the MembershipUser itself. I'm already doing this?!
I attempted to instead just update the FormsAuthenticationCookie and then when calling Membership.GetUser() I at least pass an updated User.Identity.Name, but to no avail, still old data even though database is updated. I've ran out of ideas...
This could possibly be a repeat of yesterday's question MembershipUser not getting updated result from database
I eventually found out the MembershipUser wasn't updating due to every time I calling GetUser() the query involved was using FirstOrDefault(). Turns out this caches the result rather than retrieving a fresh result. By adding AsNoTracking() to the query itself I now get the updated result, without having to even call UpdateUser().
I am working on a project which was almost complete. I didn't use SQL server, rather I used inbuilt database in Asp.net 4.5.1. At first everything was perfect - like when I am registering a user, AspNetUsers table gets updated. Now I deleted all the contents of my table and registering the same user - it says name asag******#gmail.com has already taken. Even if I registered new user, AspNetUsers table is not updated...
Code-(inbuilt)
protected void btnsubmit_Click(object sender, EventArgs e)
{
var manager = Context.GetOwinContext().GetUserManager<ApplicationUserManager>();
var signInManager = Context.GetOwinContext().Get<ApplicationSignInManager>();
var user = new ApplicationUser() { UserName = txtemailid.Text, Email = txtemailid.Text };
IdentityResult result = manager.Create(user, txtpass.Text);
if (result.Succeeded)
{
-
-
-
-
}
I am getting result =false. It says user already exists.
I've set up the Continuous Deployment in Microsoft Azure (Web App) using a ButBucket Git repo. Code First Migrations works well on my computer, it creates tables and seeds them, but when I sync the branch, the seed method of the migration is not run on Azure.
So Azure gets the changes from BitBucket, creates the tables as needed, but does not run the seed method (every table remains empty).
Can you suggest a solution to run the Seed method on Azure automatically when a new migration is applied (or after every time Azure builds from BitBucket if that is the only solution)?
Additional Info:
MigrationHistory table contains the migrations, so they were run.
I've set AutomaticMigrationsEnabled = true; but the problem remains
On Azure there is a Web App which is built and migrated, and an SQL Database which is referenced in the ConnectionString in Web.config
Configuration.cs
internal sealed class Configuration : DbMigrationsConfiguration<MyInsidR.Models.ApplicationDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
ContextKey = "MyInsidR.Models.ApplicationDbContext";
}
protected override void Seed(ApplicationDbContext context)
{
// This method will be called after migrating to the latest version.
// You can use the DbSet<T>.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" }
// );
//
context.Prophecies.AddOrUpdate(p => p.ID,
new Prophecy() { ID = 1, Text = "Fűben iszogatós, sírva nevetős."}
);
context.Interesteds.AddOrUpdate(x => x.ID,
new Interested() { ID = 1, Email = "teszt.elek#gmail.com", FirstName = "Elek", LastName = "Teszt", RegistrationDate = DateTime.Now }
);
var tag1 = new Tag() { ID = 1, Name = "Karaoke", ApplyTo = TagApplication.All, Type = TagType.Games };
var tag3 = new Tag() { ID = 3, Name = "4 rooms", ApplyTo = TagApplication.All, Type = TagType.Misc };
var tag4 = new Tag() { ID = 4, Name = "Helipad", ApplyTo = TagApplication.All, Type = TagType.Vip };
context.Tags.AddOrUpdate(x => x.ID,
tag1, tag3, tag4
);
var indicatorIcon1 = new IndicatorIcon() { ID = 1, VisualClass = IndicatorIcon.VisualClassType.Hidden, Name = "No Indicator Icon", Description = "Nothing special, just a regular place or event." };
var indicatorIcon2 = new IndicatorIcon() { ID = 2, VisualClass = IndicatorIcon.VisualClassType.Fire, Name = "Hot", Description = "This place or event is very popular at the moment. There are big parties and a big fuss around it." };
context.IndicatorIcons.AddOrUpdate(x => x.ID,
indicatorIcon1, indicatorIcon2
);
AddUserAndRole(context);
}
bool AddUserAndRole(ApplicationDbContext context)
{
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(context));
var identityResult = roleManager.Create(new IdentityRole("Admin"));
var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
var user = new ApplicationUser()
{
UserName = "myinsidr#gmail.com",
};
identityResult = userManager.Create(user, "Qwertz1234!");
if (identityResult.Succeeded == false)
return identityResult.Succeeded;
identityResult = userManager.AddToRole(user.Id, "Admin");
return identityResult.Succeeded;
}
}
(I've found questions and solutions related to seed method issue only for direct deployment from Visual Studio, but that's not the way I would like to go.
Also there are solutions using different SQL management projects, but I think code first migrations inside the MVC project is the cleanest solution if it works like on my local machine)
I have found out how to run the Seed method every server start using this technique: http://romiller.com/2012/02/09/running-scripting-migrations-from-code/
Running Seed at every server start is pretty good for me, since it will run after every build by Azure Continuous Deployment. Of course it will run in other cases as well, but my method is not too long, so it does not matter.
I put the following code to Global.asax --> Application_Start():
var migrator = new DbMigrator(new Configuration());
migrator.Update();
As
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
// CODE FIRST MIGRATIONS
#if !DEBUG
var migrator = new DbMigrator(new Configuration());
migrator.Update();
#endif
}
What this does is basically running a Code First Migration at every server start.
I've seen not hundred but THOUSANDS of example where from scratch to complete examples with MVC identity 2.0 are done but not a single one with bloody web forms and the one which are present are not even worth while just very basic.
I'm working on an application where I've three roles, user,admin,superUser and all these are in AspNetRoles table because I'm using identity 2.0. now when I create a user I also assign that user one of these roles too.
before this role and stuff I've worked on customize roles system as we use to do on desktop applications.
so here I tried all the links and articles written on CodeProject about form authentication and all that what we can do in web.config but nothing was helpful
Please take a look at this screen shot http://prntscr.com/6ca09i you might get a little idea what I mean by that.
My C# code on register is
protected void btnSubmit_Click(object sender, EventArgs e)
{
//owin entity
var userStore = new UserStore<IdentityUser>();
userStore.Context.Database.Connection.ConnectionString =
System.Configuration.ConfigurationManager
.ConnectionStrings["GCR"].ConnectionString;
var manager = new UserManager<IdentityUser>(userStore);
//string userInfor;// = new UserInformation();
// check if the url contains an id perameter
if (!String.IsNullOrWhiteSpace(Request.QueryString["id"]))
{
var id = Convert.ToInt32(Request.QueryString["id"]);
var userInfo = new UserInformation
{
Email = txtEmail.Text,
FirstName = txtFirstName.Text,
LastName = txtLastName.Text,
AddressLine1 = txtAddressLine1.Text,
AddressLine2 = txtAddressLine2.Text,
City = txtCity.Text,
State = ddlState.SelectedValue,
ZipCode = Convert.ToInt32(txtZip.Text),
PhoneNumber = txtPhone.Text,
RoleId = Convert.ToInt32(ddlRole.SelectedValue)
and here is my registration page where I am assigning the roles which are not actually getting assigned http://prntscr.com/6ca1xi
Now please tell me how can I create role based app where in a single folder we have different files which User with different role can get access
Please I'd already wasted my two days on Identity I have no wich to waste more time on it
This is how you are going to properly deal with this
var userInfo = new UserInformation
{
Email = txtEmail.Text,
FirstName = txtFirstName.Text,
LastName = txtLastName.Text,
AddressLine1 = txtAddressLine1.Text,
AddressLine2 = txtAddressLine2.Text,
City = txtCity.Text,
State = ddlState.SelectedValue,
ZipCode = Convert.ToInt32(txtZip.Text),
PhoneNumber = txtPhone.Text,
RoleId = ddlRole.SelectedValue
Fist your role should be some text value because it does not take role as id
after saving this object or model above `db.saveChanges();
you in the end are going to add this role to aspnetroles table and how you are going to do that is very simple just a single line
// add role to the user which is created right now
manager.AddToRole(userInfo.GUID, ddlRole.Text.Trim());
The first argument is the id of the user and the second one is the dropdown in which you are selecting the user roles and you can also do that role exist stuff in it. now how you are going to check this one page load is very simple
and its just like this
#region page load
if (!IsPostBack)
{
if (User.IsInRole("admin") || User.IsInRole("superuser"))
{
}
else
{
string unAuthorizedRedirect = WebConfigurationManager.AppSettings["UnAuthorizedRedirect"];
Response.Redirect("~/" + unAuthorizedRedirect);
}
}
#endregion
I hope this helps you completely
I got the roles from aspnetroles table and this is how I got those
var context = new ApplicationDbContext();
var roleStore = new RoleStore<IdentityRole>(context);
var roleMgr = new RoleManager<IdentityRole>(roleStore);
if (User.IsInRole("admin"))
{
//come here
}
I have a doubt. I am using Asp.net mvc5 in VS2013. When the user is logged in, username of the logged in user can be identified using,
User.Identity.GetUserId
But i couldn't be able to identify the role of the user in the view page.
I tried the following:
#{
var store = new Microsoft.AspNet.Identity.EntityFramework.UserStore<RaspberryPi.Models.ApplicationUser>(new RaspberryPi.Models.ApplicationDbContext());
var manager = new Microsoft.AspNet.Identity.UserManager<RaspberryPi.Models.ApplicationUser>(store);
var l = manager.IsInRole(User.Identity.GetUserId, "Moderator");
}
But resulted in error.
CS1928: 'Microsoft.AspNet.Identity.UserManager<RaspberryPi.Models.ApplicationUser>' does not contain a definition for 'IsInRole' and the best extension method overload 'Microsoft.AspNet.Identity.UserManagerExtensions.IsInRole<TUser>(Microsoft.AspNet.Identity.UserManager<TUser>, string, string)' has some invalid arguments
How can i do that?
Please help,
Thanks
The exception is pretty self explanatory really, the parameters you are providing do not tie up with the IsInRole extension method.
The problem (assuming your code is exactly as you have shown) is thatGetUserId is a function, not a property, therefore you need to actually call it
manager.IsInRole(User.Identity.GetUserId(), "Moderator");
Does your ApplicationUser derive from IdentityUser?
public class ApplicationUser : IdentityUser
This should work in the cshtml
#{
var context = new RaspberryPi.Models.ApplicationDbContext();
if (context.Users.Any(u => u.UserName == User.Identity.Name))
{
var store = new Microsoft.AspNet.Identity.EntityFramework.UserStore<applicationuser>();
var manager = new Microsoft.AspNet.Identity.UserManager<applicationuser>(store);
ApplicationUser user = manager.FindByName<applicationuser>(User.Identity.Name);
if (manager.IsInRole(user.Id, "Moderator") == true)
{
// Do whatever you want...
}
}
Or if you want to do it the simple way just do this.
#if (User.IsInRole("Moderator")){
}