title: Recommended way to access the current context from a class library in ASP.NET Core 2.0?
body: <p>We have separated our business logic out into a singular class library that all other projects reference.  Our front end was Web Forms before which had a singleton that made accessing the current web context very easy (<code>HttpContext.Current</code>).  In ASP.NET Core 2.0 this is gone and seemingly replaced by Dependency Injection.  </p>
  
  <p>DI seems like a step in the right direction to me and I can definitely see the benefit.  However with my class library I don't see a way to use DI.  So to access all the information needed to fulfill my business requirements I must pass all this information in as parameters.</p>
  
  <p>For example, I record the current user each time I create a new database entry.  With my web forms app (which I'm in the process of replacing) my business logic library could could obtain the user like so:</p>
  
  <pre><code>public abstract class TableBase
  {
      public User Creator { get; private set; }
  
      internal TableBase() {}//EF select constructor
  
      internal TableBase(bool newRow)
      {
          Creator = User.Current;
      }
  }
  
  public class Client : TableBase
  {
      public string Name { get; set; }
  
      protected Client() {}//EF select Constructor
  
      public Client(string name) : base(true)
      {
          Name = name;
      }
  }
  
  public class User
  {
      public static User Current =&gt; GetUserFromContext(HttpContext.Current);
  }
  </code></pre>
  
  <p>This works terrifically since the code to handle Creator is entirely handled by the base class and invisible to derived classes.  The derived classes just work.  However in ASP.NET Core 2.0 the <code>HttpContext.Current</code> singleton is gone.  Apparently replaced by DI.  So I can no longer check the currently logged in user the way I was before.  I've looked around but can't seem to find a way to access the current web context.  So I'm currently thinking that replicating my functionality would work like this: </p>
  
  <pre><code>public abstract class TableBase
  {
      public User Creator { get; private set; }
  
      internal TableBase() {}//EF select constructor
  
      internal TableBase(User creator)
      {
          Creator = creator;
      }
  }
  
  public class Client : TableBase
  {
      public string Name { get; set; }
  
      protected Client() {}//EF select constructor
  
      public Client(string name, User creator) : base(creator)
      {
          Name = name;
      }
  }
  
  public class MyPage : PageModel
  {
      private readonly User _currentUser;
      private readonly DbContext _context;
  
      public MyPage(User currentUser, DbContext context)
      {
          _currentUser = currentUser;
          _context = context;
      }
  
      public async Task&lt;IActionResult&gt; OnPostAsync(string name)
      {
          var newClient = new Client(name, _currentUser);
          _context.Clients.Add(newClient);
          await _context.SaveChangesAsync();
          return RedirectToPage("/Index");
      }
  }
  </code></pre>
  
  <p>This works but has a few undesirable traits.  </p>
  
  <ul>
  <li>I now have to pass in another parameter (<code>User creator</code>) for the new constructor in all 70 of table entities.  This is a lot of added code and we haven't even talked about the fact I have to acquire and pass the parameter at each call site.</li>
  <li>I need to use DI to inject the current user into any page model or controller that plans on possibly creating a new object.</li>
  <li>According to the guides I read model binding will initialize a new instance of my table entities on post from the parameters of the post.  Wouldn't this use the parameterless constructor and thus leave a null reference in Creator?  How can my business logic be applied here?  Do I need to build my entity myself from the POST body to utilize logic in the constructor?</li>
  </ul>
  
  <p>Maybe this is a necessary evil.  It does also remove the reliance on System.Web that my business logic library previously contained, making it more portable.  But it also seems like a lot of work to add when I expected DI to reduce the amount of code I wrote.  Are my expectations incorrect?  Have I overlooked something?</p>