MVC Role based routing clarification - asp.net-mvc-3

Small Question at the end of a very long explanation ...
Assuming the Admin User belonging to Admin Role and the Regular User belonging to User Role attempt to access the Index page with the following route registered in Global.asax.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] {"tst.Controllers"}
);
In the HomeController, the Index Action Method is decorated with the Authorize attribute.
[Authorize]
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View();
}
Forcing the anonymous user to logon.
If the Admin User logs in with his/her credentials, I would like to redirect him/her to the Index Action Method in the HomeController located in the Admin area.
If a Regular user logs in, I would like to redirect him/her to the Index Action Method in the HomeController located in the User area.
I have the following code in UserAreaRegistration.cs
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"User",
"Profile/{action}",
new { area = AreaName, Controller = "Home", action = "Index" },
new { RoleConstraint = new RoleConstraint()},
new[]{ "tst.Areas.User.Controllers"}
);
}
and the following code for AdminAreaRegistration.cs
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Admin",
"Profile/{action}",
new { area = AreaName, Controller = "Home", action = "Index" },
new { RoleConstraint = new RoleConstraint()},
new[]{ "tst.Areas.Admin.Controllers"}
);
}
Where the RoleConstraint is defined as follows
public class RoleConstraint: IRouteConstraint
{
public bool Match(
HttpContextBase httpContext,
Route route,
string parameterName,
RouteValueDictionary values,
RouteDirection routeDirection)
{
RoleProvider rp = new tst.Providers.CustomRoleProvider();
string[] roles = rp.GetRolesForUser(httpContext.User.Identity.Name);
if (roles != null && roles.Length > 0)
{
string roleName = roles[0];
string areaName = route.Defaults["area"].ToString();
return areaName == roleName;
}
return false;
}
}
The stock standard LogOn Action Method in the AdminController in the main Controllers folder...
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (Membership.ValidateUser(model.UserName, model.Password))
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl)
&& returnUrl.Length > 1
&& returnUrl.StartsWith("/")
&& !returnUrl.StartsWith("//")
&& !returnUrl.StartsWith("/\\"))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "The user name or password is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
Question:
Am I right in thinking that, When the Admin/Regular User is validated he/she must be redirected in this line in the code snippet above
return RedirectToAction("Index", "Home");
to the appropriate Index Action Method(Read: Index Action Method in the appropriate Area).
If so, I would like to know how.
I am confused because a constant string "Profile" is involved and it is not the usual stuff involving an action method and a controller name. "Profile" is neither a controller nor an action method.
Inspired by this post
MVC role-based routing

Instead of
return RedirectToAction("Index", "Home");
in the LogOn Action Method, I replaced it with
return Redirect("/Profile");
It worked !!!
However, what I don't understand is, when I click Log Off, it renders the Index page in the main Views folder. So I have to click LogOff again to be taken back to the LogOn page.

Related

How to redirect from Identity Area to Admin in ASP.NET CORE 2

I cant redirect from Identity Area:
if (role=="Admin")
{
return RedirectToAction("Index","Home",new { Area=Input.Role ,id=9});
}
To Admin Area Controller-Home,Action-Index.Always redirect me to Index in the Identity Area;
looking at your code I am still scratching my head as to the reason that someone would specify the Role at login. Can you articulate the reasoning behind this?
Simplest answer is inline with the code within the OnPostAsync(); that resides in
//this because of the routes you have in StartUp.cs
[Authorize(Roles ="Admin")]
[Area("admin")]
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
Login.cs Page...
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(Input.Username, Input.Password, Input.RememberMe, lockoutOnFailure: true);
if (result.Succeeded)
{
var user = await userManager.GetUserAsync(User); // Claims Principle
if (await userManager.IsInRoleAsync(user, "Admin"))
{
//SIMPLEST ANSWER since you using mixed environment with PAGES
return LocalRedirect("~/admin");
}
//TODO:
_logger.LogInformation("User logged in.");
return LocalRedirect(returnUrl);
}
Check your issues below one by one:
I got error A method 'CakeStore.App.Areas.Admin.Controllers.HomeController.Index (CakeStore.App)' must not define attribute routed actions and non attribute routed actions at the same time, you should not define [HttpGet(Name ="AdminPanel")] and [Route(nameof(Admin) + "/[controller]")] at the same time.
//[HttpGet(Name ="AdminPanel")]
[Area(nameof(Admin))]
[Route(nameof(Admin) + "/[controller]")]
public IActionResult Index()
{
return View();
}
For var role = this.roleManage.GetUrl(Input.Username);, it will retrive the role by username, check whether you got expected role Admin.
return RedirectToAction("Index","Home",new { Area=Input.Role ,id=9});, you did not define id in Index, there is no need to add id route.

redirecting authorized users to certain pages

I used the identity to assign roles to users.now I want to redirect users according to their role to certain pages.for example user with role"user" after login redirects to a page says" hello user".different from that of admin and so on.I have created the pages and validate authorization each .but where should I redirect after login?
You can simply change the login post action to check the user and redirect to the correct view.
Create separate view for normal users.
NormalUser.cshtml
#{
ViewBag.Title = "Normal User";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Hello User!</h2>
Inside the controller
[Authorize(Roles = "user")]
public ActionResult NormalUser()
{
ViewBag.Message = "Hello normal user.";
return View();
}
Then Login post action
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
return View(model);
}
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, change to shouldLockout: true
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
var user = await UserManager.FindByEmailAsync(model.Email);
var userRole = await UserManager.GetRolesAsync(user.Id);
if (userRole.Any(role => role == "user"))
{
RedirectToAction("NormalUser", "Home");
}
else
{
RedirectToAction("Index", "Home");
}
return RedirectToLocal(returnUrl);
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);
}
}
Check this github Project to get the code.

How to send data from view to controller in MVC3

Hello everyone I would like to ask how to send data from view to controller ? I would like to describe my question with my controller and view as you can see below
Here is the login action controller
[HttpPost]
public ActionResult Login(Panel model, string Username, string Password, string CaptchaValue, string InvisibleCaptchaValue)
{
bool cv = CaptchaController.IsValidCaptchaValue(CaptchaValue.ToUpper());
bool icv = InvisibleCaptchaValue == "";
if (!cv || !icv)
{
ModelState.AddModelError(string.Empty, "The Captcha Code you entered is invalid.");
}
if (ModelState.IsValid)
{
if (model.Username == Username && model.Password == Password)
{
FormsAuthentication.SetAuthCookie(model.Username, false);
return RedirectToAction("index", "Home");
}
else
{
ModelState.AddModelError("", "Check your name or password");
}
}
return View();
}
So when user login, redirect to Home/index view. At this point everything is okey.
Here is my index view:
[Authorize]
public ActionResult index()
{
return View();
}
My question is how can I hold user's password parameter and send from index view to different controller to use this parameter in controller method but how ? For example I would like to use password parameter at my index_test controller method in where clause but first of all I need to send this data from index.
public ActionResult index_test()
{
return View(db.contents.Where(x => x.test_parameter== password).ToList());
}
You have to add a parameter to your action method:
public ActionResult index_test(string password) { ...
In Your view you can either send data to the action via a standard link:
#Html.ActionLink("Click me", "index_test", "Controller",
new { password = "StringOrVariable")
Or by doing a form post:
#using(Html.BeginForm("index_test")) {
<input type="hidden" name="password" value="mypassword" />
add some fields
<input type="submit" value="Send" />
}
In your view post the form back to the controller, for example
<form action = "yourcontroller/youraction" method = "POST" enctype = "multiparrt/form-data">

Url routing in mvc 3.0

I want to have below specific Url routing for my website
http://www.MyWebsite?Region=US&Area=South
based on passed Region and Area query string parameter, i want to redirect to a specific controller action.
Problems:
What should be the Url Routing ?
Whether creating a common controller action which redirects to specific action will work here?
Any help would be greatly appriciated !!
Thanks
If you want to do querystring right off the root, then you need to map routes in global this way. Inside your action you can access context and grab querystring from it. Below is my example to do twitter style usernames, but idea is the same.
routes.MapRoute("UserSettings",
"{username}/settings",
new { controller = "Home", action = "Settings", username = "" },
new { username = new NotNullOrEmptyConstraint() }
);
public class NotNullOrEmptyConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{
try
{
return !String.IsNullOrEmpty(values["username"].ToString());
}
catch (Exception)
{
return false;
}
}
}
public ActionResult Settings(string username){
}

Add User Roles on Registration (Forms Authentication) MVC3

I am developing an MVC 3 project and want to add a user to a role when they are registered, using Forms Authentication. So I'd like to create some check boxes, or a drop down list showing the roles, which are selected and the user is assigned to the role as they are registered.
I have this code so far, which works:
public ActionResult Register()
{
ViewData["roleName"] = new SelectList(Roles.GetAllRoles(), "roleName");
return View();
}
And in the view I have:
<label for="roleName">Select Role:</label>
#Html.DropDownList("roleName")
#Html.ValidationMessage("roleName")
This is HttpPost section of the controller, and this is the part that I don't know what to code:
[HttpPost]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// Attempt to register the user
MembershipCreateStatus createStatus;
Membership.CreateUser(model.UserName, model.Password, model.Email, null, null, true, null, out createStatus);
if (createStatus == MembershipCreateStatus.Success)
{
FormsAuthentication.SetAuthCookie(model.UserName, false /* createPersistentCookie */);
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", ErrorCodeToString(createStatus));
}
}
// If we got this far, something failed, redisplay form
return View(model);
So, all the roles do show up in the view. All I need to know is what to add to the HttpPost section to get this working.
Thanks a lot, Amy
if (createStatus == MembershipCreateStatus.Success)
{
Roles.AddUserToRole(model.UserName, "RoleName");
FormsAuthentication.SetAuthCookie(model.UserName, false /* createPersistentCookie */);
return RedirectToAction("Index", "Home");
}
Try this. It's should work

Resources