ASP.Net MVC elegant UI and ModelBinder authorization
We know that authorization stuff is a cross-cutting issue and we do our best to avoid merging business logic in our views.
But I still don't find an elegant way to filter UI components (like widgets, form elements, tables, etc.) using the user's current roles without polluting the view with business logic. this also applies to model binding.
Example
Form: Product Creation
Fields:
- Name
- Price
- A discount
Roles:
-
Role administrator
- Allowed to view and modify the "Name" field
- Allowed to see and change the Price field
- Allowed to view and change the discount
-
Role Administrator Assistant
- Allowed to see and change the name
- Allowed to see and change the price
Fields
shown in each role are different, model binding
should also ignore the role discount field
for Administrator Assistant.
How do you do it?
a source to share
Since you already have both the current user and access to the authorization provider in your controllers, this is the ideal responsibility for them. Using a naive implementation, you can pass a collection of widgets to your view after you've filtered which widgets the current user belongs to. In the case of your form field, things can look hairy if you're considering client side validation.
The binding component will be the most direct of them all, having a dedicated binder for these special cases will do this trick especially well since it will have access to the controller context and you can grab the current user from there and bind the values according to your role definitions.
a source to share
The way I could think of is to create custom versions of the input extension methods . For example, instead, TextBox
you can create TextBoxRoles
and define it like this:
public static MvcHtmlString TextBoxRoles(
this HtmlHelper htmlHelper,
string name,
string RolesEdit,
string RolesView
)
Then in the code it will look like this:
<%= Html.TextBoxRoles("Price", "Administrator","Administrator,Assistant") %>
Then your implementation TextBoxRoles
will check the roles of the current user through User.IsInRole()
to determine what should appear on the page.
Of course, you will need to do this for every input extension method you use.
a source to share