Asp.NET MVC Autofac Inject Dependence non-controller class - asp.net

All classes that inherit from controller have already inserted the dependencies, but I do not know how to inject those who do not inherit from contoller.
in the example below the SendEmailAndLog() method waits for the ILoggerService interface to be injected. but I do not know how to do this.
public async Task Execute(IJobExecutionContext context)
{
SendEmailHelper sendEmailHelper = new SendEmailHelper();
await sendEmailHelper.SendEmailAndLog(user, "Task", user.UserName, UserManager, loggerService);
}
this task is called the method Application_Start() on Global.asax.cs
I created a constructor to receive this service as a parameter, this is working for the methods within the controllers that call the Class Emailservice. However there are classes that do not inherit from controller so I do not know how to inject.
My Service is:
public interface ILoggerService
{
void Error(ExceptionLogger exception);
void SaveLog();
}
public class LoggerService : ILoggerService
{
private readonly ILoggerRepository loggerRepository;
private readonly IUnitOfWork unitOfWork;
public LoggerService(ILoggerRepository loggerRepository, IUnitOfWork unitOfWork)
{
this.loggerRepository = loggerRepository;
this.unitOfWork = unitOfWork;
}
public void Error(ExceptionLogger exception)
{
loggerRepository.Error(exception);
}
public void SaveLog()
{
unitOfWork.Commit();
}
}

Related

Get HubContext from outside of Hub using Aspnetcore.signalr libray (not from Controller)

I am developing SignalR service using AspNetCore.SignalR.
Following is my Hub:
public class NotificationHub : Microsoft.AspNetCore.SignalR.Hub
{
public override async Task OnConnectedAsync()
{
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception exception)
{
await base.OnDisconnectedAsync(exception);
}
}
Following is Another Context class that i have created to invoke Hub's method on client side:
public class NotificationHubContext
{
private readonly IHubContext<NotificationHub> _context;
public NotificationHubContext(IHubContext<NotificationHub> context)
{
_context = context;
}
public async Task Broadcast(string groupId, string eventName, object data)
{
await _context.Clients.Group(groupId).SendAsync(eventName, data);
}
}
I would like to Inject reference of NotificationContext class into my own IoC Container so I can just resolve it and call a BroadCast method on it and it should handle sending messages to clients.
I am using Service Bus to listen for messages from another part of the system, once I receive a message from Queue, I would like to notify Connected clients using HubContext from QueueHandler.
Assembly Info
var hubContext = app.ApplicationServices.GetService<IHubContext<Notification>>
That resolved my issue.
I design my class as below.
public class NotificationHub : Microsoft.AspNetCore.SignalR.Hub
{
public static IHubContext<NotificationHub> Current { get; set; }
}
In your Startup class
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
NotificationHub.Current = app.ApplicationServices.GetService<IHubContext<NotificationFromServerHub>>();
}
So, you can use as like this from anywhere.
public class MyBizClass
{
public void DoSomething()
{
NotificationHub.Current.MyMethod(...);
}
}

Asp.Core Depenency Injection Session Null

I have a Asp.Core project with dependency injection. The problem is that when I get an instance of a CustomerService my session is null. But I pass it through with dependency injection.
My Controller looks like this:
private ISessionService _sessionService;
private IContainer _container;
public AuthController(ISessionService sessionService, IContainer container) {
_container = container;
_sessionService = sessionService;
// here my session is NOT NULL
string userName = _sessionService.Username;
}
public IActionResult Index() {
// here I have some code so the line below is not always needeed and therefore not injected in the constructor
IUserService userService = _container.GetInstance<IUserService>();
// here my session is NULL
string name = userService.GetUserName();
}
public class UserService : IUserService {
private ISessionService _sessionService;
private IHttpContextAccessor _httpContextAccessor;
public UserService(ISessionService sessionSerivce, IHttpContextAccessor httpContextAccessor) {
_sessionService = sessionSerivce;
_httpContextAccessor = httpContextAccessor;
}
public string GetUserName() {
return _sessionService.User.Name;
}
}
my StartUp.cs where I'm using StructureMap
Container container = new Container(expr => {
expr.For<IHttpContextAccessor>().Use<HttpContextAccessor>();
expr.For<ISessionService>().Use<SessionService>();
expr.For<IUserService>().Use<UserService>();
});
So why is my session null when I instantiate a UserService object when using the container class ?
UPDATE
I know now that the Session object is null because the life cycle of a MVC page. In my BaseController class I created a method named InitContainer like this:
public void InitContainer(Type typeOfInterface, Type typeOfClass) {
Configure(expr =>
For(typeOfInterface).Use(typeOfClass)
.Ctor<ISessionService>().Is(_sessionService)
.Ctor<IHttpContextAccessor>().Is(_httpContextAccessor)
);
}
}
When I want to use an instance of a service than I do this in my Controller method:
public IActionResult Test() {
InitContainer(typeof(ICustomerService), typeof(CustomerService));
ICustomerService customerService = _container.GetInstance<ICustomerService>();
}
I don't know if it's ugly or the right way to do this, but it works for me now.
Has someone a better way to do this?

Spring MVC - How to create a proper Service layer?

I'm using SpringBoot and I am trying to create a service layer for my web application but i cant make it work.
My classes look like this
ServiceFactory
#Service
public class ServiceFactory {
#Autowired
public static EncuestaService getEncuestaService()
{
return new EncuestaServiceImpl();
}
}
EncuestaService
public interface EncuestaService {
void crearEncuesta(Encuesta encuesta, Map<String,String> parametros);
}
EncuestaServiceImpl
#Service
public class EncuestaServiceImpl implements EncuestaService {
#Override
public void crearEncuesta(Encuesta encuesta, Map<String, String> parametros) {
CrearEncuesta nueva = new CrearEncuesta(encuesta,parametros);
nueva.execute();
}
}
CrearEncuesta
#Service
public class CrearEncuesta {
private Encuesta encuesta;
private Map<String,String> parametros;
#Autowired
private RespuestasRepository respuestasRepository;
#Autowired
private EncuestasRepository encuestasRepository;
public CrearEncuesta(Encuesta encuesta, Map<String,String> parametros) {
super();
this.encuesta = encuesta;
this.parametros = parametros;
}
public void execute()
{
encuestasRepository.save(encuesta);
}
}
Everytime I call ServiceFactory.getEncuestasService().crearEncuesta() from any Controller it returns me a NullPointerException.
From what I have been reading I should not be creating a new EncuestsaServiceImpl() in my ServiceFactory but I don't really know the correct way to do so. I would appreciate if anyone could help me out :P.
Edit:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
Controller
#Controller
public class EncuestaController {
#RequestMapping(value ="registrarEncuesta", method = RequestMethod.POST)
private String formularioEncuesta(#Valid #ModelAttribute("formEncuesta") EncuestaForm formEncuesta, BindingResult bindingResult,#RequestParam Map<String,String> allRequestParams)
{
if (bindingResult.hasErrors()) {
return "nuevaEncuesta";
}
try {
Encuesta nueva = formEncuesta.toEncuesta();
ServiceFactory.getEncuestaService().crearEncuesta(nueva,allRequestParams);
} catch (DataIntegrityViolationException e) {
return "nuevaEncuesta";
}
return "redirect:/encuestas";
}
}
You will have to read a little bit more about dependency injection. The central principle in Spring Framework is dependency injection which should be used to avoid referencing beans (service implementations, repository implementations etc...) statically. Spring container also servers as a bean factory that will instantiate and inject (autowire) implementations to beans that need them.
Because Spring will instantiate service interface implementations for you, you don't need ServiceFactory. In your controller you need to add a reference (a field) to EncuestaService and annotate it as Autowired and Spring will wire in the implementation. And then you can just use it in your controller.
#Controller
public class EncuestaController {
#Autowired
EncuestaService encuestaService;
#RequestMapping(value ="registrarEncuesta", method = RequestMethod.POST)
private String formularioEncuesta(#Valid #ModelAttribute("formEncuesta") EncuestaForm formEncuesta, BindingResult bindingResult,#RequestParam Map<String,String> allRequestParams)
{
if (bindingResult.hasErrors()) {
return "nuevaEncuesta";
}
try {
Encuesta nueva = formEncuesta.toEncuesta();
encuestaService.crearEncuesta(nueva,allRequestParams);
} catch (DataIntegrityViolationException e) {
return "nuevaEncuesta";
}
return "redirect:/encuestas";
}
}

Unity Dependency Injection error - No parameterless constructor defined for this object

I have an application with a GenericHandler and would like to inject dependencies using Unity. No matter what I try I get the error:
[MissingMethodException: No parameterless constructor defined for this object.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean
I have tried to follow the example at http://geekswithblogs.net/Rhames/archive/2012/09/11/loosely-coupled-.net-cache-provider-using-dependency-injection.aspx.
My constructor for the handler is as follows:
public class GetPerson : IHttpHandler
{
private IPersonRepository repo;
public GetPerson(IPersonRepository repo)
{
this.repo = repo;
}
IPersonRepository is implemented by CachedPersonRepository. CachedPersonRepository wraps the PersonRepository (which is used for DataAccess if an item cannot be found in the cache). Both CachedPersonRepository and PersonRepository are IPersonRepository:
public class CachedPersonRepository : IPersonRepository
{
private ICacheProvider<Person> cacheProvider;
private IPersonRepository personRepository;
public CachedPersonRepository(IPersonRepository personRepository, ICacheProvider<Person> cacheProvider)
{
This IPersonRepository personRepository is parameterless.
ICacheProvider<Person> is implemented by MemcachedCacheProvider<T>:
public class MemcachedCacheProvider<T> : ICacheProvider<T>
{
public T Get(string key, Func<T> retrieveData, DateTime? absoluteExpiry, TimeSpan relativeExpiry)
{
I have tried unsuccessfully to initialise the Unity Container in my Global.asax file Application_Start. DI is new to me and I would very much appreciate any advice on where I'm going wrong.
There were actually two issues here.
Firstly, CachedPersonRepository uses the Decorator pattern which I didn't properly understand before. Once I understood this I was able to register and resolve the PersonRepository appropriately using this configuration:
public static void Configure(IUnityContainer container)
{
container.RegisterType<ICacheProvider<Person>, MemcachedCacheProvider<Person>>();
container.RegisterType<IPersonRepository, PersonRepository>("PersonRepository", new ContainerControlledLifetimeManager());
container.RegisterType<IPersonRepository, CachedPersonRepository>(
new InjectionConstructor(
new ResolvedParameter<IPersonRepository>("PersonRepository"),
new ResolvedParameter<ICacheProvider<Person>>()));
container.Resolve<IPersonRepository>();
}
Having fixed this I still saw the same "No parameterless constructor defined for this object" error.
The reason for this, is that I was working with an IHttpHandler and it is not possible to inject dependencies in the constructor.
I got around this by using Property injection:
A Repository property with the Dependency Attribute has been added to the GetPerson handler:
public class GetPerson : HandlerBase
{
[Dependency]
public IPersonRepository Repository { get; set; }
A new http module was needed to check for requests from handlers which implemented my HandlerBase:
public class UnityHttpModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += OnPreRequestHandlerExecute;
}
public void Dispose() { }
private void OnPreRequestHandlerExecute(object sender, EventArgs e)
{
IHttpHandler currentHandler = HttpContext.Current.Handler as HandlerBase;
if (currentHandler != null)
{
HttpContext.Current.Application.GetContainer().BuildUp(
currentHandler.GetType(), currentHandler);
}
}
}
Resources:
http://download.microsoft.com/download/4/D/B/4DBC771D-9E24-4211-ADC5-65812115E52D/DependencyInjectionWithUnity.pdf (Chapter 4, pages 60-63)
http://msdn.microsoft.com/en-us/library/ff664534(v=pandp.50).aspx

Dependency Resolver using Ninject

I am always getting the error
No parameterless constructor defined for this object.
when I execute the codes below.
It must be something to do with my ninject modules.
What seems to be the problem here?
Controller
public class AccountController : Controller
{
private readonly IUserService _service;
public AccountController(IUserService service)
{
_service = service;
}
}
Service Layer
public class UserService : ServiceBase<User>, IUserService
{
public UserService(IRepository repository) : base(repository)
{
}
}
public interface IUserService : IService<User>
{
}
Repository
public class UserRepository : RepositoryBase<User>, IUserRepository
{
}
public interface IUserRepository : IRepository<User>
{
}
Ninject ----
ServiceModule
public class ServiceModule : NinjectModule
{
public override void Load()
{
Bind<IUserService>().To<UserService>();
}
}
RepositoryModule
public class RepositoryModule : NinjectModule
{
public override void Load()
{
Bind<IUserRepository>().To<UserRepository>();
}
}
Setup
public static void SetupDependencyInjection()
{
// Create Ninject DI kernel
var kernel = CreateKernel();
// Tell ASP.NET MVC 3 to use our Ninject DI Container
DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
}
private static IKernel CreateKernel()
{
var modules = new INinjectModule[]
{
new ServiceModule(),
new RepositoryModule()
};
return new StandardKernel(modules);
}
Have have registered:
Bind<IUserRepository>().To<UserRepository>();
But you are referring to the base IRepository interface in UserService:
public UserService(IRepository repository) : base(repository)
{
}
So Ninject won't know how to construct a generic IRepository. You need to Bind a implementation for IRepository. Or use IUserRepository in UserService:
public UserService(IUserRepository repository) : base(repository)
{
}

Resources