this my code for login :
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = UserManager.FindByNameAsync(model.UserName);
var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
if (returnUrl != null)
return RedirectToLocal(returnUrl);
else if (await UserManager.IsInRoleAsync(user.Id, "Admin")) //<= Checking Role and redirecting accordingly.
return Redirect("~/Admin/Home/");
else
return Redirect("~/User/Home");
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
}
but it show me this error :
Argument 1: cannot convert from 'int' to 'string' GoKhoda
show error in this line :
else if (await UserManager.IsInRoleAsync(user.Id, "Admin"))
this line for find user and role of user for redirect to page .
how can i solve this ?
Edit
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
// You can write your own provider and plug it in here.
manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser>
{
MessageFormat = "Your security code is {0}"
});
manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser>
{
Subject = "Security Code",
BodyFormat = "Your security code is {0}"
});
manager.EmailService = new EmailService();
manager.SmsService = new SmsService();
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider =
new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
}
Edit(2)
When i using the .TosString()
show me this error .
IMHO your error is more than just int
to String
conversion, it is related to FindByNameAsync
method. The problem occurs when IsInRoleAsync
method requested for UserId
property but the property doesn't exist in ApplicationUser
class (related to Dapper mapping issue).
According to MVC - InvalidOperationException: UserId not found, ensure FindByNameAsync
to include Id
property in ApplicationUser
like this one (use your EF database context if you have it instead of query statement):
public async Task<ApplicationUser> FindByNameAsync(string userName)
{
ApplicationUser result = null;
using (var conn = await GetOpenDBConnection())
{
try
{
// note that UserId does not exist on ApplicationUser by default
// thus we need to adjust the query statement
var queryResults = await conn.QueryAsync<ApplicationUser>(
"SELECT UserId AS [Id], UserName, Email FROM dbo.Users WHERE UserName = @UserName;",
new { UserName = userName });
result = queryResults.FirstOrDefault();
}
catch (Exception ex)
{
// handle exception
}
}
return result;
}
Alternatively you may try FindByName
method instead of FindByNameAsync
there.
Regarding the await
usage error, the exception explains that only one async operation allowed at a time in given context (see Multi-async in Entity Framework 6?), hence you need to move await
outside if-condition or create a new context before executing second await
:
var isInRole = await UserManager.IsInRoleAsync(user.Id.ToString(), "Admin");
// inside switch...case
if (returnUrl != null)
return RedirectToLocal(returnUrl);
else if (isInRole) //<= Checking Role and redirecting accordingly.
return Redirect("~/Admin/Home/");
else
return Redirect("~/User/Home");
or change to IsInRole
if it still throwing exception:
if (returnUrl != null)
return RedirectToLocal(returnUrl);
else if (UserManager.IsInRole(user.Id.ToString(), "Admin")) //<= Checking Role and redirecting accordingly.
return Redirect("~/Admin/Home/");
else
return Redirect("~/User/Home");
This may or may not solve your entire issue, but may explain what should you do to handle async-related issues.
Related problems:
MVC InvalidOperationException adding role to user