简体   繁体   中英

Asp.Net MVC Service Layer - additional service vs passed in parameter

I'm spinning up an MVC5 app inside of a legacy webforms site to help refactor/replace some very old code. Along the way I discovered that as was typical of old webforms, there's a giant class that was created to manage values in session, SessionManager. Obviously this isn't very testable, so I've hidden the properties I need behind a service:

 public class LegacySessionService : ISessionService
 {
         public IUser GetCurrentUser()
         {
             return SessionManager.CurrentIUser;
         }
 }

Now my question is, inside another service, is it cleaner to have the controller have access to the session service and pass in an IUser, or to have the working service know of and access the session service?

public class MyController : Controller
 {
    /*skipping obvious dependency injection*/

    public ActionResult DoStuff()
    {
       var viewModel = _someotherService.DoStuffWithIUser(_sessionService.GetCurrentUser())
       return View("DoStuff", viewModel)
    }
 }

OR

 public class SomeOtherService
 {
   /*skipping obvious dependency injection*/

   public ViewModelClass DoStuffWithIUser()
   {
     var currentUser = _sessionService.GetUser();
     //do more stuff, return ViewModel
   }
 }

Which is more architecturally correct and why? I can't tell.

Your second option is the better of the two, under the single responsibility principle the controller should be concerned with coordinating the model and view layers, not with how the model layer retrieves information like the current user.

Your second example could still be improved though. Your SomeOtherService has an assumption in it that the current user should be retrieved from SessionService. What if you change to reading the user from HttpContext or elsewhere in the future? I'd suggest creating an ICurrentUser interface and adding that into the constructor for SomeOtherService. You can then create a concrete implementation of it called something like CurrentUserFromSession which reads from SessionService and inject that for now. If you ever change how the current user is retrieved you can then just create a new implementation of ICurrentUser, change the DI container and not have to reopen SomeOtherService.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM