Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>You're on the right track, but you can encapsulate all of the permission check into a single method like <code>GetProductForUser</code>, which takes a product, user, and the required permission. By throwing an exception that's caught in the controller's OnException handler, the handling is all in one place:</p> <pre><code>enum Permission { Forbidden = 0, Access = 1, Admin = 2 } public class ProductForbiddenException : Exception { } public class ProductsController { public Product GetProductForUser(int id, User u, Permission perm) { Product p = ProductRepository.GetProductById(id); if (ProductPermissionService.UserPermission(u, p) &lt; perm) { throw new ProductForbiddenException(); } return p; } public ActionResult Edit(int id) { User u = UserRepository.GetUserSomehowFromTheRequest(); Product p = GetProductForUser(id, u, Permission.Admin); return View(p); } public ActionResult View(int id) { User u = UserRepository.GetUserSomehowFromTheRequest(); Product p = GetProductForUser(id, u, Permission.Access); return View(p); } public override void OnException(ExceptionContext filterContext) { if (typeof(filterContext.Exception) == typeof(ProductForbiddenException)) { // handle me! } base.OnException(filterContext); } } </code></pre> <p>You just have to provide ProductPermissionService.UserPermission, to return a user's permission on a given product.By using a Permission enum (I think I've got the right syntax...) and comparing permissions with <code>&lt;</code>, Admin permissions imply Access permissions, which is pretty much always right.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    1. COThe only big problem I see here is that rolling up the permission into the request somewhat prevents you using the same code to generate the view. Imagine the Index (List) method of your controller there. The client has come to you with the requirement that the List view has "Edit" links next to products the current user is allowed to edit. How would you reconcile that so the same code which determines that a user can GET or POST the Edit action also determines whether or not to render the "Edit" link on the List or Details views?
      singulars
    2. COThe permissions associated with each action method (i.e the permissions that control access to the page and access to the model, which may be the same) could be stored in an attribute on the action. Then the code at <http://msdn.microsoft.com/en-us/library/71s1zwct.aspx#cpconretrievingsingleinstanceofattribute> could be used to retrieve that permission from the attribute for the call to GetProductForUser.
      singulars
    3. COContinuing... In the view, a method like Controller.UserCanAccessAction(User u, string action) could return true or false if the user can access the view, based on the permission in the attribute. So the view code could be like: <% if (ProductController.UserCanAccessAction(CurrentUser, "Edit")) { Response.Write(Html.ActionLink("Edit", ....)); } %> This technique doesn't duplicate the permission in the action and the view. You could use two attributes (e.g. ModelPermissionAttribute and ActionPermissionAttribute) if the permissions differ.
      singulars
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload