从MVC控制器注入一个值

时间:2014-03-14 12:12:51

标签: asp.net-mvc asp.net-mvc-4 asp.net-web-api dependency-injection unity-container

我们的存储库和服务目前正通过Unity容器(使用Web API MVC引导程序)注入我们的控制器。

public class AnnouncementsController : BaseApiController
{
    protected IAnnouncementRepository AnnouncementRepository{ get; set; }

    public AnnouncementsController (IAnnouncementRepository announcementRepository)
        : base()
    {
        this.AnnouncementRepository = announcementRepository;
    }

    public HttpResponseMessage Post([FromBody]GetAnnouncementsModel model)
    {
        var announcements = AnnouncementRepository.GetByType(model.AnnouncementType);
        // ... 
    }
}

出现了新的要求:所有输入模型(例如GetAnnouncementsModel)现在需要AccessToken

为什么呢?因此,存储库的结果将根据数据权限进行过滤。客户端对他们可以使用的数据进行限制。

错误的解决方案 - 将令牌作为方法参数传递

一种解决方案是在每个存储库或服务调用中包含AccessToken参数。这不是一个好的解决方案。我们必须以数百种方法实现这一点。此参数的一个示例:

public HttpResponseMessage Post([FromBody]GetAnnouncementsModel model)
{
    var announcements = AnnouncementRepository.GetByType(model.AccessToken, model.AnnouncementType);
    // ... 
}

更好的解决方案 - 在解决期间注入令牌

更好的解决方案是在存储库构造函数中提供AccessToken,并具有一些隐式执行过滤逻辑的基本实现。

但我如何通过依赖注入来做到这一点?构造函数由Unity容器解析并调用。如何将输入模型的属性值注入此过程?

container.RegisterType<IAnnouncementRepository, AnnouncementRepository>(
    new InjectionConstructor(
        new InjectionParameter<Guid>(AccessToken)
    )
);

1 个答案:

答案 0 :(得分:2)

您可以定义自定义界面,例如IAccessTokenProvider:

interface IAccessTokenProvider
{
    Guid Token { get; }
}

现在你可以实现这样的实现:

public class HttpContextAccessTokenProvider
{
    public Guid Token
    {
      get { return (Guid)HttpContext.Current.Items["AccessToken"]; }
    }

    public static void SetToken(Guid token) 
    {
        HttpContext.Current.Items["AccessToken"] = token;
    }
}

现在,您应该能够实现过滤器以从请求中读取令牌:

public class TokenFilter : ActionFilterAttribute
{
     public override void OnActionExecuting(ActionExecutingContext filterContext)
     { 
         string tokenString = filterContext.HttpContext.Request.QueryString["token"];

         ActionExecutingContext.SetToken(Guid.Parse(tokenString));
     }
}

您还可以从其他来源读取令牌或将其存储在其他容器中(会话,cookie,等等)。您也可以直接在控制器或存储库中访问它。

您可以使用2个选项在存储库中使用令牌:

  1. 将IAccessTokenProvider注入您的存储库并直接从提供程序获取令牌。
  2. 将IAccessTokenProvider注入您的控制器并传递令牌