-1

What are the best-practices and/or standards for creating a user control in ASP.Net MVC web applications with the ability to limit the functionality of it, based on the user role or user itself?

In other words, assume that I have four different web pages with 90% exact similar content (some search fields, a grid containing the result of the search, some javascript, ...) and each one may have one or two other search fields. (Please note that these extra search fields on each page, are effective in the result of the search. also please consider that we use the same stored procedures behind the scene, and in pages with less search fields, we pass null or default values -based on the situation- to them).

we are looking for a way to refactor our code and if it's possible use a USER CONTROL in each of four pages instead.

edit : maybe I should correct the question to something like this : how to avoid putting <% if(...)%> tags inside the view and use a method like the one described here, where CRice said: "it is better to let the viewdata or model represent what the view is to display, and the view can simply check the view data. A controller base class or a filter on an action can make repetitive use of this very simple and allow the code to exist in one place." in order to solve my problem?

people keep emphasizing on the check user-in-role part. In fact I had already knew this when I asked the question. What I don't know is how to do it the right way, using viewdata or model or whatever suits these kind of cases. (specially using the model as described in the reference question)

Thanks a lot for guiding me through this and your patience.

Community
  • 1
  • 1
Arashv
  • 305
  • 4
  • 15
  • There are any number of ways to accomplish role-based access control in an app. Decorating controller actions with permission attributes is a relatively common one, though I don't know whether it's a best practice or not. – 48klocs Jul 07 '12 at 16:33
  • @48klocs Thanks for the response, I get it, but I was curious about the view not the controller. I meant how to render the control role-specific? – Arashv Jul 07 '12 at 18:31

2 Answers2

1

we are looking for a way to refactor our code and if it's possible use a USER CONTROL in each of four pages instead.

This is the right way indeed. Except that in ASP.NET MVC there are no user/server side controls. You could write a custom reusable HTML helper that will encapsulate this function functionality and inside your view call this custom helper. For example:

@Html.RoleBasedTextBoxFor(x => x.SomeField, "Admin")

The custom helper will simply check if the currently authenticated user is in the Admin role and render a textbox, if not return an empty string.

Here's how such a sample helper could look like:

public static class HtmlExtensions
{
    public static IHtmlString RoleBasedTextBoxFor<TModel, TProperty>(
        this HtmlHelper<TModel> html,
        Expression<Func<TModel, TProperty>> expression,
        string roleName
    )
    {
        var user = html.ViewContext.HttpContext.User;
        if (!user.Identity.IsAuthenticated || !user.IsInRole(roleName))
        {
            // the user is not authenticated or is not in the required role
            return MvcHtmlString.Empty;
        }

        return html.TextBoxFor(expression);
    }
}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Thanks man. Can you please read my comments about 48klocs' answer? What do you think? – Arashv Jul 09 '12 at 12:15
  • Yes, I read it. Your comment makes perfect sense. You were asking about making conditional logic in the view based on roles without writing if statements in the view and that's what I tried to illustrate in my answer. – Darin Dimitrov Jul 09 '12 at 12:28
  • Yes. Darin, your answer is quite right. In fact it's a way of hiding IF clauses inside a helper method and so far is the best. But I got curious about the answer of CRice. After reading it, it seemed to me that there's a whole **different standard way** of doing what I need that I'm not ware of! So I got really curious to find out. So if you know anything about what he says please tell me. – Arashv Jul 09 '12 at 12:51
  • Yes, another possibility is to use model metadata on your view model property indicating the roles that a user must be in if the property is to be displayed. And then override the default editor templates to check whether the user is in this role before rendering the field or not. – Darin Dimitrov Jul 09 '12 at 12:54
  • Thanks. Do you have any samples, code snippets or any useful reference? – Arashv Jul 09 '12 at 13:05
  • Yes, you may take a look at the following article which illustrates how a custom metadata provider could be implemented along with custom metadata on the view model and custom editor templates for the standard types in order to be able to set for example things like class name, maxsize, ... for textboxes: `http://aspadvice.com/blogs/kiran/archive/2009/11/29/Adding-html-attributes-support-for-Templates-_2D00_-ASP.Net-MVC-2.0-Beta_2D00_1.aspx`. This could easily be adapted to the needs of roles management. – Darin Dimitrov Jul 09 '12 at 13:13
0

If you're looking to check the role inside of the view, that question has already been answered.

While you can use Page.User.IsInRole("RoleName") on the view, it's better to have the controller, well, control user flow.

Community
  • 1
  • 1
48klocs
  • 6,073
  • 3
  • 27
  • 34
  • Thanks, but I don't know why do people keep emphasizing on the **check user-in-role part**; in fact I had already knew this when I asked the question! My real question is about how to avoid putting `<% if(...)%>` tags inside and use some methods like the one described in the question you mentioned, where CRice said: "it is better to let the viewdata or model represent what the view is to display, and the view can simply check the view data. A controller base class or a filter on an action can make repetitive use of this very simple and allow the code to exist in one place." – Arashv Jul 09 '12 at 07:49
  • in fact can you please tell me how to solve my problem with a method like the one @CRice has described – Arashv Jul 09 '12 at 07:52