MVC3 render html based on roles

Hi All,

I am new to MVC3 and just learning how it works.

I currently am building a project which has several different membership roles. I understand that I can limit different controller actions to different roles, but what if I want all my roles to share a view and just render slightly different information based on your role. An example would be some sort of data entry page…If I’m an admin I can edit and see all the information, if I’m just a regular user I can only see and edit a subset of the information.

Should I build a different page for the admin and the user or am I on the right approach with using the same page and just limiting what get’s displayed by the role. How do I do this?

Thanks,
AFrieze

Hi AFrieze,

Like always there are more roads that lead to Rome. (I wasn’t even sure this would be a saying outside the Netherlands but according to Google it does… ;-)) Depending on how you set up your website you should pick your preffered solution.

When you created a website that contains an Area for the backend you should create seperate Controllers and Actions for Administrators and visitors. This way you don´t need to write logic into your View for seperating Roles in a page and logic to check user input in the backend.

When you want to set up a page like you described above you should seperate Roles in the View and in the Controller. In the View you could use code like below for seperating for example Administrators from normal users. You can see that I use Partials for the different forms that need to be submit to the server.

<% if (User.IsInRole("Role")) { %>
     <%: Html.Partial("AdminForm") %>
<% } else { %>
     <%: Html.Partial("PublicForm") %>
<% } %>

After that you need to check user input in the backend to be sure that visitors only can insert some content to the database. In your method you could say something like:

myMessage = filledInMessage.Message;
if (User.IsInRole("Role"))
{
     myMessage.IsApproved = filledInMessage.IsApproved;
}
myContext.InsertOnSubmit(myMessage);

Please pay attention that in case of Unit Tests you need to mock the User to properly test the method!

Regards, Tom

Hi Tom,

Thank you for your answer. Your first post too! Welcome to sitepoint!

I understand the partial view idea and that may well be the way I approach the issue. Going this route provides the benefit of specifying access level on the actual controller for the partial views if I understand correctly. The downside to this would be that I am still duplicating code and essentially building the form multiple times.

I could modify your example a little and do something like this sprinkled throughout the page:


[LEFT]<% [COLOR=#0600FF]if[/COLOR] [COLOR=#000000]([/COLOR]User.[COLOR=#0000FF]IsInRole[/COLOR][COLOR=#000000]([/COLOR][COLOR=#808080]"Admin"[/COLOR][COLOR=#000000])[/COLOR][COLOR=#000000])[/COLOR] [COLOR=#000000]{[/COLOR] %> 
     @Html.LabelFor(model => model.Name)
     @Html.EditorFor(model => model.Name)
     @Html.ValidationMessageFor(model => model.Name, null, new { @class = "validation-message" }) 
<% [COLOR=#000000]}[/COLOR] [COLOR=#0600FF]else[/COLOR] [COLOR=#000000]{[/COLOR] %>       @Html.LabelFor(model => model.Name)
     @Html.EditorFor(model => model.Name)  

<% [COLOR=#000000]}[/COLOR] %>
[/LEFT]


This approach seems quite inelegant

I think you should go for separate Pages. I have not worked on MVC yet but i am working on MVP. It is quite similar to MVC in approach. You can even create separate user control for admin and visitors and populate appropriate user control.

Doesn’t it also depends on what Roles you have in a website. I can imagine that you use special Views for Administrators, I would definetly in most cases, But maybe you have logged-in users and not-logged-in users, creating whole different pages for almost the same functionality sounds to me like wet.

Of course you’re entirely free in how you set up the partial views, so you can avoid code duplication by specifying the pieces of code in the partial view as much as you can to the particular user.

Again I think it’s also a matter of what the purpose of the view is. In the code you wrote above you could take out the else-statement while the name is always visible, that saves code duplication…

We actually use different views for stuff like this in most cases – much easier to test against, much cleaner and more explicit.

As for restricting access entirely, I’d advise using the [Authorize] attributes rather than alot of logic in each controller method.