ASP.NET MVC, 'Ticket Required' Attribute

蹲街弑〆低调 提交于 2020-01-01 05:29:07

问题


I am attempting to build a system that allows users to perform certain actions, but their account must have a specific 'Ticket' per time they do it. For instance, suppose they wish to create a Product, they would need a CreateProductTicket.

I could simply do this with some 'if' statements, sure, but I want to try a bit more of a robust solution. My structure looks something like this...

interface ITicket<T> where T : ITicketable
{
}

My basic goal is to build an Attribute, perhaps like the following..

public class TicketRequiredAttribute : Attribute
{
 public TicketRequiredAttribute(ITicket<T> ticket)
 {
  if(ticket == null) 
    return;
  }
}

And to be able to decorate Controller or Repository Actions with this. So like ...

ProductsControlller

[TicketRequired(CreateProductTicket)]
public ActionResult CreateProduct(Product product)
{
 // ... **I am unsure how to tell if TicketRequired was true or not**
}

Problem 1

I'm not familiar enough with attributes to know how to tell if TicketRequired was 'met' or not. Can anyone enlighten me on this?

Problem 2

The problem I am running into is with database querying. I want to be able to check the user (IMembershipRepository has a GetUser method), but I'm not entirely certain how to do that through an attribute.

Using Castle.Windsor, I have my Dependency Injection set up to inject repositories into controllers. I suppose I could pass the IMembershipRepository through the TicketRequired constructor, but I have a feeling that will become very messy - and extremely unstable. Is there a more logical way to approach this?


回答1:


You're almost there. You can find more details at http://www.asp.net/mvc/tutorials/understanding-action-filters-cs

I would only use the attribute on the action since the website is where I do all my authorization.

Here is a possible solution. I have not tested this, but it should work. You'll need to verify the way I'm redirecting, not sure if that's the proper way.

 public class TicketRequiredActionFilter : ActionFilterAttribute
 {
        private Type _ticketType;

  public TicketRequiredAttribute(Type ticketType)
  {
        _ticketRequired = ticketType;     
  }

  public override void OnActionExecuting(ActionExecutingContext filterContext)
  {
     UserServices userServices = GetUserServicesViaDIContainer(); // you'll need to figure out how to implement this 
     string userId = filterContext.HttpContext.User.Identity.Name
     bool hasTicket = userServices.HasTicket(_ticketType, (int)userId); // again, you'll need to figure out the exact implementation
     if(!hasTicket)
     {
        filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary { { "controller", "Home" }, {"action", "NoPermission" } })
     }
     else
     { 
        base.OnActionExecuting(filterContext);
     }     
  }
}

In your controller:

[TicketRequiredActionFilter(typeof(CreateProductTicket))]
public ActionResult MyMethod()
{
    // do stuff as if the person is authorized and has the ticket
}

If the user doesn't have the ticket, a redirect is issues;, otherwise, continue as normal.




回答2:


This sounds very much like user roles.

How are you handling the user membership? If your using the built-in asp.net membership you can use roles. So each user will have a certain number of roles in your case one of the will be "CreateProductTicket" then you can decorate your action or controller with the Authorize attribute. Something like:

[Authorize(Roles="CreateProductTicket")]
public ActionResult CreateProduct(Product product)

If a user doesn't have the role or is not authorized then they can access the action.



来源:https://stackoverflow.com/questions/4511496/asp-net-mvc-ticket-required-attribute

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!