Role specific controls in Views - asp.net

I'm trying to hide controls based on a user's role. I used to be able to do something like
#if (User.IsInRole("Admin"))
{Html.ActionLink("RolesAdmin", "Index", "RolesAdmin")}
in the view but this doesn't seem to work anymore. After much digging I found that Identity 2.0 doesn't use this at all.
Is there still something I can use directly from the View? Or am I doing this completely wrong?

This should still work fine, as the identity samples are currently doing something similar to only display top level links for "Admins"
#if (Request.IsAuthenticated && User.IsInRole("Admin")) {
<li>#Html.ActionLink("RolesAdmin", "Index", "RolesAdmin")</li>
<li>#Html.ActionLink("UsersAdmin", "Index", "UsersAdmin")</li>
}

This type of logic is better placed inside a controller, leave the views for rendering.
You can use Html.Action with a combination of ChildActions in your controller and render partial views depending on the users role.
I posted a question similar to this a while ago and think it would be helpful to you.
Role Based Navigation
-EDIT-
For clarification, this works using the new ASP.NET Identity
This would go in the layout
#Html.Action("BuildNavigation", "Component")
And this would be your controller.
public class ComponentController : Controller
{
[ChildActionOnly]
public ActionResult BuildNavigation()
{
if (this.User.IsInRole("customer"))
{
return PartialView("_NavigationCustomer");
}
else
{
return PartialView("_NavigationBasic");
}
}
}
This should get you going in the right direction.

Related

#model for _layout.cshtml on MVC4?

I was wondering if there's a way to specify a model for the _layout.cshtml file, i've seen lots of posts with the basic same question with people replying with "alternative" solutions, not saying it's not possible nor showing how exactly we could achieve this
having some experience with webforms I've been trying to migrate to MVC and often find myself with such questions, I've found this website: http://blog.bitdiff.com/2012/05/sharing-common-view-model-data-in.html
which partially solved my problem but even them don't bind their _layout.cshtml with a #model, as far as I know, I have to specify a model on each view if I want to access the SharedContext, please correct if I'm wrong
what I wanted to do is declare a "#model Namespace.MyModel" on _layout.cshtml so it could retrieve its information by itself, instead of having to implement a model for each view inherinting from the LayoutModel
*I hope I'm being clear, basically, I wanted to know how can I declare #model tag on a _layout.cshtml so it can access its own model
with the solution I linked before (even though it's not linked to my question) I have to do:
#(((BaseController)ViewContext.Controller).Context.Property) to get the shared information, and if I could simply declare (and use) a #model instead, I could accomplish the same thing by doing something like: #Model.Property*
as you can see, im struggling trying to migrate whatever I already know from webforms to MVC and it's being quite difficult for me since I have to adopt certain practices which are completely different from what I'm used to
thanks in advance
You should delegate the parts of your layout that "need a model" to a separate controller using partial views and RenderAction:
#Html.RenderAction("SomeAction", "LayoutController")
Have LayoutController.SomeAction return a PartialViewResult, which you can then strongly type to a model.
Even though you already accepted an answer, based on your saying you are just pulling an image URL you should do it using JQuery, not a model.
This code is untested, apologies for that. Feel free to point out if I typed a bug. The HTML element containing the background image has the id="url" attribute so the selectors work.
Controller
[HttpGet]
public string GetSessionUrl()
{
//logic to detmine url
return url;
}
JQuery
$(document).ready(function () {
var $url = $('#url');
var options = {
url: "/Home/GetSessionUrl",
type: "get",
async:false
};
$.ajax(options).done(function (data) {
$url.attr('src', data);
});
});
You can add BaseModel to _Layout.
#model BaseModel
Then all models inherit from that BaseModel class.
public class MyModel : BaseModel
{
}
As others stated, it is not a good practice. If your model forgets to inherit from BaseModel, it'll throws exception at run time. However, it is up to you.
In BaseController you can declare any model as property.
public class BaseController : Controller
{
public BaseController ()
{
MyTag = new TagModel (); // or get db, take any value from there
}
public TagModel MyTag { get; set; }
}
In action:
ViewBag.MyTag = MyTag ;
And in _Layout.cshtml, you can use
#{
var myTag = (TagModel)ViewBag.MyTag;
}

How to Show or hide controls based on roles - ASP.NET MVC 4 Razor

I m working on ASP.NET MVC 4 application.I have a dashboard and my users groups will be based on Windows Domain
So I am using WIndows Authentication for authenticating users.
I created sample applications which uses custom authentication by overrides functions AuthorizeAttribute, ActionFilterAttribute . Is this a good approach ?
Which attribute is best used for authentication ?
I have a dashboard. So I need to show or hide the controls based on roles.
Suppose if there is 3 grids(table), If Admin is logs in, he can able see 3 grids(tables).
But if Support user is log in he can see 2 grids (table) only.
My plan is to create partial views for each grid and so there will be an Action and Controller for each partial view.
There will be a database and in that I will specify the actions which each group can perform. So that I can filter the requests.
2 How can I hide or show the partial views based on roles ?.
I tried some SO links, but all they are talking about 2,3 roles and it was hard coded.
In my case roles may vary and we uses db to set up access for roles.
Thanks in advance.
You can use Following code for role based checking
#if(Request.IsAuthenticated)
{
if(User.IsInRole("Admin"))
{
<Ul Class="SubMenuItem">
<li> this menu item is for Admin role</li>
</Ul>
}
if(User.IsInRole("User"))
{
<Ul Class="SubMenuItem">
<li> this menu item is for User role</li>
</Ul>
}
}
#* For unknown user *#
else
{
<Ul Class="SubMenuItem">
<li> this menu item is for Unknown user</li>
</Ul>
}
Typically you would want to keep your views as clean as possible with little to no logic.
I would suggest moving your role checking logic into a controller action and rendering a partial view based on the users role.
You can use ChildActions and the Html.Action extension method to get this wired up.
From MSDN:
A child action method renders inline HTML markup for part of a view
instead of rendering a whole view. Any method that is marked with
ChildActionOnlyAttribute can be called only with the Action or
RenderAction HTML extension methods.
In your project, create a new Controller called Dashboard and added a single Action called BuildTable.
public class DashboardController : Controller
{
[ChildActionOnly]
public ActionResult BuildTable()
{
if (Roles.IsUserInRole("Administrator"))
{
return PartialView("_AdminTable");
}
return PartialView("_SupportTable");
}
}
Include the following line in the view where you want the dashboard table to appear.
#Html.Action("BuildTable", "Dashboard")
I have done something similar. The way I did it (may not be the best)
is to send a boolean back to the view
in the controller use:
bool showSection1 = true;
bool showSection2 = false;
ViewData["showSection1"] = showSection1;
ViewData["showSection2"] = showSection2;
/// may be better to use a viewmodel here rather than ViewData
then in the view:
#if((bool)ViewData["showSection1"])
{
#{Html.RenderPartial("section1");}
}
#if((bool)ViewData["showSection2"))
{
#{Html.RenderPartial("Section2");}
}
you will need to do the logic to set the boolean the way you want them but this should be a start.
you could also create a static method that returns the role and then get that value directly from the view. this may be bad form though.
#if(AppHelper.GetRole().equals("role1")){
//show the partial
}
then create a class called AppHelper and a method called GetRole that returns the role of the user.

Access Parent Page ViewState from the user control?

is there any way to access parent page ViewState from the user control.
Yes you can ... To do so you just need to follow a basic trick ..
First inherit the caller page by a base page (using a base page over the project always a good practice it help later very much) like below ...
public abstract class BasePage : Page
{
public StateBag ViewState
{
get
{
return base.ViewState;
}
}
}
Later you can call this property from usercontrol ........
var CallerPage = this.Page as BasePage;
if (CallerPage!=null)
{
var CallerPageViewState = CallerPage.ViewState;
//Do your rest job
}
The ViewState property of the Page class is protected. Therefore, there's no way to access it from a user control, unless you're willing to break encapsulation by using reflection.
In a word no. Depending on what you want to do though there may be another way to do what you're trying to achieve
More information on what you're wanting to achieve will help people to answer your question more fully

Specify different _Layout.cshtml depending on controller

I created an asp mvc3 project, I want to have a different _Layout.cshtml depending on which controller is selected. This is because with controller 1 it has 2 buttons with the controller2 there will be 3 and with the controller3 there will be 4. Each controller is for a specific type of user, so it depends on the login.
How can i link a controller and its views to another Layout.cshtml, right now there is one layout and it's under the Shared folder.
Thanks!
The View should determine the layout, not the controller.
The Controller should just determine what View is returned.
Then in the top of your view you can specify the layout.
You could add a If statement around it to change it based on your data
#{
if(ViewBag.someValue)
Layout = "~/Views/Shared/_Layout.cshtml";
else
Layout = "~/Views/Shared/_otherLayout.cshtml";
}
At this point since the other one is a bit dated and with mvc 5 , I know you will have some issues with not having brackets. If you wish to use the View to be doing logic then here is a more complete answer.
Controller
public ActionResult Index()
{
ViewBag.Admin = 1;
return View();
}
View
#{
if (ViewBag.Admin == 1)
{
Layout = "~/Views/Shared/_AdminLayout.cshtml";
}
else
{
Layout = "~/Views/Shared/_Layout.cshtml";
}
}

How do I make a custom ASP.NET control based/subclassed on an existing one?

I want to make a custom ASP.NET control that is a subclasse of System.Web.UI.WebControls.Calendar. I need it to add a few data members and set up a few event handlers in it's constructor.
Is this possible? If so How?
So far I have tried using add new item to add a default web user control and tried editing in Calendar in a few different places. None have worked so far.
Edit: it seems I'm totally missing how this stuff is supposed to work.
Does anyone known of a demo project that I can look at? Something that already exists. (Unless you are really board, don't go out and make one for me.)
Unless I'm misunderstanding the question, you can just create a new class file and inherit from Calendar. Add in the properties you need, and the event handlers you want to set up.
public class MyCalendar : System.Web.UI.WebControls.Calendar
{
public MyCalendar()
{
// set up handlers/properties
}
}
Then anywhere you'd like to add a Calendar to your pages, you can simply create a MyCalendar instead. If you need to do so in the designer, you can look at several good tutorials about how to make your inherited controls show their new properties in the designer, like this one.
In a new class file you need to inherit from System.Web.UI.WebControls.Calendar instead of System.Web.UI.UserControl.
namespace MyNamespace
{
[ToolboxData("<{0}:UserCalendar runat=\"server\" />")]
public class UserCalendar : System.Web.UI.WebControls.Calendar
{
private string property1;
public UserCalendar() { }
public string Property1 { get { return property1;} set { property1 = value; } }
}
}
Then on your .aspx page (or in another control .ascx):
<%# Register TagPrefix="userControl" namespace="MyNamespace" assembly="MyProjectAssembly" %>
<userControl:UserCalendar runat="server" ID="myCalendar" property1="some value" />
Stuff to read: Developing Custom ASP.NET Server Controls.

Resources