Include JavaScript based on ActiveDirectory Membership - asp.net

I've got a single page application and in the start page I've linked to the ActionResult "_ADMIN()"
#Html.Action("_ADMIN")
Depending on the user's group membership, this ActionResult returns either an EmptyResult or its view:
public ActionResult _ADMIN()
{
if (User.IsInRole("admin"))
{
return View();
}
else
{
return new EmptyResult();
}
}
Its view consists of this one line:
#Scripts.Render("~/bundles/admin")
This works but feels suboptimal. I could copy the start page and create seperate ones for non-admins and admins, but that would be even more suboptimal. I'm using MVC 4.
What's a better way to include a bundle of JavaScript only if the current user is in a certain Active Directory group?

You can add scripts depending on roles. Like that :
if (User.IsInRole("admin"))
{
#Scripts.Render("~/bundles/admin")
}
And on your Action method you add attribute then the user will be automatically redirected to the login page if it does not have rights. You can add this attribute also on whole class.
[Authorize(Roles = "admin")]

I would only show the link to admin users:
if (User.IsInRole("admin"))
{
#Html.Action("_ADMIN")
}
Then, in the event a non-admin tried to access the action method, I would block the request at the action method:
[Authorize(Roles = "admin")]
public ActionResult _ADMIN()
{
return View();
}

Related

How can I force the user login before go to any where in my application?

I'm working on the asp.net mvc5 project, my problem is forcing the user login then they can go anything on my site. I'm using Session to check user login or not (I'm not using Identity or Authorization).
Here is my Login code:
[HttpPost]
public ActionResult Login(User user)
{
if (IsValid(user.username, user.password))
{
Session["username"] = user.username;
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", "Login details are wrong.");
}
return View(user);
}
I can check the user login or not with Session but I cannot deny the user access to the link, if I have to do this manually, I will need to add the block code below to any action in every controller I have.
public ActionResult Index()
{
if (Session["username"] != null)
{
//then user can go anywhere with any link
}
else
{
//user cannot go to here without login
}
}
There is any way I can force the user to redirect to the login page (if they are not login) when they click on any link or type the link in the browser? I was searching about config the route or using filter config but it seems not to solve my problem. I hope there has the general way to do this without adding the check-code manually to each controller/action.
Thanks for reading my problem, I will be very appropriated any comment to help me solve this.
One possible way to tackle on this globally is to override the OnActionExecuting method on the controller, that does the check and redirects to the homepage if no user is logged or allows the action if there is a user.
This can be done on a base controller so that it applies to all the website (by making all controllers inherit from this one).
public abstract class LoginRequiredController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (Session["username"] != null)
{
base.OnActionExecuting(filterContext);
}
else
{
//Redirect to the main page, or login, or somewhere else, without running the requested action
filterContext.Result = Redirect("/");
return;
}
}
}
Controllers inheriting from this one will check on each request that there is a user, and redirected to the main page in case there isn't one, without needing to copy/paste this check for each method.
Of course, the login controller should not inherit from it or it would be impossible to login at all.

ASP.Net MVC Authentication - Hide Element in View based on roles

Is there a possibility to hand over the Result of the Authorize-Attribute to the View?
Let's assume I want to hide 5 links in my Index view based on the memberships of a User.
[Authorize(Roles = "Admin")]
public ActionResult Index(){
....
}
The code above will prevent all users that are not part of the Admin-Group from visiting the Index page.
#{
if(User.IsInRole("Admin"){
Some link to be hidden
}
}
This code will hide the link if the User is not part of the Admin role. This is basically what I want BUT using this method I have to change the role name on every hidden link if the role would change.
Isn't there something like a combination of both? (Schema see below)
[Authorize(Roles = "Admin")] //This will pass true to the View if the User is a member of the group "Admin"
public ActionResult Index(){
....
}
#{
if(User.IsAuthenticated){ //This will read the "Token" and if it's true the if statement will get executed.
Some link to be hidden
}
}
So - if the User is in Role "Admin" the link will be shown. Is this possible?
You could use ViewBag and ViewData among other things, but I'd suggest passing a model back to the view with properties indicating whether to display the links or not.
public class YourViewModel()
{
public bool ShowHiddenLinks { get; set; }
// ... whatever other properties
}
In your controller you'd then do:
[Authorize(Roles = "Admin")]
public ActionResult Index()
{
var yourVm = new YourViewModel();
yourVm.ShowHiddenLinks = true;
return View(yourVm);
}
And your view becomes:
#model YourViewModel
/* ShowHiddenLinks is true & this view is meant for admins only,
so show admin-related links */
#if (Model.ShowHiddenLinks)
{
Some link to be hidden
}
I've named the viewmodel property ShowHiddenLinks on purpose, so that it becomes re-usable for views meant for other users as well. You can of course extend the viewmodel to feature properties for other roles (e.g. a view which is accessible by admins and moderators, each with their own distinct set of hidden links), or create one viewmodel per roleā€”it all depends on the scenario.

asp.net mvc 4 custom urls for action method

I am creating a asp.net mvc 4 application
public class AspNetController : Controller
{
//
// GET: /AspNet/
public ActionResult Index()
{
return View();
}
public ActionResult Introduction()
{
return View();
}
}
as Shown Above There is AspNet Controller and Introduction Action Method
Default Url for Introduction Action Method is
localhost:55134/aspnet/introduction
But I Want Url Like
localhost:55134/aspnet/introduction-To-AspNet
Same for
/localhost:55134/aspnet/NetFrameWork To
/localhost:55134/aspnet/What-is-.Net-Framework
How to do that
You should be able to use the ActionName attribute to decorate your routes.
[ActionName("Introduction-To-AspNet")]
public ActionResult Introduction()
{
return View();
}
You really want to use AttributeRouting, either via a 3rd party package or natively if you can.
Technically this concept comes under Routing in ASP.NET MVC.
For this you need to do an entry for route in App_Start->RouteConfig.cs file under RegisterRoutes(RouteCollection routes)
For Example:
routes.MapRoute(
"customRouteName",
"aspnet/introduction-To-AspNet",
new { controller = "AspNet", action = "Introduction" });
here aspnet/introduction-To-AspNet will append after your base url i.e. localhost:55134/
The quick and dirty answer is to add a route to your ~/AppStart/RouteConfig.cs file and it will be taken care of:
routes.MapRoute(
name: "CustomRoute",
url: "Aspnet/Introduction-To-AspNet",
defaults: new { controller = "Home", action = "AspNet", id = UrlParameter.Optional }
);
However, I'm assuming this is for some type of blog? I would reccomend that you have an action method called view, and then use your name as a parameter for the article. That way, you don't have to go in and edit the code every time you add a new article or other content:
public class ArticlesController : Controller
{
public ActionResult ViewArticle(string? title)
{
ViewBag.Article = title;
return View();
}
}
that way, your URL would be www.yoursite.com/Articles/ViewArticle/Introduction-To-AspNet. In general, you don't want to add tons of specific routes to your route config if you can avoid it. That being said, if this is a legacy system, the route table may be the only way.
EDIT
Ok, so what you can do is pass the string into the ViewBag and use a case statement to determine which partial view to show (I think this just might be your ideal solution):
<!--cshtml view-->
#switch(ViewBag.Article)
{
case 'Introduction-To-AspNet':
#Html.Partial('pathToPartialView.cshtml')
break;
case 'Some-Other-Article'
#Html.Partial('pathToAnotherPartialView.cshtml')
break;
...
...
default:
#Html.Partial('invalidArticleName.cshtml')
break;
}
The controller will pass the article name through the ViewBagand then you can use the case statement to figure out which article to render... and of course, the real secret sauce you've been looking for: #Html.Partial('URL') - this will take your partial and render it right were you put that in the page. You can also pass objects to that just as an FYI.
In addition, make sure that you have a default action on the switch statement that will show some sort of 404 page that indicates that the name in the URL was invalid. You ALWAYS want to have this anytime you're taking user input from the URL because people monkey with URLs all the time (and more innocently, copy+paste them wrong/incompletely all the time)

User is still signed in after AuthenticationManager.SignOut()

When I sign out a user in a controller, User.Identity.Authenticated is still true on the returned view.
If I refresh the page again, then User.Identity.Authenticated is false
// GET: /Account/SessionExpired
[AllowAnonymous]
public ActionResult SessionExpired()
{
AuthenticationManager.SignOut();
//Clear the session
SessionHelper.Clear();
return View();
}
Is it normal?
Thank you
Yes that is normal as the authorization is checked before the action executes. If you want to log out before that you have to do it before that, for example with a custom attribute
The standard MVC template in Visual Studio uses a RedirectToAction to instead of returning a View. That way the browser is automatically redirected to for example the home/index action from a new request.
// GET: /Account/SessionExpired
[AllowAnonymous]
public ActionResult SessionExpired()
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
//Clear the session
SessionHelper.Clear();
return View();
}

MVC3 logged in User can see only own stuff apart from Admin

A novice to asp.net and mvc3. I am learning by setting myself challenges/developing an application. I tag all record tables where users interact with ProviderUserKey. Now I want to be able to restrict users logged in to be able to edit or delete their own records only but administrators can edit or delete any. I have been using scaffolding to generate controllers and views etc. for eg code for editing`// POST: /Post/Edit/5
[HttpPost]
public ActionResult Edit(PJpost pjpost)
{
if (ModelState.IsValid)
{
db.Entry(pjpost).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(pjpost);
}`
Any help will be highly appreciated.
If you have a generic Edit method/action and you would like to keep it that way, I would add a method in your controller somethink like ValidateOwnership(record). This method would need to verify if CurrentUser's ID is matching the one on the record and if user is a member of particular role - that can be done with RoleManager class. Method would return true/false.
When you got it ready just put the call to the method in your code after ModelState validation. It would look like this
[HttpPost]
public ActionResult Edit(PJpost pjpost)
{
if (ModelState.IsValid)
{
if(IsOwnershipValid(pjpost){
db.Entry(pjpost).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
else {
ModelState.AddModelError("ERROR","You're not allowed to do that");
return View(pjpost);
}
}
return View(pjpost);
}
EDIT :
So the OwnershipValidation could look like this :
public bool ValidateOwnership(Pjpost pjpost) {
if (pjpost.MemUID == Membership.GetUser().ProviderUserKey.ToString())
{
return true;
}
else
{
return false;
}
}
I hope this is what you meant.
You need to look in to user roles and the process of authorization usually, MVC provides a registration and log in in it template including the account controller. To restrict user access you have to assign roles to users.
the code behind it would look something like this.
[Authorize(Roles="admin")]
public ActionResult admin()
{
//Action gives an admin rights since the user is in the admin role
return View();
}
[Authorize(Roles="manager")]
public ActionResult manager()
{ //give a managers rights since user is im managers roles.
return View();
}

Resources