ASP.NET CORE 2.0 runtime value using DI - asp.net-core-2.0

In ASP.NET CORE 2.0, how can I pass runtime parameter(string type) such as dynamic connection string to my service as Dependency injection. The string parameter value will be dynamic and be taken from HttpContext.
I'm not able to understand how can I pass runtime parameter value using DI from Controller->Service->Repository class?
Below code is what I'm using. Please guide me.
Code
public class AccountController : BaseController//Controller
{
ILogger<AccountController> _logger;
private IUserService _userService;
public AccountController(
ILogger<AccountController> logger
, IUserService userService
) {
_logger = logger;
_userService = userService;
}
public class UserService : IUserService
{
private readonly IUserRepository _userRepository;
private readonly IRoleRepository _roleRepository;
public UserService(
IUserRepository userRepository
,IRoleRepository roleRepository
)
{
_userRepository = userRepository;
_roleRepository = roleRepository;
}
public class UserRepository : DbProvider, IUserRepository
{
private IConfiguration _configuration;
private DatabaseSetting _databaseSetting;
public UserRepository(IConfiguration configuration, IOptions<DatabaseSetting> databaseSetting) : base(configuration, databaseSetting)
{
_configuration = configuration;
_databaseSetting = databaseSetting.Value;
}
public static class StartupExtensions
{
public static IServiceCollection AddCloudscribeCore(this IServiceCollection services, IConfiguration configuration)
{
// Add application repository.
services.AddSingleton<AuthAttributeFilter>();
#region Add Repository Dependency Here
services.AddTransient<IUserRepository, UserRepository>();
services.AddTransient<IRoleRepository, RoleRepository>();
#endregion Repository Dependency
#region Add Service Dependency Here
services.AddTransient<ICompanyService, CompanyService>();
services.AddTransient<IUserService, UserService>();
#endregion Service Dependency
services.Configure<DatabaseSetting>(options =>
{
options.DBProvider = configuration["DatabaseSetting:DBProvider"];
options.ConnectionString = configuration["DatabaseSetting:ConnectionString"];
});
return services;
}
}

For accessing HttpContext in Service and Repository, there is no need to pass from Controller, try IHttpContextAccessor.
public class UserRepository : DbProvider, IUserRepository
{
private IConfiguration _configuration;
private DatabaseSetting _databaseSetting;
private readonly IHttpContextAccessor _accessor;
public UserRepository(IConfiguration configuration, IOptions<DatabaseSetting> databaseSetting, IHttpContextAccessor accessor) : base(configuration, databaseSetting)
{
_configuration = configuration;
_databaseSetting = databaseSetting.Value;
_accessor = accessor;
}
Then, you could access HttpContext by _accessor.HttpContext.

Related

Springboot mockito mock a field

I want to mock the TreeMap in Service class, I tried to mock using TreeMap<String, String> requestsMap = Mockito.mock(TreeMap.class); But the map is getting null at runtime.
#RunWith(SpringRunner.class)
#SpringBootTest
#WebAppConfiguration
public class ServiceTest {
#InjectMocks
private Service service;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() {
TreeMap<String, String> requestsMap = Mockito.mock(TreeMap.class);
}
}
#Service
public class Service {
private TreeMap<String, String> requestsMap = null;
}
Your Service class doesn't actually do anything but declare and initialize the requestMap to null. Also, your test method doesn't do anything other than declare a mock requestMap.
In addition to the code you have, write a method in the Service that uses the request map and just declare/autowire the requestMap. In your test, use the #Mock annotation on a declaration of your mock requestMap. Finally, use the mocked requestMap in your test.
For example:
#RunWith(SpringRunner.class)
#SpringBootTest
#WebAppConfiguration
public class ServiceTest {
#Mock
TreeMap<String, String> requestsMap;
#InjectMocks
private Service service;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() {
when(requestMap.get("foo")).thenReturn("bar");
String result = service.doSomething();
assertEquals(result, "bar");
}
}
#Service
public class Service {
#Autowired
private TreeMap<String, String> requestsMap;
public String doSomething() {
return requestMap.get("foo");
}
}

Is it possible to use Jax-WS with a Generic interface?

How to use a generic common Interface for Jax-WS ?
public interface IGenericWebService<T extends Record> {
#WebMethod
public List<T> listAll();
}
how to make it works without overriding the method ?
#WebService
public interface IWCustomerService extends IGenericWebService<Customer>{
/*
#WebMethod
public List<Customer> listAll(); */
}
Common implementation
public abstract class GenericWebService<T extends Record> implements IGenericWebService<T>{
protected static Log log = LogFactory.getLog(GenericWebService.class);
}
Customer Service
#WebService(endpointInterface="com.dev.bridge.iwservices.IWCustomerService")
#Service
public class WCustomerService extends GenericWebService<Customer> implements IWCustomerService{
#Autowired
private ICustomerService customerService;
public List<Customer> listAll() {
try {
return customerService.listAll();
} catch (CoreException e) {
log.error(e.getMessage(), e);
}
return new ArrayList<Customer>();
}
}

Property injection with Unity

i encoutered problem with unity, i want to use property injection, here is what i had in my code :
config of the container :
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<GTModelContainer, GTModelContainer>(new HttpContextLifetimeManager<GTModelContainer>())
.RegisterType<IUnitOfWork, UnitOfWorkGT>()
.RegisterType<ILogger, Logger>(new ContainerControlledLifetimeManager())
.RegisterType<ISocieteServices, SocieteServices>() ;
}
SocieteService Class :
public class SocieteServices : ISocieteServices
{
private IUnitOfWork UnitOfWork;
public SocieteServices(IUnitOfWork unitOfWork)
{
UnitOfWork = unitOfWork;
}
}
i tried to use property injection (i can't use constructor injection with custom data annotation) and here what i had done :
public class CodeSocieteUniqueAttribute : ValidationAttribute
{
[Dependency]
public ISocieteServices SocieteService {get; set;}
[InjectionMethod]
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
string codeSociete = value as string;
var societe = SocieteService.getSocieteByCode(codeSociete);
if (societe == null) return ValidationResult.Success;
else return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
}
the problem is that the societeService in CodeSocieteUniqueAttribute class is not injected.
Assuming that your class for registering types is publicly accessible and has a IUnityContainer object, ie:
public static class Resolver
{
public static IUnityContainer Container { get; set; }
public static void RegisterTypes(IUnityContainer container)
{
// type registrations here
container.RegisterType<GTModelContainer, GTModelContainer>(new HttpContextLifetimeManager<GTModelContainer>())
.RegisterType<IUnitOfWork, UnitOfWorkGT>()
.RegisterType<ILogger, Logger>(new ContainerControlledLifetimeManager())
.RegisterType<ISocieteServices, SocieteServices>() ;
// Now, set the container
Container = container;
}
}
You could access the container you've built up and resolve these types during method execution.
For instance,
public class CodeSocieteUniqueAttribute : ValidationAttribute
{
[Dependency]
public ISocieteServices SocieteService { get; set; }
[InjectionMethod]
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var societeServices = Resolver.Container.Resolve<ISocieteServices>();
SocieteService = societeServices; // Or, you know, just use this since it's resolved.
string codeSociete = value as string;
var societe = SocieteService.getSocieteByCode(codeSociete);
if (societe == null) return ValidationResult.Success;
else return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
}
This is actually pretty standard practice, and this MSDN article describes resolving items during runtime.
Another option is to pop the resolution into a default constructor like this:
public class CodeSocieteUniqueAttribute : ValidationAttribute
{
[Dependency]
public ISocieteServices SocieteService {get; set;}
public CodeSocieteUniqueAttribute()
{
var societeServices = Resolver.Container.Resolve<ISocieteServices>();
SocieteService = societeServices;
}
// the rest of the class omitted for brevity
}

Custom AuthenticationFilter with token-based authentication

I am using token-based authentication. I have a custom authentication filter which does a REST call to authenticate the user. I managed to create and configure the custom authentication provider but having trouble setting the order of the providers. I want the default DaoAuthenticationProvider to be the default and customProvider to be the secondary.
This is how I configured the customAuthenticationProvider
#Inject
private CustomAuthenticationProvider customAuthenticationProvider;
#Inject
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(customAuthenticationProvider)
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
How can I configure customAuthenticationProvider to be the second provider?
PS: I couldn't Inject the customAuthenticationProvider into SecurityConfiguration.java as the Proxy couldn't be created until I added the following scope to customAuthenticationProvider.
#Component("alfrescoAuthenticationProvider")
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS, value = "prototype")
public class AlfrescoAuthenticationProvider implements AuthenticationProvider {
....
}
I don't understand what you said about why you can not inject. My SecurityConfiguration class is as below:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Inject
private Http401UnauthorizedEntryPoint authenticationEntryPoint;
#Inject
private UserDetailsService userDetailsService;
#Inject
private TokenProvider tokenProvider;
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Inject
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
auth.authenticationProvider(weixinAuthenticationProvider());
}
#Bean
public WeixinAuthenticationProvider weixinAuthenticationProvider() {
WeixinAuthenticationProvider provider = new WeixinAuthenticationProvider(userDetailsService, passwordEncoder());
return provider;
}
#Override
public void configure(WebSecurity web) throws Exception {
......
I hope it can help.

ServiceStack's Funq.Container not Newing-Up Properties

My service uses a utility class and that utility class has several public properties. Is there something special I need call to ensure these public properties are setup?
The service uses a ASP.NET host. Inside of Global.ASAX I have declared a new AppHostBase:
public class MyServiceHost : AppHostBase
{
public MyServiceHost() : base("My Service Host", typeof(ServiceLibrary).Assembly) {}
public override void Configure(Funq.Container container)
{
container.Register<IDbConnectionFactory>(dbConFactory);
container.RegisterAutoWired<UtilityLibrary>();
container.RegisterAutoWired<RepositoryLibrary>();
}
}
Within both my repository library and utility library is a main class. This may class receives the Container and registers more specific utilities and repositories:
public class UtilityLibrary
{
public UtilityLibrary(Funq.Container container)
{
container.RegisterAutoWired<WidgetAActions>();
container.RegisterAutoWired<WidgetBActions>();
}
}
In the example below, WidgetARepository was set in the constructor of the RepositoryLibrary class. The RepositoryLibrary class, which contains the WidgetARepository, was supplied to the Container in the Configure method of the AppHost (first snippet above). Even still, the WidgetARepository (below) is never set:
public class WidgetAActions
{
public WidgetARepository WidgetARepository { get; set; }
public WidgetA Get(string id)
{
var item = this.WidgetARepository.Get(id);
if (item == null) { return null; }
// Do something else
return item;
}
}
Must I manually call Resolve()? This seems like it would defeat the purpose of injection by doing this.
If you are using wanting to use the Funq Container Autowire IoC outside of the ServiceStack service then you need to call Container.AutoWire yourself to have the container inject the relevant dependencies. This call is made behind the scenes in the ServiceStack request pipeline.
For ServiceStack v4:
HostContext.Container.AutoWire(objectToPopulate);
For ServiceStack v3:
AppHostBase.Instance.Container.AutoWire(objectToPopulate);
I would typically add this call to the construtor method of the object I want populated with the injections. So in your case:
public class WidgetAActions
{
public WidgetARepository WidgetARepository { get; set; }
public WidgetAActions()
{
// (Substitute with v3 usage if required.)
HostContext.Container.AutoWire(this);
}
...
}
Hope this helps.
Edit: Have you considered having the container inject the corresponding repository to WidgetAActions's constructor?
container.RegisterAutoWired<WidgetAActions>(c => new WidgetAActions(c.Resolve<WidgetARepository>()));
public class WidgetAActions
{
public WidgetARepository WidgetARepository { get; private set; }
public WidgetAActions(WidgetARepository repository)
{
WidgetARepository = repository;
}
...
}
Edit: Or you could resolve and set the public property of your object to the repository and then you don't have to have a constructor:
container.RegisterAutoWired<WidgetAActions>(c =>
new WidgetAActions { WidgetARepository = c.Resolve<WidgetARepository>() }
);
public class WidgetAActions
{
public WidgetARepository WidgetARepository { get; set; }
...
}
Or you could call autowire at time of resolving WidgetAActions:
container.RegisterAutoWired<WidgetAActions>(c => {
var actions = new WidgetAActions();
container.AutoWire(actions); // All dependencies injected
return actions;
});
public class WidgetAActions
{
public WidgetARepository WidgetARepository { get; set; }
...
}

Resources