How can I get HttpContext inside an abstract class in ASPNETCore - asp.net-core

I have the following Repository:
public class TestRepository : WebCaller<Data>, ITestRepository
{
string connString = this.GetConnectionString();
.... some code here
}
In my Repository I can do Dependency Injection to the constructor without a problem.
In my abstract class WebCaller I need to get access to HttpContext somehow, I was reading that you can Inject IHttpContextAccessor to get access to the context, but because this is an Abstract class, that also lives outside the Web project, I can't have a constructor.
I was trying to do this:
public abstract class WebCaller<T> : WebRequest, IDisposable
{
//[Inject]
public ITestRepository TestRepo
{
get
{
return this.HttpContext.RequestServices.GetRequiredService<ITestRepository >();
}
}
..... more code here
}
Was trying to use Inject attribute but was reading that is no longer available, so should be other way to pass HttContext to the abstract class.

You can have a constructor on your abstract class. Just inject IHttpContextAccessor to it. Then any derived class will also take IHttpContextAccessor and pass it to its base constructor (your abstract class constructor). You can make the abstract class constructor protected.
Like:
public abstract class WebCaller<T> : WebRequest, IDisposable
{
protected WebCaller(IHttpContextAccessor contextAccessor)
{
}
}
public class TestRepository : WebCaller<Data>, ITestRepository
{
public TestRepository(IHttpContextAccessor contextAccessor) : base(contextAccessor)
{
}
string connString = this.GetConnectionString();
.... some code here
}

Related

Inject DbContextOptions vs DbContext in a repository EF Core

I have the StudentDbContext
public class StudentDbContext : DbContext
{
public StudentDbContext()
{
}
public StudentDbContext(DbContextOptions<StudentDbContext> options)
: base(options)
{
}
public virtual DbSet<Students> Students{ get; set; }
}
and then I have a repository and I try to understand what is the difference if I inject the StudentDbContext vs inject DbContextOptions
Inject the DbContextOptions
class StudentRepository : IStudentRepository
{
private readonly DbContextOptions<StudentDbContext> _context;
public StudentRepository(DbContextOptions<StudentDbContext> context)
{
_context = context;
}
}
Inject StudentDbContext
class StudentRepository : IStudentRepository
{
private readonly StudentDbContext _context;
public StudentRepository(StudentDbContext context)
{
_context = context;
}
}
Are there any advantages or disadvantages in each case?
DbContextOptions class is used to create the options to be used by a DbContext. It configures the database (and other options) to be used for the database context. DbContext class contains DbSet properties for each entity in the model.
If you try to use DbContextOptions in a repository you will have no access to any model since it doesn't have them.
DbContextOptions and DbContextOptions<TContext> have different use cases.
You need to inject DbContextOptions (generic or not) in subtypes of DbContext.
The DbContextOptions instance will contain the options that you have configured in the Startup class:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContextFactory<ConcreateDbContext>(
options => options.UseSqlServer(#"Server=(localdb)\mssqllocaldb;Database=Test")
);
}
If your DbContext implementation is not supposed to be inherited from, you will inject in your ConcreateDbContext the generic version of options type DbContextOptions<ConcreateDbContext>, and this ensures that the correct options for the specific DbContext subtype are resolved from dependency injection. You can also, mark your ConcreateDbContext as sealed, as the class is not designed to be inherited from.
public sealed class ConcreateDbContext: DbContext
{
public ConcreateDbContext(DbContextOptions<ConcreateDbContext> contextOptions)
: base(contextOptions)
{
}
}
In case that you want to have a DbContext that is intended to be inherited from, you are supposed to expose a protected constructor which will take as a parameter the non-generic version of DbContextOptions.
public class BaseDbContext: DbContext
{
protected BaseDbContext(DbContextOptions contextOptions)
: base(contextOptions)
{
}
}
In case you want to have a DbContext that is intended to be both instantiated and inherited from, you will have two constructors, one taking the generic, and one the non-generic version of DbContextOptions.
And when you want to interact with the data in your database, you will inject the concrete DbContext implementation (in your case StudentDbContext).

How to simplify asp.net core dependency injection

Since asp.net core DI provides only constructor injection and method injection.
If there's a lot of services to inject.
Instead of writing a lot inside constructor and change constructors frequently.
Can I just use some kind of provider so that I can get the services everywhere inside controller?
Instead of :
public class HomeController : BaseController
{
public HomeController(
IEmailService emailService,
ISMSService smsService,
ILogService logService,
IProductRepository _productRepository)
:base(emailService,smsService,logService)
{
}
public IActionResult()
{
_emailService.SendSomething();
}
...
}
public class BaseController : Controller
{
protected readonly IEmailService _emailService;
protected readonly ISMSService _smsService;
protected readonly ILogService _logService;
public BaseController(
IEmailService emailService,
ISMSService smsService,
ILogService logService)
{
_emailService = emailService;
_smsService = smsService;
_logService = logService;
}
}
With some kind of provider like:
public class HomeController : BaseController
{
public HomeController(IDIServiceProvider provider)
:base(provider)
{
}
public IActionResult()
{
_provider.GetScopedService<IEmailService>().SendSomething();
}
...
}
public class BaseController : Controller
{
protected readonly IDIServiceProvider _provider;
public BaseController(IDIServiceProvider provider)
{
_provider = provider;
}
}
So that I don't have to change all controller's constructors every time when BaseController's constructor changes and simplify all controller's constructors.
You can inject IServiceProvider to your controller and get your dependencies from that but it's not DI anymore and it's called Service Locator pattern.
public class HomeController
{
private readonly ITestService _testService;
public HomeController(IServiceProvider serviceProvider)
{
_testService = serviceProvider.GetRequiredService<ITestService>();
}
}
It's recommended to not use Service Locator because :
1- Your controller dependencies are not obvious with the first look.
2- It's harder to write unit tests for that.
3- Your service now needs one more dependency (IServiceProvider).
Use Service Locator pattern only when it needed like injecting your dependencies to FilterAttributes or ValidationAttributes. ( You can use ServiceFilter for this situations too. )

kernel.Get to get singleton instance

I have ConverterTest class where I need to access ValidateTest class. I can't pass ValidateTest using constructor because ConverterTest is abstract class. If I introduce second constructor to bind ValidateTest I will get numerous problems in derived classes and many things will need to change. So I have tried to pass ValidateTest to ConverterTest using property injection(decorated with inject attribute) but that also do not work because ConverterTest is not created by Ninject and inject properties are ignored. So I decided to create Instance property directly in ValidateTest class and bind instance of itself. To get instance of ValidateTest in ConverterTest class I use kernel.Get<ValidateTest>().Instance. Everything works fine but is it good idea to use kernel.Get to access instance class? Is there any other solution?
public class ValidateTest
{
private readonly ISettingsRepository _settingsRepository;
[Inject]
public ValidateTest Instance { get; set; }
public ValidateTest(ISettingsRepository settingsRepository)
{
_settingsRepository = settingsRepository;
}
}
Binding
kernel.Bind<ISettingsRepository>().To<SettingsRepository>();
kernel.Bind<ValidateAbuse>().ToSelf().InSingletonScope();
Getting instance of ValidateTest using kernel.Get in abstract class where constructor binding is not possible and property binding is not working.
public abstract class ConverterTest
{
public void Execute()
{
NinjectHelper.kernel.Get<ValidateTest>().Instance
}
}
Why not have your subclasses of ConverterTest set the ValidateTest either via an exposed property in ConverterTest or constructor's of their own?
public abstract class ConverterTest
{
protected ValidateTest ValidateTest{get;set;}
public void Execute()
{
ValidateTest.ValidateStuff();
}
}
public class ConcreteConverter : ConverterTest
{
[Inject]
public ConcreteConverter(ValidateTest validateTest)
{
base.ValidateTest = validateTest;
}
}
Or, I think that you could make the property public public ValidateTest ValidateTest{get;set;} and it should work for property injection if you add the appropriate attribute.
public abstract class ConverterTest
{
[Inject]
public ValidateTest ValidateTest{get;set;}
public void Execute()
{
ValidateTest.ValidateStuff();
}
}

Ninject fails to resolve interface type when the concrete type derives from an abstract base class

I have a problem with Ninject trying to resolve an interface type where the concrete type derives from an abstract base class that implements the interface.
EDIT: This is on Windows Mobile using .NET CF.
My particular issue involves presenters and views, so I stick to that in this example instead of foos and bars.
I want to inject factories for presenters and views to allow for late creation of those instances deep down the UI view stack.
Below I've omitted all error checking for better readability.
My factory interface:
public interface IFactory<T>
{
T Create();
}
My presenter and view:
public sealed class Presenter
{
private readonly View view;
public Presenter(View view)
{
this.view = view;
}
}
public sealed class View
{
public View()
{
}
}
First, I'll show what works perfectly, that Ninject resolves as expected. This will not include the abstract base class I mentioned at the beginning. After this, I'll add the slight modifications with the abstract base class that will make Ninject throw when trying to resolve the dependencies.
We see above that the presenter depends on the view, so the presenter factory will depend on the view factory:
public sealed class GoodPresenterFactory : IFactory<Presenter>
{
private readonly IFactory<View> viewFactory;
public GoodPresenterFactory(IFactory<View> viewFactory)
{
this.viewFactory = viewFactory;
}
public Presenter Create()
{
return new Presenter(this.viewFactory.Create());
}
}
public sealed class ViewFactory : IFactory<View>
{
public ViewFactory()
{
}
public View Create()
{
return new View();
}
}
Wiring this up with Ninject:
Bind<IFactory<Presenter>>().To<GoodPresenterFactory>();
Bind<IFactory<View>>().To<ViewFactory>();
And then resolving the presenter factory:
var presenterFactory = container.Get<IFactory<Presenter>>();
Everything up until now works perfectly. The dependency on the view factory inside the presenter factory is resolved as expected.
Now, I have a million classes that looks like GoodPresenterFactory above and I therefore wanted a small base class to handle some trivial common stuff, like the dependency on the view factory in the presenter factory:
public abstract class FactoryBase<T, U> : IFactory<T>
{
protected readonly U dependency;
protected FactoryBase(U dependency)
{
this.dependency = dependency;
}
public abstract T Create();
}
Then the presenter factory will change and something in that change will make Ninject fail resolving:
public sealed class BadPresenterFactory : FactoryBase<Presenter, IFactory<View>>
{
public BadPresenterFactory(IFactory<View> viewFactory)
: base(viewFactory)
{
}
public override Presenter Create()
{
return new Presenter(this.dependency.Create());
}
}
And changing the Ninject wiring accordingly:
Bind<IFactory<Presenter>>().To<BadPresenterFactory>();
Bind<IFactory<View>>().To<ViewFactory>();
Those changes will make Ninject throw an ArgumentNullException when doing
var presenterFactory = container.Get<IFactory<Presenter>>();
Call stack from the exception:
at System.Reflection.RuntimeMethodInfo.GetParentDefinition()
at System.Reflection.CustomAttribute.IsDefined(MemberInfo member, Type caType, Boolean inherit)
at System.Reflection.RuntimeMethodInfo.IsDefined(Type attributeType, Boolean inherit)
at System.Attribute.IsDefined(MemberInfo element, Type attributeType, Boolean inherit)
at System.Attribute.IsDefined(MemberInfo element, Type attributeType)
at Ninject.Infrastructure.Language.ExtensionsForMemberInfo.HasAttribute(MemberInfo member, Type type)
at Ninject.Selection.Heuristics.StandardInjectionHeuristic.ShouldInject(MemberInfo member)
at Ninject.Selection.Selector.<>c__DisplayClassa.<SelectMethodsForInjection>b__9(IInjectionHeuristic h)
at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source, Func`2 predicate)
at Ninject.Selection.Selector.<SelectMethodsForInjection>b__8(MethodInfo m)
at System.Linq.Enumerable.<WhereIterator>d__0`1.MoveNext()
at Ninject.Planning.Strategies.MethodReflectionStrategy.Execute(IPlan plan)
at Ninject.Planning.Planner.<>c__DisplayClass2.<GetPlan>b__0(IPlanningStrategy s)
at Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map[T](IEnumerable`1 series, Action`1 action)
at Ninject.Planning.Planner.GetPlan(Type type)
at Ninject.Activation.Providers.StandardProvider.Create(IContext context)
at Ninject.Activation.Context.Resolve()
at Ninject.KernelBase.<Resolve>b__4(IContext context)
at System.Linq.Enumerable.<SelectIterator>d__d`2.MoveNext()
at System.Linq.Enumerable.<CastIterator>d__b0`1.MoveNext()
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
at Ninject.ResolutionExtensions.Get[T](IResolutionRoot root, IParameter[] parameters)
at NinjectTest.Program.Main()
If I modify FactoryBase so that it has no dependency, it's just a naked base class, then Ninject also fails.
public abstract class NakedFactoryBase<T> : IFactory<T>
{
protected NakedFactoryBase()
{
}
public abstract T Create();
}
public sealed class PointlessPresenterFactory : NakedFactoryBase<Presenter>
{
private readonly IFactory<View> viewFactory;
public PointlessPresenterFactory(IFactory<View> viewFactory)
{
this.viewFactory = viewFactory;
}
public override Presenter Create()
{
return new Presenter(this.viewFactory.Create());
}
}
As you can see, that failing PointlessPresenterFactory is identical to the succeeding GoodPresenterFactory, apart from the direct IFactory<Presenter> implementation in GoodPresenterFactory, as opposed to the completeley naked base class used in PointlessPresenterFactory.
Any idea why Ninject fails to resolve when the factory base class is used?
This issue has been fixed in build 2.3.0.46 and will be part of the next release (2.4).
NOTE: because CF seems not to allow to detect is a method is generic or not the Inject attribute can not be defined on base methods anymore. It has to be defined on the overload method.

Injecting my UnitOfWork into my Repository Constructor

Im very new but on a quest to learn nhibernate and DI with structuremap so am making an app to test everything out.
I am having some problems injecting my unitofwork into my base repository. I create a unitofwork on every request then either commit or rollback at the end. But when tryin to inject into my base repository its always null when i go to use it in my methods. More specifically i get this error: "Object reference not set to an instance of an object". Any ideas what im doing wrong and if this is the correct route i should be going?
Many thanks in advance.
Base Repository:
public abstract class Repository<T> : IRepository<T>
{
public readonly IUnitOfWork _unitOfWork;
public Repository(IUnitOfWork UnitOfWork)
{
UnitOfWork = _unitOfWork;
}
public Repository() {}
public void Save(T obj)
{
_unitOfWork.CurrentSession.Save(obj);
}
}
StructureMap registry thats set in my application_start:
public class NHibernateRegistry : Registry
{
public NHibernateRegistry()
{
For<IUnitOfWork>().HybridHttpOrThreadLocalScoped().Use<UnitOfWork>();
For<ISession>().HybridHttpOrThreadLocalScoped().Use(context => context.GetInstance<ISessionFactory>().OpenSession());
For<ISessionFactory>().Singleton().Use(NHibernateSessionFactory.GetSessionFactory());
}
}
Update:
The baserepository is inherited by specific repositorys ie ArticleRepository then im injecting that into my aspx pages on application_start. Then my aspx page inherits a basepage where the buildUp takes place. And i access the repository like this:
public IArticleRepository ArticleRepo { get; set; }
public void SaveThing()
{
ArticleRepo.Save(object);
}
This gets called on application_start:
public class Bootstrapper
{
public static void BootStrap()
{
ObjectFactory.Configure(x =>
{
x.AddRegistry<NHibernateRegistry>();
x.AddRegistry<WebRegistry>();
});
}
}
And in the webregistry:
For<IArticleRepository>().Use<ArticleRepository>();
There is a good chance your ArticleRepository doesn't have a constructor that takes an IUnitOfWork as a parameter make sure you have the following
public class ArticleRepository : Repository<Article>
{
public ArticleRepository(IUnitOfWork unitOfWork) : base(unitOfWork)
{
}
...
}
Remember Strcuture map uses the greediest constructor on the class that it instantiates. Since your abstract repository class will never be instantiated it will not use its constructors. I would also suggest not having any default constructors if your classes need to have their dependencies injected that way. Less chance for errors that way.
public readonly IUnitOfWork _unitOfWork;
public Repository(IUnitOfWork UnitOfWork)
{
UnitOfWork = _unitOfWork;
}
I think you mean to write
public readonly IUnitOfWork _unitOfWork;
public Repository(IUnitOfWork UnitOfWork)
{
_unitOfWork = UnitOfWork;
}
You were assigning the local variable to the parameter instead of the parameter to the local variable.
Edit: Also you should write your parameter with a lowercase U 'unitOfWork' instead of 'UnitOfWork'