将TempData和/或ViewData传递给服务是否是一种好习惯? [英] Is it good practice to pass TempData and/or ViewData to services?

查看:82
本文介绍了将TempData和/或ViewData传递给服务是否是一种好习惯?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试减小MVC控制器的大小时,我将大量逻辑重构到服务中(尽管如果将其分解为模型,则同样会发生此问题).我经常发现我直接用想要显示给用户的信息来设置ViewData和/或TempData,例如:

In trying to reduce the size of my MVC controllers, I am refactoring a lot of logic out into services (though this same issue would apply if it was being factored into models). I'm often finding that I was directly setting ViewData and/or TempData with information I wanted to be displayed to the user, like:

var repoUser = new UserRepository();
var foundUser = repoUser.GetUser(userId);
if (foundUser == null) {
    ViewData["ErrorMessage"] = "Could not find user with ID {0}.".FormatWith(userId);
    return View("UsersRegister");
}

当然,一旦进入服务类,您将失去对ViewDataTempData和诸如View()RedirectToAction()之类的方法的直接访问,所以我试图找出最好的方法.练习处理它.有两种解决方案:

Of course, as soon as you move into a service class, you lose direct access to ViewData, TempData, and methods like View() or RedirectToAction(), so I'm trying to figure out the best practice for dealing with it. Two solutions come to mind:

  1. 创建一个类,其中包含有关控制器应该做什么的各种信息,这些信息将从服务中传递回去,例如:

  1. Create a class containing various pieces of information about what the controller should do, to be passed back from the services, like:

public class ResponseInfo {
    public string Name { get; set; }
    public bool DoRedirect { get; set; }
    public object RedirectRouteValues { get; set; }
    public string InfoMessage { get; set; }
    public string ErrorMessage { get; set; }
}

  • 尝试并允许服务方法直接访问诸如ViewDataTempData之类的内容,例如:

  • Try and allow the service methods to have direct access to things like ViewData and TempData, eg.:

    public ActionResult ToggleUserAttended(int eventId, int userId, HttpRequestBase request, TempDataDictionary tempData, ViewDataDictionary viewData, Func<string, object, ActionResult> redirectAction) {
        //...
        var repoUser = new UserRepository();
        var foundUser = repoUser.GetUser(userId);
        if (foundUser == null) {
            tempData["ErrorMessage"] = "Could not find user with ID {0}.".FormatWith(userId);
            return redirectAction("UsersRegister", new { id = eventId, returnUrl = request.QueryString["returnUrl"] });
        }
        //...
    }
    

    ...,然后在控制器中:

    ... and then in the controller:

    return _svcEvent.ToggleUserAttended(123, 234, Request, TempData, ViewData, (name, routeVals) => RedirectToAction(name, routeVals));
    

  • 对于数字1,控制器在查看ResponseInfo对象并确定是否重定向,显示视图,将错误或信息消息插入TempDataViewData等时,将有更多的逻辑要做. 2号几乎可以使用一个单线控制器,但是您要使该服务非常了解特定于控制器的内容.但是,无论如何,服务始终将与控制器紧密联系在一起,所以这有问题吗?是1还是2是最佳做法,还是我未列出的其他内容?

    For number 1, the controller would have more logic to do in looking at the ResponseInfo object and determining whether to redirect, display a view, plugging the error or info message into TempData or ViewData, etc. Number 2 would pretty much allow a one-liner controller, but you're making the service very aware of controller-specific stuff. However, the service is always going to be closely tied in with the controller anyway so is this a problem? Would 1 or 2 be best practice, or something else I haven't listed?

    推荐答案

    也许我误解了一些东西,但是奇怪的是,您想提供与服务的表示方式有关的信息. IMO,这样做是一个非常糟糕的主意,因为服务是业务逻辑,不应依赖于表示层.

    Maybe I misunderstood something, but I find it strange that you want to provide information related to presentation concerns to the services. IMO, it is a very bad idea to do that as services are business logic and should not depend on presentation layer.

    我真的不喜欢您建议的任何一种方法,因为在我看来它们模糊了表示和服务之间的界限.

    I don't really like neither of approaches you suggested as it seems to me that they blur the line between presentation and services.

    作为示例,如果服务找不到用户,则应引发服务,然后控制器应使用适当的UI机制处理此错误:错误消息,HTTP错误或适合您应用程序的任何错误.同样,服务如何知道重定向到哪里?知道GUI吗?您打算如何在其他上下文(API,非Web GUI,等等)中使用它?

    As an example, a service should throw if it can't find the user, and the controller should then handle this error with appropriate UI mechanism: an error message, HTTP error or whatever fits your app. Similarly, how can the service know where to redirect? It is aware of GUI? How do you plan to use it in other contexts (API, non-web GUI, whatever)?

    我通常要做的是基于表单/参数创建一个命令/dto,并将其提供给服务.然后,任何服务客户端都可以使用相同的命令.如果我需要显示数据,我会向服务/仓库索取所需信息,然后将其映射到演示文稿表单(如果需要),然后将其放入ViewData/TempData/Model/Whatever.

    What I usually do is create a command/dto based on form/parameters and provide that to service. Then any service client can use the same command. If I need to show data, I ask services/repos for whatever I need, and map that to presentation form (if needed) and put that into ViewData/TempData/Model/Whatever.

    以下是一些示例(将其作为伪代码进行处理):

    Here are some examples (treat it as pseudo-code):

    [HttpPost]
    public ActionResult ChangeUserInfo(UserInfoModel model)
    {
      var cmd = new ChangeUserInfoCommand(CurrentUserId, model.FirstName, model.LastName);
      try {
          userSvc.UpdateUser(cmd); 
          return RedirectToAction(...);
      }
      catch(XxxxException e) { // e.g. something wrong (business logic)
          TempData["Error"] = "an error occurred: " + e.FriendlyError();
          return RedirectToAction(...); // error action
      }
      catch(SecurityException e) {
          throw new HttpException(404, "NotFound");
      }
    }
    
    public ActionResult ShowUsers()
    {
      var userInfo = svc.GetUsers().Select(u => { Id = u.id, FullName = u.First + " " + u.Last);
      // or var userInfo = svc.GetUsers().Select(u => Mapper.To<UserDTO>(u));
      return View(userInfo);
    
      // or without model
      // ViewData["users"] = userInfo;
      // return View();
    }
    

    请注意,这只是一个示例-我通常以不同的方式进行操作,但是我有很多其他基础结构(例如,我没有明确处理此类异常,我的服务有时只有一种方法Execute(IEnumerable<Command> cmds) ,我对匿名类(如视图模型等)有很好的支持

    Please note that this is an illustration - I usually do it quite differently, but I have a lot of other infrastructure in place (e.g. I don't explicitly handle exceptions like this, my services sometimes have only one method Execute(IEnumerable<Command> cmds), I have nice support for anonymous classes as view models, etc)

    这篇关于将TempData和/或ViewData传递给服务是否是一种好习惯?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆