【问题标题】:How to keep controllers small in ASP.NET MVC?如何在 ASP.NET MVC 中保持控制器很小?
【发布时间】:2012-07-31 20:23:40
【问题描述】:

我有一个精心设计的架构,其中控制器转到访问与数据库通信的存储库的服务。

因此,控制器中的逻辑保持在最低限度,但我仍然有非常微妙的代码片段可以执行一些任务,例如

  • 验证模型
  • 排列动作方法参数
  • 使用这些参数调用一些服务,如果模型现在无效
  • ,可能会验证结果并返回视图
  • 最终根据服务结果生成模型,并将其返回。

根据服务返回的“状态”,一些较长的案例会做不同的事情。

这里有几个例子:

[HttpPost]
[AjaxOnly]
[Authorize]
public JsonResult Preview(string input)
{
    LinkResult parsed = linkService.ParseUserInput(input);
    if (parsed.Result == LinkParseResult.Used)
    {
        long? postId = parsed.Link.PostId;
        if (postId.HasValue)
        {
            Post post = postService.GetById(postId.Value, false);
            return Json(new
            {
                faulted = "used",
                link = DetailsRoute(post),
                id = postId
            });
        }
        else
        {
            return Json(new { faulted = "invalid" });
        }
    }
    else if (parsed.Result == LinkParseResult.Invalid)
    {
        return Json(new { faulted = "invalid" });
    }
    else
    {
        Link link = parsed.Link;
        if (link.Description != null && link.Description.Length > 200)
        {
            link.Description = link.Description.Substring(0, 200);
        }
        return AjaxView(link);
    }
}

和(Post 来自域,PostModel 是视图模型)

private PostModel PostModelConverter(Post post)
{
    Link link = post.Link;
    if (link == null)
    {
        throw new ArgumentException("post.Link can't be null");
    }
    if (link.Type == LinkType.Html)
    {
        return new PostedLinkModel
        {
            Description = link.Description,
            PictureUrl = link.Picture,
            PostId = post.Id,
            PostSlug = postService.GetTitleSlug(post),
            Timestamp = post.Created,
            Title = link.Title,
            UserMessage = post.UserMessage,
            UserDisplayName = post.User.DisplayName
        };
    }
    else if (link.Type == LinkType.Image)
    {
        return new PostedImageModel
        {
            PictureUrl = link.Picture,
            PostId = post.Id,
            PostSlug = postService.GetTitleSlug(post),
            Timestamp = post.Created,
            UserMessage = post.UserMessage,
            UserDisplayName = post.User.DisplayName
        };
    }
    return null;
}

这提出了一个问题,即视图模型是否真的应该作为规则出现在 Web 项目中,或者它们实际上可能是域或其他项目的一部分。

我不确定我可以对预览操作做很多事情,除了可能使用接收链接并截断描述的 PreviewModel,但这会节省两行。

模型转换器可能应该在其他地方,但我不知道应该在哪里。

我想到的另一点是我是否应该使用 partial 关键字拆分此控制器(将其用于自动生成的类以外的其他东西是一种不好的做法吗?),或者添加使用不同控制器的路由,具体取决于请求什么操作或使用什么 http 方法,通常的处理方法是什么?

【问题讨论】:

  • 只是个人喜好,但你可以使用 switch 语句代替 if .. else if ... 等

标签: c# asp.net-mvc-3 controller refactoring


【解决方案1】:

这个问题已经问了好几次了:
Business logic in the controller
Where should I put my controller business logic in MVC3
Keep Controllers Thin

以及其他地方写的:
ASP MVC Best Practices - Skinny Controllers
Keep Controllers Thin

社区似乎对这种逻辑属于控制器之外达成了很好的共识。一般在模型(或 ViewModel)中,但在业务层某处

最后一点,不建议将partials 用于非自动生成的代码。如果拆分事物有意义,请这样做。想想你拆分它的原因是什么。这将是一个个案。

【讨论】:

    【解决方案2】:
    private PostModel PostModelConverter(Post post)
    {
        Link link = post.Link;
        if (link == null)
        {
            throw new ArgumentException("post.Link can't be null");
        }
        if (link.Type == LinkType.Html)
        {
            var model = AutoMapper.Map<PostedLinkModel>(post);
            model.PostSlug = postService.GetTitleSlug(post);
            return model;
        }
        else if (link.Type == LinkType.Image)
        {
            var model = AutoMapper.Map<PostedImageModel>(post);
            model.PostSlug = postService.GetTitleSlug(post);
            return model;
        }
        return null;
    }
    

    http://www.viddler.com/v/b568679c

    【讨论】:

      【解决方案3】:

      控制器不会包含任何域逻辑

      控制器应该只负责:

      验证输入

      调用模型准备视图

      返回视图或重定向到另一个动作

      如果你在做任何其他事情,你是在错误的地方做的,而是你在 Controller 中做的 Model 责任。

      如果您遵循此规则,您的操作方法将不会超过 20 - 25 行代码。 Ian Cooper 有一篇很棒的帖子 Skinny Controller Fat Model,请阅读。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多