ASP.NET MVC : calling a controller from another controller - asp.net-mvc

I am writing a web application with ASP.NET MVC, and I would like to call a controller from another controller. More precisely I would like to call a routine in the Login controller, where I do sign in and sign out, from the controller where I allow the normal user to change his/her password. Thus, I check the old password (given by the user in the change password form).
I tried to search in the internet methods to change user (not Administrator) password but I didn't find anything good.
Thank you.

I didn´t called a controller from another controller, instead I called my User Administration Controller AdminController from a View within the HomeController controller (via na input button).
Then the code of my routine EditByUser in the AdminController was written as:
[HttpPost]
[Authorize]
public async Task<IActionResult> EditByUser(string email, string passwordnew, string passwordconf)
{
AppUser user = await userManager.FindByEmailAsync(email);
if (user != null)
{
IdentityResult validEmail
= await userValidator.ValidateAsync(userManager, user);
if (!validEmail.Succeeded)
{
AddErrorsFromResult(validEmail);
}
IdentityResult validPassnew = null;
bool passNewEqPassConf = passwordconf == passwordnew;
if (!passNewEqPassConf)
{
ModelState.AddModelError("", "New Password not equal to Confirmation!");
}
if (!string.IsNullOrEmpty(passwordnew) && passNewEqPassConf)
{
validPassnew
= await passwordValidator.ValidateAsync(userManager, user, passwordnew);
if (validPassnew.Succeeded)
{
user.PasswordHash = passwordHasher.HashPassword(user, passwordnew);
}
else
{
AddErrorsFromResult(validPassnew);
}
}
if (((validEmail.Succeeded && validPassnew == null)
|| (validEmail.Succeeded
&& passwordnew != string.Empty && validPassnew.Succeeded)) && passNewEqPassConf)
{
IdentityResult result = await userManager.UpdateAsync(user);
if (result.Succeeded)
{
return RedirectToAction("Index", "Home", new { email = user.Email });
}
else
{
AddErrorsFromResult(result);
}
}
}
else
{
ModelState.AddModelError("", "User not found!");
}
return View(user);
}
However, I didn't manage to check the old password… The sign in is made on another controller…

Related

why login page in asp.net mvc loads very slow?

this is my controller
#region Authentication
public ActionResult Login()
{
return View();
}
[HttpPost]
public ActionResult Login(string username, string password)
{
// Lets first check if the Model is valid or not
if (ModelState.IsValid)
{
bool userValid = itreedb.Users.Any(user => user.UserName == username && user.Password == password && user.Approved == true);
// User found in the database
if (userValid)
{
//
// Save un and pw into cookies
HttpCookie auth = new HttpCookie("auth", Request.Form["username"] + "|" + Request.Form["password"]);
auth.Expires.AddDays(30);
Response.Cookies.Add(auth);
// Redirect the user to the index page
return Json(new { IsValidLogin = true });
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View();
}
When I try to insert my admin informations it takes more than 5 minutes to be authentified .The others pages reload normally. What can I do?
`

MVC 5 Identity Login and "Remember Me" - What needs to be done to get it set up?

I have the following code in my Account controller:
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
ApplicationUser user = null;
// In order to authenticate, we need a user name. Let's find it based on the email address.
user = await this.UserManager.FindByEmailAsync(model.Email);
if (user != null)
user = await this.UserManager.FindAsync(user.UserName, model.Password);
if (user != null && user.EmailConfirmed)
{
await this.SignInAsync(user, model.RememberMe);
return this.RedirectToLocal(returnUrl);
}
else
{
ModelState.AddModelError(string.Empty, "Either your username or password is invalid, or your email address has not yet been confirmed");
}
}
// If we got this far, something failed, redisplay form
return this.View(model);
}
It appears that "Remember Me" is already being handled with this snippet of code:
if (user != null && user.EmailConfirmed)
{
await this.SignInAsync(user, model.RememberMe);
return this.RedirectToLocal(returnUrl);
}
However, it doesn't seem to be working reliably. Is there anything else that needs to be done to set up "Remember Me?"
you can use this code
FormsAuthentication.SetAuthCookie(user.UserName, model.RememberMe);

Require login before doing a action

Thank everyone read my topic. But i need your help !
I've got a problem with Asp.NET MVC Action.
In HomePage. I have a link redirect to an action call checkTicket(), but require login.
So, in checkTicket() method. I'm using following code to check permision
if (Request.IsAuthenticated)
{
return View();
}
else
{
return RedirectToAction("Login", "Account");
}
But in action Login of Account controller. How can i return back to checkTicket's View() ?
This is something i want.
HomePage (click) -> checkTicket (require) -> Login (return) -> checkTicket()
Create a cookie that is set, letting you know that the user wants to checkticket but is not logged in:
if (Request.IsAuthenticated)
{
return View();
}
else
{
//The cookie's name is UserSettings
HttpCookie myCookie = new HttpCookie("UserSettings");
//The subvalue of checkticket is = true
myCookie["checkticket"] = "true";
//The cookie expires 1 day from now
myCookie.Expires = DateTime.Now.AddDays(1d);
//Add the cookie to the response
Response.Cookies.Add(myCookie);
return RedirectToAction("Login", "Account");
}
Then in your Login Action, check if the cookie exists like so:
if (Request.Cookies["UserSettings"] != null)
{
string userSettings;
if (Request.Cookies["UserSettings"]["checkticket"] != null)
{
userSettings = Request.Cookies["UserSettings"]["checkticket"];
}
if(userSettings) {
//redirect to checkticket
} else {
// redirect to your normal view
}
}
*Code courtesy of MSDN: write cookie, read cookie

Custom login with mvc messing up with the login partial view

So I've set up a custom login in my MVC application which appears to work...
public ActionResult Login()
{
return View();
}
[HttpPost]
public ActionResult Login(User model, string returnUrl)
{
if (ModelState.IsValid)
{
if (model.Login())
{
FormsAuthentication.SetAuthCookie(model.Username, true);
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "Invalid email address or password.");
}
}
// If execution got this far, something failed, redisplay form
return View(model);
}
public class User
{
public bool Login()
{
var user = db.Users.FirstOrDefault(u => u.EmailAddress == EmailAddress);
if (user == null)
{
throw new ValidationException("User not found.");
}
else
{
// validates whether or not the password on the user record
// that was retrieved by the query matches the password entered at login
return Hashing.ValidatePassword(Password, user.Password);
}
}
}
Unfortunately, there's some conflict between it and the default _LoginPartial.cshtml View (which looks like below):
#model LoganMVC.Models.User
#if (Request.IsAuthenticated) {
<text>
Hello, #Html.ActionLink(User.Identity.Name, "Manage", "Account", new { User.Identity.Name })!
#using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm" })) {
#Html.AntiForgeryToken()
Log off
}
</text>
} else {
<ul>
<li>#Html.ActionLink("Register", "Register", "Account", routeValues: null, htmlAttributes: new { id = "registerLink" })</li>
<li>#Html.ActionLink("Log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" })</li>
</ul>
}
The ArgumentNullException highlights this line...
Hello, #Html.ActionLink(User.Identity.Name, "Manage", "Account", new { User.Identity.Name })!
Saying...
Value cannot be null or empty.
It's clear that the value that cannot be null or empty is User.Identity.Name, but what isn't clear is WHY IsAuthenticated is true to begin with. This is Forms Authentication and, as far as the software is aware (because I killed the debug server, closed the solution and started debugging fresh again), the application has never run before.
Okay I've been bashing my head against various hard surfaces trying to get this one figured out and eventually did.
After looking at the errors I was initially getting:
Value cannot be null or empty.
And then later
The provided identity of type 'System.Web.Security.FormsIdentity' is marked IsAuthenticated = true but does not have a value for Name. By default, the anti-forgery system requires that all authenticated identities have a unique Name. If it is not possible to provide a unique Name for this identity, consider setting the static property AntiForgeryConfig.AdditionalDataProvider to an instance of a type that can provide some form of unique identifier for the current user.
Were fairly simple fixes.
First off, I had initially set my login cookie to persist. This means that it wouldn't be deleted when the browser is closed and would not expire either. While this did not cause the Value cannot be null or empty error, it was contributory in that the site was finding it and assuming a user had authenticated.
FIX
To fix this, I simply cleared cookies from my browser set the cookie's persist to false. This allowed me to focus more on the actual problem.
Value cannot be null or empty
This problem was actually not as complicated as I thought. When I started taking a closer look at things, I noticed that there was an error in the following code:
[HttpPost]
public ActionResult Login(User model, string returnUrl)
{
if (ModelState.IsValid)
{
if (model.Login())
{
FormsAuthentication.SetAuthCookie(model.Username, true);
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "Invalid email address or password.");
}
}
// If execution got this far, something failed, redisplay form
return View(model);
}
This post captures an instance of my User model from the form (which is the login form so only EmailAddress and Password values are included). It also uses the Username value from this model (which is null) to set the Authentication Cookie.
I changed my .Login() method to a function that returns a User if the email address is found and the stored hash matches a hash of the password entered for the login.
The code, thus, changed to the following (this is only the key point of the change)
// Account.Login Post
if (ModelState.IsValid)
{
var user = model.Login(model.EmailAddress);
if (user == null)
{
ModelState.AddModelError("", "Invalid email address or password.");
}
FormsAuthentication.SetAuthCookie(user.Username, true);
// create session variables n such
}
// User.Login
public User Login(string EmailAddress
{
var user = dbContext.Users.FirstOrDefault(u => u.EmailAddress == Email);
if (user == null)
throw new Exception("User not found.");
if (Hashing.ValidatePassword(Password, user.Password))
return user;
return null; // if we got here, something went wrong
}
Once I'd fixed this, I got another problem later. Some issue to do with the Anti-Forgery system.
While not a solution, I managed a workaround and commented out the following line from my _LoginPartial View:
#Html.AntiForgeryToken()
I had concerns about security but I figured that Forms Auth on a basic asp.net website with a hashed and salted password has been sufficient for quite a number of years, so I shouldn't have any issues with it here.
You probably miss something. In your controller Account you have an Action:
public ActionResult Manage(string name) // I presume name
{
....
}
Then your line should be:
Hello, #Html.ActionLink(User.Identity.Name, "Manage", "Account", new { name=User.Identity.Name })!
The anonymous object which is routeValues
It's n object that contains the parameters for a route. The parameters are retrieved through reflection by examining the properties of the object. The object is typically created by using object initializer syntax.(Definition taken from MSDN) And it should be well formatted.
I hope it will solve the problem otherwise you have to check if the User.Identity is different of null.
I have noticed also somthing else in this line:
var user = db.Users.FirstOrDefault(u => u.EmailAddress == EmailAddress);
Where comes from the EmailAddress after ==?
You should provide a parameter to you Login method to replace your second EmailAddress.
public bool Login(string emailAddress)
{
var user = db.Users.FirstOrDefault(u => u.EmailAddress == emailAddress);
if (user == null)
{
throw new ValidationException("User not found.");
}
else
{
// validates whether or not the password on the user record
// that was retrieved by the query matches the password entered at login
return Hashing.ValidatePassword(Password, user.Password);
}

mvc c# url change makes me signed in as another user, how to prevent this?

I am using following code for user authentication
Home Controller:
------------------
[AllowAnonymous]
[HttpPost]
public JsonResult JsonLogin(SecurityDTO usr)
{
var cnt = _ipres.CheckLoginCount(usr);
if (cnt == 1)
{
var logDet = _ipres.GetUser(usr);
if (logDet != null)
{
var dto = new SecurityDTO
{
Id = logDet.Id,
UserName = logDet.username,
Password = logDet.password,
Email = logDet.Emailid,
UTID = logDet.UTID,
};
Session[USER] = dto;
}
if (logDet != null)
{
switch (logDet.UTID)
{
case 1:
Session["UType"] = "admin";
return Json(new { success = true, redirect = Url.Action("Index", "Admin", new { area = "Admin" }) });
case 2:
Session["UType"] = "user";
return Json(new { success = true, redirect = Url.Action("Index", "User", new { area = "User" }) });
case 3:
Session["UType"] = "client";
return Json(new { success = true, redirect = Url.Action("Index", "Client", new { area = "Client" }) });
default:
Session["UType"] = null;
break;
}
}
}
else
{
ModelState.AddModelError("", "Invalid Username or Password");
}
return Json(new { errors = GetErrorsFromModelState() });
}
Base Controller:
------------------
public SecurityDTO UDTO { get; set; }
protected override void OnActionExecuting(ActionExecutingContext act)
{
if (Session["UType"] != null)
{
UDTO = (SecurityDTO)Session[HomeController.USER];
base.OnActionExecuting(act);
}
else
act.Result = RedirectToAction("Index", "Home", new { area = "" });
}
This works pretty well for authentication. After successful login I redirect the user to an area according to his user type. All controllers in area implement base controller. Lately I found this not effective because of following reason. When I logged in as user my url will be ~/AppName/User/User/ViewName. But when I do some tampering with url and change it as ~/AppName/Admin/Admin/ViewName it takes me to that page even though I am not an admin user. I am still logged in as user but I have access to all admin features. Basically when I change user type in url it considers me as that user type. But intended behaviour is to redirect the user to login page when url tampering occurs like this. Can I do something like recognising user type change in base controller and redirect the user to login page? please show the right way to do this... Thanks in advance.
You can add page level authentication where you check if user is having permission to page else redirect him, also have a look at https://stackoverflow.com/a/5184363/87956

Resources