ASP.NET MVC从控制器方法属性传递认证信息给ViewModel

本文关键字:认证 信息 ViewModel 属性 MVC NET 控制器 方法 ASP | 更新日期: 2023-09-27 17:49:48

我正在重新设计一个asp.net MVC后台,以获得完整的多租户支持。

由于我决定使用分片来实现租户之间的完美分离,我需要在每个viewModel中访问一些Auth信息(租户Id),只有使用这些信息,我才能为指定的租户创建正确的连接。

对于传递信息,我有3条规则:

  • 我不想使用会话变量
  • 我不想使用ViewBag
  • 我不想为每个VM添加一个新的对象来获取认证信息

最重要的是我想要一个"代码更少"的解决方案,完美的场景是在VM内访问认证信息,例如将其作为控制器调用中的属性传递。

我已经重写了controlleronauthorization所以每次调用时它都会将tenantId添加到我的基本控制器(这是我所有控制器的基础)这样我就可以在每个控制器中捕获tenantId,现在我只需要一种方法将tenantId的属性传递给每个VM,就像下面的伪代码

    [Authorize]
    [TenantId AS A PARAM]
    public ActionResult Index()
    {
        myViewModel vm = new myViewModel();
        vm.method();
        return this.View(vm);
    }

ASP.NET MVC从控制器方法属性传递认证信息给ViewModel

1)将TenantId放入HttpContext.Curent.Items

2)编写一个静态函数,从上下文中返回TenantId:
    private static int GetTenantId()
    {
        return HttpContext.Current.Items["TenantId"];
    }

3)创建BaseViewModel

public abstract class BaseViewModel
{
    public Func<int> GetTenantIdFunc{get;set;}
}
使用依赖注入容器注册你的GetTenantId函数,并通过属性注入把它注入到你所有的模型中

一种选择是使用基视图模型和继承:

public abstract BaseViewModel()
{
    public int TenantId { get; set; }
    public void SetAuthInfo(BaseController controller)
    {  
        this.TenantId = controller.TenantId;
    }
}
public MyViewModel() : BaseViewModel
// no other changes needed to MyViewModel
...
public ActionResult Index()
{
    var model = new MyViewModel();
    model.SetAuthInfo(this);
    return View(model);
}

通过属性(而不是model.SetAuthInfo)添加一个动作过滤器并覆盖OnResultExecuted并将其添加到那里,类似(未经测试):

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class SetTenantActionAttribute : ActionFilterAttribute
{
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        var baseController = filterContext.Controller as BaseController;
        if (baseController == null) return;
        var model = filterContext.Controller.ViewData.Model as BaseViewModel;
        if (model == null) return;
        model.TenantId = baseController.TenantId;
    }
}

那么你可以把它添加到你的基本控制器(甚至比添加到每个动作更少的代码)