【问题标题】:DRY-ing ASP.NET MVC actions: ApplicationController or Service?DRY-ing ASP.NET MVC 操作:ApplicationController 还是 Service?
【发布时间】:2011-08-01 20:27:52
【问题描述】:

我正在编写一个 ASP.NET MVC 3 应用程序,我发现自己经常在我的操作方法中编写这行代码:

var user = _session.Single<User>(u => u.UserName == User.Identity.Name);

(显然与AuthorizeAttribute结合使用)

还有其他事情经常重复,但这是最突出的事情,我最终有 3 个操作彼此相邻,每个操作都需要检索授权用户。

所以这需要干燥:

  1. 我应该写一个ApplicationContoller,所有其他控制器都从那里继承并公开一个User属性,还是应该将它添加到我的IAdminService并将它作为一种方法公开?

  2. 在 ASP.NET MVC 中应避免或采用 ApplicationController 吗?

【问题讨论】:

  • 你考虑过custom membership provider吗?
  • @Josiah - 绝对不是 :) 当然不是为了这个微小的功能,那将是巨大的矫枉过正。除了我有“标准”会员提供商并且运行顺利之外,我只会浪费时间。

标签: asp.net-mvc asp.net-mvc-3 dry service-layer applicationcontroller


【解决方案1】:

作为一个不太喜欢控制器超类型的人,我会考虑使用依赖注入并使用构造函数注入来“注入”用户。

o/c 这有一些缺点。这意味着您必须为控制器中的每次使用提供一个字段,并且还必须在您的 IOC 工具中创建一个绑定。这也假设您使用的是 IOC 容器。

关于其他选项:

在 IAdminService 中公开它会给您带来额外的好处,即可以在其他地方使用,而不仅仅是在 Controller 中。所以这是一个优点。请确保您的界面不会过于混乱。

一开始在基本控制器中使用它也很诱人,但我发现随着越来越多的功能被添加,控制器基本类型变得臃肿和管理不善,因为没有多重继承,人们需要其中一些和一些那...事情会变得丑陋。更不用说,如果您使用 AsyncController,您将需要管理两种基本类型。

基本上,在您的两个选项之间,我会使用界面。

无论你做什么,你仍然可以向接口添加一个方法,也可以将它抽象到基础控制器中的用户属性后面。

【讨论】:

  • "o/c 这有一些缺点。这意味着您必须为控制器中的每次使用创建一个字段,并且还必须在您的 IOC 工具中创建一个绑定。这也假设您重新使用 IOC 容器。” - 这根本不是真的。他可以简单地 new() 在基本控制器中添加他需要的任何类,根本不需要 DI。
【解决方案2】:

如果您发现自己在重复这个逻辑,那么 User 类型的自定义模型绑定器可能会有所帮助:

public class UserModelBinder : DefaultModelBinder
{
    private readonly ISession _session;
    public UserModelBinder(ISession session)
    {
        _session = session;
    }

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var username = controllerContext.HttpContext.User.Identity.Name;
        return _session.Single<User>(u => u.UserName == username);
    }
}

一旦您注册了 binder,您的控制器操作可能如下所示:

[Authorize]
public ActionResult Foo(User user)
{
    // ...
}

【讨论】:

  • 我想提一个模型活页夹...但是你不觉得它有点hackish吗?我的意思是使用动作参数来做这种用途?
  • @Linkgoron,不,我个人不觉得这种方法 hackish
  • @Linkgoron - 我也不认为这很骇人听闻;实际上相当整洁。我看到的唯一两个“问题”是 1)它强制您每次都将用户作为参数传递,因此默认路由“{controller}/{action}/{id}”不再匹配。 “{controller}/{action}/{user}/{id}”可能不是一个坏选择。 2)它只对动作方法有用,而不是在你的控制器中的任何其他地方有用,比如私有方法,不需要再次将它作为参数传递......
  • @SergiPapaseit - 您的论点无效。 Darin 的代码不会影响路线。根据您的逻辑,接受模型的 Action 方法需要将模型内置到路由中,事实并非如此。
猜你喜欢
  • 2012-05-03
  • 1970-01-01
  • 1970-01-01
  • 2011-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多