3

现在我正在考虑一种将“当前用户”作为我的操作中的模型绑定参数的模式。

我的动作看起来像这样:

public JsonResult ListStuff(User currentUser, string paramter1, int parameter2)
{
}

我有一个非常简单的 ModelBinder,如下所示:

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
    if ( bindingContext.ModelName == "currentUser" )
        return Globals.HttpContextItems.User;

    return null;
}

我真的很喜欢这个动作不太依赖另一个控制器属性。它使函数的“输入参数”更加清晰,更易于重用,并且将来更容易测试。

我有点害怕安全问题。我可能必须非常确定(即在 DefaultModelBinder 中)currentUser 永远不会被其他 ModelBinder 自动绑定。

如果这可能是一个好的模式,并且如果有一些我目前没有考虑的东西,那么任何人都可以发光,但这会在未来产生问题。

4

2 回答 2

2

如果您担心其他 ModelBinders 会设置该参数,为什么不创建一个 ActionFilterAttribute 以便您必须明确地装饰您的操作方法:

public class GetCurrentUserAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.ActionParameters["currentUser"] = filterContext.HttpContext.User;
    }
}

然后使用它:

[GetCurrentUser]
public ActionResult Index(User currentUser)
{
}

绝对不像默认模型绑定器那样干净,但更明确。

于 2012-12-31T16:50:18.387 回答
1

有趣的想法。而且我喜欢它通过将需求注入方法来与 IoC 保持一致(人们经常忘记您可以将依赖项注入方法,而不仅仅是构造函数)。

您的安全问题将被抽象到您将填充此上下文项的位置。我的建议是将相同的逻辑放置在同一位置,以填充上下文项。在两个地方(一个模型绑定器,然后说一个控制器方法)拥有这种逻辑会让你在两个地方追逐一个错误。我说这个模型绑定器应该负责加载那个上下文项,如果它为空的话。

最后,如果您想这样做,这将在将来抽象出更复杂的“用户验证”服务。例如,我曾经有一个项目要求,通过安全检查确保传递到域中的每条数据和 ID 都属于该用户。你描述的这个方法让你看到的是有一个从你的基本用户对象继承的自定义用户对象,称为类似的东西UserContext : User,可以有许多额外的 UI 相关功能和属性 - 包括额外的安全布尔验证。

我可能会在我的下一个项目中尝试这个。

于 2012-12-31T16:50:06.597 回答