Is there a replacement for aspnetboilerplate IIocResolver.ResolveAll? - abp

Is there a comparible interface / functionality in abp.io ?
I need something like this:
public PaymentGatewayStore(IIocResolver iocResolver)
{
_iocResolver = iocResolver;
}
public List<PaymentGatewayModel> GetActiveGateways()
{
var gateways = _iocResolver.ResolveAll<IPaymentGatewayConfiguration>();
return gateways.Where(gateway => gateway.IsActive).Select(gateway => new PaymentGatewayModel
{
GatewayType = gateway.GatewayType,
SupportsRecurringPayments = gateway.SupportsRecurringPayments
}).ToList();
}
Geert Veenstra

You can inject IEnumerable<IYourService> to inject all implementations of an interface. Alternatively, you can use IServiceProvider.GetServices<IYourService>().
This is standard Dependency Injection system of the AspNet Core. See the documentation.

Related

Data Acces Objects Factory Design Pattern in React?

I'm currently going through some tutorial about React Design Patterns, subject: Custom Hooks.
While the concept feels awesome and seems familiar to me, the solution below provided by the tutor made me question how to deal with different data sources.
Is there something like the above mentioned DAO Factory Pattern, you can find in Frameworks like J2E?
Or how is the common approach to handle this challenges in React to make the code maintainable?
My first intension woulda be throwing the stuff into a Factory Component and having implementations for the specific providers, basically like it is shown in the two other Code snippets bewlow.
Is this the regular wayt to do it?
Any help, tips, additional sources to learn this would be highly appreciated.
Here's the solution, with the both possible implementations thrown into the React Form Component:
import axios from 'axios';
import { useDataSource } from './useDataSource';
import { useResource } from './useResource';
import { useUser } from './useUser';
const serverResource = resourceUrl => async () => {
const response = await axios.get(resourceUrl);
return response.data;
};
const localStorageResource = key => () => {
return localStorage.getItem(key);
}
export const UserInfo = ({ userId }) => {
// const user = useResource(`/users/${userId}`);
const user = useDataSource(serverResource(`/users/${userId}`));
const message = useDataSource(localStorageResource('message'));
const { name, age, hairColor, hobbies } = user || {};
return user ? (
<>
<h3>{name}</h3>
<p>Age: {age} years</p>
<p>Hair Color: {hairColor}</p>
<h3>Hobbies:</h3>
<ul>
{hobbies.map(hobby => <li key={hobby}>{hobby}</li>)}
</ul>
</>
) : <p>Loading...</p>;
}
And here's the DAO Factory Pattern example provided by Oracle:
src: https://www.oracle.com/java/technologies/dataaccessobject.html
// Abstract class DAO Factory
public abstract class DAOFactory {
// List of DAO types supported by the factory
public static final int CLOUDSCAPE = 1;
public static final int ORACLE = 2;
public static final int SYBASE = 3;
...
// There will be a method for each DAO that can be
// created. The concrete factories will have to
// implement these methods.
public abstract CustomerDAO getCustomerDAO();
public abstract AccountDAO getAccountDAO();
public abstract OrderDAO getOrderDAO();
...
public static DAOFactory getDAOFactory(
int whichFactory) {
switch (whichFactory) {
case CLOUDSCAPE:
return new CloudscapeDAOFactory();
case ORACLE :
return new OracleDAOFactory();
case SYBASE :
return new SybaseDAOFactory();
...
default :
return null;
}
}
}
...with a concrete implementation:
// Cloudscape concrete DAO Factory implementation
import java.sql.*;
public class CloudscapeDAOFactory extends DAOFactory {
public static final String DRIVER=
"COM.cloudscape.core.RmiJdbcDriver";
public static final String DBURL=
"jdbc:cloudscape:rmi://localhost:1099/CoreJ2EEDB";
// method to create Cloudscape connections
public static Connection createConnection() {
// Use DRIVER and DBURL to create a connection
// Recommend connection pool implementation/usage
}
public CustomerDAO getCustomerDAO() {
// CloudscapeCustomerDAO implements CustomerDAO
return new CloudscapeCustomerDAO();
}
public AccountDAO getAccountDAO() {
// CloudscapeAccountDAO implements AccountDAO
return new CloudscapeAccountDAO();
}
public OrderDAO getOrderDAO() {
// CloudscapeOrderDAO implements OrderDAO
return new CloudscapeOrderDAO();
}
...
}
how is the common approach to handle this challenges in React to make the code maintainable?
sure you can. As design patterns do not depend on programming language.
If you are using TypeScript, then you can use Abstract class
If you are using plain JavaScript, then you can use the following approach
An example of using Factory in React can be seen here.

About load supported cultures from DB in .NET CORE

I have a Language entity with all supported languages in my db, each language has a culture string attribute. I want to load supported cultures from DB.
In my service initializer I have it:
public void ConfigureServices(IServiceCollection services)
{
// ... previous configuration not shown
services.Configure<RequestLocalizationOptions>(
opts =>
{
var supportedCultures = new List<CultureInfo>
{
new CultureInfo("en-GB"),
new CultureInfo("en-US"),
new CultureInfo("en"),
new CultureInfo("fr-FR"),
new CultureInfo("fr"),
};
opts.DefaultRequestCulture = new RequestCulture("en-GB");
// Formatting numbers, dates, etc.
opts.SupportedCultures = supportedCultures;
// UI strings that we have localized.
opts.SupportedUICultures = supportedCultures;
});
}
How I can access my DB context inside it?
There is any other better way to do it?
I don't think there's an out of the box solution for this.
However, you can implement your own middleware that achieves this by using ASP.Net's RequestLocalizationMiddleware:
public class CustomRequestLocalizationMiddleware
{
private readonly RequestDelegate next;
private readonly ILoggerFactory loggerFactory;
public CustomRequestLocalizationMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
{
this.next = next;
this.loggerFactory = loggerFactory;
}
public async Task Invoke(HttpContext context /* You can inject services here, such as DbContext or IDbConnection*/)
{
// You can search your database for your supported and/or default languages here
// This query will execute for all requests, so consider using caching
var cultures = await Task.FromResult(new[] { "en" });
var defaultCulture = await Task.FromResult("en");
// You can configure the options here as you would do by calling services.Configure<RequestLocalizationOptions>()
var options = new RequestLocalizationOptions()
.AddSupportedCultures(cultures)
.AddSupportedUICultures(cultures)
.SetDefaultCulture(defaultCulture);
// Finally, we instantiate ASP.Net's default RequestLocalizationMiddleware and call it
var defaultImplementation = new RequestLocalizationMiddleware(next, Options.Create(options), loggerFactory);
await defaultImplementation.Invoke(context);
}
}
Then, we inject the required services and use the custom middleware in Startup.cs or Program.cs as follows:
services.AddLocalization()
/* ... */
app.UseMiddleware<CustomRequestLocalizationMiddleware>()
Do not call app.UseRequestLocalization(), because this would call ASP.Net's RequestLocalizationMiddleware again with the default options, and override the culture that has been resolved previously.

React native- Best way to create singleton pattern

I am new in react-native coding but have experienced on objective-c and swift coding and want use singleton pattern in react-native.
I have tried to find out the solution from other StackOverflow answer but most of them are creating only singleton functions as below code:
var Singleton = (function () {
var instance;
function createInstance() {
var object = new Object("I am the instance");
return object;
}
return {
getInstance: function () {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
function run() {
var instance1 = Singleton.getInstance();
var instance2 = Singleton.getInstance();
alert("Same instance? " + (instance1 === instance2));
}
As we can see in above code here we are creating singleton function not class.
Please let me know if any way to create singleton class and pass multiple variables in that class as objective-c or swift.
Note: Please also notify me if I am going in the wrong direction.
Here's my implementation for singleton class...
Controller.js
export default class Controller {
static instance = Controller.instance || new Controller()
helloWorld() {
console.log("Hello World... \(^_^)/ !!")
}
}
Usage:
import Controller from 'Controller.js'
Controller.instance.helloWorld()
You can use something like that
class SingletonClass {
static instance = null;
static createInstance() {
var object = new SingletonClass();
return object;
}
static getInstance () {
if (!SingletonClass.instance) {
SingletonClass.instance = SingletonClass.createInstance();
}
return SingletonClass.instance;
}
}
var instance1 = SingletonClass.getInstance();
var instance2 = SingletonClass.getInstance();
The singleton pattern isn't used much in the JS ecosystem. What you should look into is http://mobx.js.org. MobX is a library that allows you to create observable objects to store data for your apps. You instantiate one store for each domain you please and make edits to that store to change app state.

Integration testing with in-memory IdentityServer

I have an API that uses IdentityServer4 for token validation.
I want to unit test this API with an in-memory TestServer. I'd like to host the IdentityServer in the in-memory TestServer.
I have managed to create a token from the IdentityServer.
This is how far I've come, but I get an error "Unable to obtain configuration from http://localhost:54100/.well-known/openid-configuration"
The Api uses [Authorize]-attribute with different policies. This is what I want to test.
Can this be done, and what am I doing wrong?
I have tried to look at the source code for IdentityServer4, but have not come across a similar integration test scenario.
protected IntegrationTestBase()
{
var startupAssembly = typeof(Startup).GetTypeInfo().Assembly;
_contentRoot = SolutionPathUtility.GetProjectPath(#"<my project path>", startupAssembly);
Configure(_contentRoot);
var orderApiServerBuilder = new WebHostBuilder()
.UseContentRoot(_contentRoot)
.ConfigureServices(InitializeServices)
.UseStartup<Startup>();
orderApiServerBuilder.Configure(ConfigureApp);
OrderApiTestServer = new TestServer(orderApiServerBuilder);
HttpClient = OrderApiTestServer.CreateClient();
}
private void InitializeServices(IServiceCollection services)
{
var cert = new X509Certificate2(Path.Combine(_contentRoot, "idsvr3test.pfx"), "idsrv3test");
services.AddIdentityServer(options =>
{
options.IssuerUri = "http://localhost:54100";
})
.AddInMemoryClients(Clients.Get())
.AddInMemoryScopes(Scopes.Get())
.AddInMemoryUsers(Users.Get())
.SetSigningCredential(cert);
services.AddAuthorization(options =>
{
options.AddPolicy(OrderApiConstants.StoreIdPolicyName, policy => policy.Requirements.Add(new StoreIdRequirement("storeId")));
});
services.AddSingleton<IPersistedGrantStore, InMemoryPersistedGrantStore>();
services.AddSingleton(_orderManagerMock.Object);
services.AddMvc();
}
private void ConfigureApp(IApplicationBuilder app)
{
app.UseIdentityServer();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
var options = new IdentityServerAuthenticationOptions
{
Authority = _appsettings.IdentityServerAddress,
RequireHttpsMetadata = false,
ScopeName = _appsettings.IdentityServerScopeName,
AutomaticAuthenticate = false
};
app.UseIdentityServerAuthentication(options);
app.UseMvc();
}
And in my unit-test:
private HttpMessageHandler _handler;
const string TokenEndpoint = "http://localhost/connect/token";
public Test()
{
_handler = OrderApiTestServer.CreateHandler();
}
[Fact]
public async Task LeTest()
{
var accessToken = await GetToken();
HttpClient.SetBearerToken(accessToken);
var httpResponseMessage = await HttpClient.GetAsync("stores/11/orders/asdf"); // Fails on this line
}
private async Task<string> GetToken()
{
var client = new TokenClient(TokenEndpoint, "client", "secret", innerHttpMessageHandler: _handler);
var response = await client.RequestClientCredentialsAsync("TheMOON.OrderApi");
return response.AccessToken;
}
You were on the right track with the code posted in your initial question.
The IdentityServerAuthenticationOptions object has properties to override the default HttpMessageHandlers it uses for back channel communication.
Once you combine this with the CreateHandler() method on your TestServer object you get:
//build identity server here
var idBuilder = new WebBuilderHost();
idBuilder.UseStartup<Startup>();
//...
TestServer identityTestServer = new TestServer(idBuilder);
var identityServerClient = identityTestServer.CreateClient();
var token = //use identityServerClient to get Token from IdentityServer
//build Api TestServer
var options = new IdentityServerAuthenticationOptions()
{
Authority = "http://localhost:5001",
// IMPORTANT PART HERE
JwtBackChannelHandler = identityTestServer.CreateHandler(),
IntrospectionDiscoveryHandler = identityTestServer.CreateHandler(),
IntrospectionBackChannelHandler = identityTestServer.CreateHandler()
};
var apiBuilder = new WebHostBuilder();
apiBuilder.ConfigureServices(c => c.AddSingleton(options));
//build api server here
var apiClient = new TestServer(apiBuilder).CreateClient();
apiClient.SetBearerToken(token);
//proceed with auth testing
This allows the AccessTokenValidation middleware in your Api project to communicate directly with your In-Memory IdentityServer without the need to jump through hoops.
As a side note, for an Api project, I find it useful to add IdentityServerAuthenticationOptions to the services collection in Startup.cs using TryAddSingleton instead of creating it inline:
public void ConfigureServices(IServiceCollection services)
{
services.TryAddSingleton(new IdentityServerAuthenticationOptions
{
Authority = Configuration.IdentityServerAuthority(),
ScopeName = "api1",
ScopeSecret = "secret",
//...,
});
}
public void Configure(IApplicationBuilder app)
{
var options = app.ApplicationServices.GetService<IdentityServerAuthenticationOptions>()
app.UseIdentityServerAuthentication(options);
//...
}
This allows you to register the IdentityServerAuthenticationOptions object in your tests without having to alter the code in the Api project.
I understand there is a need for a more complete answer than what #james-fera posted. I have learned from his answer and made a github project consisting of a test project and API project. The code should be self-explanatory and not hard to understand.
https://github.com/emedbo/identityserver-test-template
The IdentityServerSetup.cs class https://github.com/emedbo/identityserver-test-template/blob/master/tests/API.Tests/Config/IdentityServerSetup.cs can be abstracted away e.g. NuGetted away, leaving the base class IntegrationTestBase.cs
The essences is that can make the test IdentityServer work just like a normal IdentityServer, with users, clients, scopes, passwords etc. I have made the DELETE method [Authorize(Role="admin)] to prove this.
Instead of posting code here, I recommend read #james-fera's post to get the basics then pull my project and run tests.
IdentityServer is such a great tool, and with the ability to use the TestServer framework it gets even better.
I think you probably need to make a test double fake for your authorization middleware depending on how much functionality you want. So basically you want a middleware that does everything that the Authorization middleware does minus the back channel call to the discovery doc.
IdentityServer4.AccessTokenValidation is a wrapper around two middlewares. The JwtBearerAuthentication middleware, and the OAuth2IntrospectionAuthentication middleware. Both of these grab the discovery document over http to use for token validation. Which is a problem if you want to do an in-memory self-contained test.
If you want to go through the trouble you will probably need to make a fake version of app.UseIdentityServerAuthentication that doesnt do the external call that fetches the discovery document. It only populates the HttpContext principal so that your [Authorize] policies can be tested.
Check out how the meat of IdentityServer4.AccessTokenValidation looks here. And follow up with a look at how JwtBearer Middleware looks here
We stepped away from trying to host a mock IdentityServer and used dummy/mock authorizers as suggested by others here.
Here's how we did that in case it's useful:
Created a function which takes a type, creates a test Authentication Middleware and adds it to the DI engine using ConfigureTestServices (so that it's called after the call to Startup.)
internal HttpClient GetImpersonatedClient<T>() where T : AuthenticationHandler<AuthenticationSchemeOptions>
{
var _apiFactory = new WebApplicationFactory<Startup>();
var client = _apiFactory
.WithWebHostBuilder(builder =>
{
builder.ConfigureTestServices(services =>
{
services.AddAuthentication("Test")
.AddScheme<AuthenticationSchemeOptions, T>("Test", options => { });
});
})
.CreateClient(new WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false,
});
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Test");
return client;
}
Then we create what we called 'Impersonators' (AuthenticationHandlers) with the desired roles to mimic users with roles (We actually used this as a base class, and create derived classes based on this to mock different users):
public abstract class FreeUserImpersonator : AuthenticationHandler<AuthenticationSchemeOptions>
{
public Impersonator(
IOptionsMonitor<AuthenticationSchemeOptions> options,
ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
{
base.claims.Add(new Claim(ClaimTypes.Role, "FreeUser"));
}
protected List<Claim> claims = new List<Claim>();
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
var identity = new ClaimsIdentity(claims, "Test");
var principal = new ClaimsPrincipal(identity);
var ticket = new AuthenticationTicket(principal, "Test");
var result = AuthenticateResult.Success(ticket);
return Task.FromResult(result);
}
}
Finally, we can perform our integration tests as follows:
// Arrange
HttpClient client = GetImpersonatedClient<FreeUserImpersonator>();
// Act
var response = await client.GetAsync("api/things");
// Assert
Assert.That.IsSuccessful(response);
Test API startup:
public class Startup
{
public static HttpMessageHandler BackChannelHandler { get; set; }
public void Configuration(IAppBuilder app)
{
//accept access tokens from identityserver and require a scope of 'Test'
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = "https://localhost",
BackchannelHttpHandler = BackChannelHandler,
...
});
...
}
}
Assigning the AuthServer.Handler to TestApi BackChannelHandler in my unit test project:
protected TestServer AuthServer { get; set; }
protected TestServer MockApiServer { get; set; }
protected TestServer TestApiServer { get; set; }
[OneTimeSetUp]
public void Setup()
{
...
AuthServer = TestServer.Create<AuthenticationServer.Startup>();
TestApi.Startup.BackChannelHandler = AuthServer.CreateHandler();
TestApiServer = TestServer.Create<TestApi.Startup>();
}
The trick is to create a handler using the TestServer that is configured to use IdentityServer4. Samples can be found here.
I created a nuget-package available to install and test using the Microsoft.AspNetCore.Mvc.Testing library and the latest version of IdentityServer4 for this purpose.
It encapsulates all the infrastructure code necessary to build an appropriate WebHostBuilder which is then used to create a TestServer by generating the HttpMessageHandler for the HttpClient used internally.
None of the other answers worked for me because they rely on 1) a static field to hold your HttpHandler and 2) the Startup class to have knowledge that it may be given a test handler. I've found the following to work, which I think is a lot cleaner.
First create an object that you can instantiate before your TestHost is created. This is because you won't have the HttpHandler until after the TestHost is created, so you need to use a wrapper.
public class TestHttpMessageHandler : DelegatingHandler
{
private ILogger _logger;
public TestHttpMessageHandler(ILogger logger)
{
_logger = logger;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
_logger.Information($"Sending HTTP message using TestHttpMessageHandler. Uri: '{request.RequestUri.ToString()}'");
if (WrappedMessageHandler == null) throw new Exception("You must set WrappedMessageHandler before TestHttpMessageHandler can be used.");
var method = typeof(HttpMessageHandler).GetMethod("SendAsync", BindingFlags.Instance | BindingFlags.NonPublic);
var result = method.Invoke(this.WrappedMessageHandler, new object[] { request, cancellationToken });
return await (Task<HttpResponseMessage>)result;
}
public HttpMessageHandler WrappedMessageHandler { get; set; }
}
Then
var testMessageHandler = new TestHttpMessageHandler(logger);
var webHostBuilder = new WebHostBuilder()
...
services.PostConfigureAll<JwtBearerOptions>(options =>
{
options.Audience = "http://localhost";
options.Authority = "http://localhost";
options.BackchannelHttpHandler = testMessageHandler;
});
...
var server = new TestServer(webHostBuilder);
var innerHttpMessageHandler = server.CreateHandler();
testMessageHandler.WrappedMessageHandler = innerHttpMessageHandler;

Register Specific Module Constructor

I would like to inject different strings into each of my module's contructors. I register a factory method which constructs the module. I can then call container.Resolve<T>() and all is well. For some reason though when Nancy tries to resolve my module it throws the error
Nancy.TinyIoc.TinyIoCResolutionException: Unable to resolve type:
Plugin.HomeModule ---> Nancy.TinyIoc.TinyIoCResolutionException:
Unable to resolve type: System.String
public class HomeModule : NancyModule
{
public HomeModule(string text)
{
}
}
protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
base.ConfigureApplicationContainer(container);
container.Register<HomeModule>((ctr, param) => { return new HomeModule("text"); });
HomeModule module = container.Resolve<HomeModule>();
}
I have also tried doing the registration in ConfigureRequestContainer() with the same results. I have tried container.Register<HomeModule>(new HomeModule("some text")); as well as AsSingleton(). I can register an implementation to the string type with container.Register<string>("text"), but this would inject the same string into all modules.
How can I register a module constructor so that Nancy can resolve it?
Modules are obtained through the INancyModuleCatalog, which is normally implemented by the bootstrapper, you'd have to create a custom variation of that - if you're using the default bootstrapper then this is the current implementation:
https://github.com/NancyFx/Nancy/blob/master/src/Nancy/DefaultNancyBootstrapper.cs#L205
The best approach for this would be to not pass in a primitive into your module, but us something richer, or perhaps a factory. The container can resolve those dependencies. Passing a plain string into the module is a sign of a problem somewhere else and a hint that your architecture probably needs rethinking
I have implemented a custom catalog that registeres only Modules of a specific namespace, but I don't know where to register this.
public CustomModuleCatalog()
{
// The license type is read from db in Global.ascx.
// So I want to register a module based on a namespace.
// The namespace is the same like the license name.
if(WebApiApplication.LicenseType == LicenseType.RouteOne)
{
var assemblyTypes = Assembly.GetExecutingAssembly().GetTypes();
var modules = assemblyTypes.Where(t => t.Namespace != null && t.Namespace.EndsWith("MyCustomNamespace"));
var nancy = modules.Where(t => t.IsAssignableFrom(typeof(INancyModule)));
foreach (var type in nancy)
{
var nancyType = (INancyModule)type;
_modules.Add(type, (INancyModule)Activator.CreateInstance(type));
}
}
}
public IEnumerable<INancyModule> GetAllModules(NancyContext context)
{
return _modules?.Values;
}
public INancyModule GetModule(Type moduleType, NancyContext context)
{
if (_modules != null && _modules.ContainsKey(moduleType))
{
return _modules[moduleType];
}
return null;
}

Resources