I have little problem with my api and its account-management. Whenever a user creates a new account, it has to be confirmed by clicking on a link that is sent by email. That works perfectly fine.
However, when the user clicks on the link, it opens up a blank browser window. Now I'd like to redirect the user to a webpage that offers instructions for the application. After a bit of research, I found the "redirect(string url)" command.
[HttpGet]
[AllowAnonymous]
[Route("ConfirmEmail", Name = "ConfirmEmailRoute")]
public async Task<IHttpActionResult> ConfirmEmail(string userId = "", string code = "")
{
if (string.IsNullOrWhiteSpace(userId) || string.IsNullOrWhiteSpace(code))
{
ModelState.AddModelError("", "User Id and Code are required");
return BadRequest(ModelState);
}
IdentityResult result = await this.AppUserManager.ConfirmEmailAsync(userId, code);
if (result.Succeeded)
{
Redirect("http://www.orf.at");
return Ok();
}
else
{
return GetErrorResult(result);
}
}
The address should only be an example. Whenever one clicks on a link, however, the browser still opens a blank tab. Is there a possibility to avoid that? The best solution would be to redirect the user to another site. But if that does not work, can it somehow be prevented that a new window is opened up?
Instead of returning Ok() return Redirect("http://www.orf.at");
if (result.Succeeded)
{
return Redirect("http://www.orf.at");
}
else
{
return GetErrorResult(result);
}
Related
I have a fairly standard Login action, but I want to change the redirect depending on the user role.
However, there's some sort of race condition going on: HttpContext.User says it yielded no results, causing the admin user to be redirected to the wrong homepage.
How do I 'wait' correctly until the HttpContext.User is available after signing in?
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginDto loginDto)
{
if (!ModelState.IsValid)
{
return View(loginDto);
}
var result = await _signInManager.PasswordSignInAsync(loginDto.Username, loginDto.Password, true, false);
if (!result.Succeeded)
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(loginDto);
}
// This check doesn't always work because User = null
if(HttpContext.User.IsInRole(RoleEnum.Administrator.ToString())){
return LocalRedirect(Url.Action("Index", "Home", new { area = "Admin" }));
}
return LocalRedirect(loginDto.ReturnUrl ?? Url.Action("Index", "Home"));
}
User UserManager instead of HttpContext in this scope like below
var userInRole = await _userManager.IsInRoleAsync(user, role);
I am trying to create user with UserManager and CreateAsync method, but it doesn't work. Im postman I always get 200 OK
My Post method
[HttpPost]
public async Task<IActionResult> Register()
{
User user = new User { Email = "asfa#gmail.com", UserName = "asfa#gmail.com" };
var result = await _userManager.CreateAsync(user, "SS22!faasd");
if (result.Succeeded)
{
// install cookie
await _signInManager.SignInAsync(user, false);
}
else
{
foreach (var error in result.Errors)
{
//how can i see my errors here
}
}
return Ok();
}
Also I dont have any cshtml files, so I cant output them on page.
Or you can just explain, why my CreateAsync method doesn't work.
You could just return the result from the server every time:
return Ok(result);
It will be serialized so you can see it.
I'm able to authenticate using anything for a password. The email has to be a valid registered email, but the pwd doesn't matter. Everything else is working normally.
Any suggestions on where to start trouble shooting this? I haven't found any similar issues in web searches.
My view...
My action in the account controller...
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(AccountLoginModel viewModel)
{
if (!ModelState.IsValid)
return View(viewModel);
var user = _manager.FindByEmail(viewModel.Email);
if (user != null)
{
await SignInAsync(user, viewModel.RememberMe);
string uid = user.Id;
return RedirectToLocal(viewModel.ReturnUrl);
}
ModelState.AddModelError("", "Invalid username or password.");
return View(viewModel);
}
and the signinasync method...
private async Task SignInAsync(IdentityUser user, bool isPersistent)
{
// Clear any lingering authencation data
FormsAuthentication.SignOut();
// Create a claims based identity for the current user
var identity = await _manager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
// Write the authentication cookie
FormsAuthentication.SetAuthCookie(identity.Name, isPersistent);
}
I did create a seperate MVC web project to see the scaffolded login action, which is quite a bit different. The SmartAdmin template is customized enough that its difficult to start changing things without knowing what I'm effecting. Any direction is appreciated.
If username in your system is email, you should use
var user = _manager.FindAsync(viewModel.Email, viewModel.Password);
and then signin the user if it's not null.
If username is not email, you should first get the user and then check for password
var user = _manager.FindByEmail(viewModel.Email);
bool isPasswordCorrect = await _manager.CheckPasswordAsync(user, viewModel.Password);
I'm learning asp.net mvc.I'm trying to do sample application with visual studio mvc template.
Login system ok for google but i have problem about signing with facebook account.
At the first step is done.
I'm redirected Associate your Facebook account page.
When i entered my Username and click the button i'm getting Object reference not set to an instance of an object for "info" variable at the blow code.
public async Task<ActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl)
{
if (User.Identity.IsAuthenticated)
{
return RedirectToAction("Manage");
}
if (ModelState.IsValid)
{
// Get the information about the user from the external login provider
var info = await AuthenticationManager.GetExternalLoginInfoAsync();
if (info == null)
{
return View("ExternalLoginFailure");
}
var user = new ApplicationUser() { UserName = model.UserName };
var result = await UserManager.CreateAsync(user);
if (result.Succeeded)
{
result = await UserManager.AddLoginAsync(user.Id,info.Login);
if (result.Succeeded)
{
await SignInAsync(user, isPersistent: false);
return RedirectToLocal(returnUrl);
}
}
AddErrors(result);
}
ViewBag.ReturnUrl = returnUrl;
return View(model);
}
I had the same exact issue and solved it by updating the Facebook Nuget Packet.
After some research I finally found out the solution thanks to the information given in this StackOverflow question&answer.
I've inherited a system which was written in MVC. This system uses the asp.net membership api, which works well. I've just discovered a bug however whereby the user is unable to change his/her password.
The system displays the form to enter in the old password, and the new password twice to confirm, however on clicking submit, it just redisplays the form, and does not change the password.
I've gone through the code but as I'm new enough to MVC, and using the membership api, I can't see anything overly wrong with it.
Here is the GET and POST code from within the Account Controller. If anyone could see anything wrong with this, I would greatly appreciate it. If anyone needs me to post additional information/code, please ask :)
Also, after debugging through the code, what seems to happen is, after
if (ModelState.IsValid)
is hit, the nested if statement within this is skipped and the code jumps straight down to the bottom to redisplay the form.
[Authorize]
public ActionResult ChangePassword(string source)
{
ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
ViewData["source"] = source;
if (!string.IsNullOrEmpty(source))
{
return View("ChangePassword", source);
}
return View("ChangePassword", "User");
}
[Authorize]
[HttpPost]
public ActionResult ChangePassword(ChangePasswordModel model, FormCollection formValues)
{
string source = formValues["source"];
if (formValues["btnCancel"] != null)
{
RedirectToRouteResult result = null;
// The user has clicked cancel. Redirect back to source!
//
switch (source)
{
case "user":
result = RedirectToAction("Index", "ManageAccount", new { Area = "User" });
break;
case "administrator":
result = RedirectToAction("Index", "ManageAccount", new { Area = "Administrator" });
break;
}
return result;
}
if (ModelState.IsValid)
{
if (MembershipService.ChangePassword(User.Identity.Name, model.OldPassword, model.NewPassword))
{
return RedirectToAction("Index", "ManageAccount", new { Area = "User" });
}
else
{
ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
}
}
// If we got this far, something failed, redisplay form
ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
ViewData["source"] = source;
return View("ChangePassword", formValues["source"], model);
}
Maybe you could check for the Errors as stated here
ASP.NET MVC Model State