Ok I found out that I had different versions for ABP Libraries and ABP Suite.
ABP Libraries were on 5.1.4 and ABP Suite was on version 5.1.3. Updating ABP Suite to 5.1.4 fixed the problem.
Thanks for the AutoMapper code, yes this change was necessary for the Blazor app to work properly.
3rd Party clients such as android are out of the box right now. I can't suggest the best way to use with ABP together but, I can recommend using ngrok for testing at development time.
It seems your last exception occurs at https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/ClientProxying/ClientProxyBase.cs#L36
So, it shows LazyServiceProvider is null. Most probably Autofac couldn't be configured properly.
Thanks for pointing us in the right direction of the issue.
We found and solved our problem regarding Autofac:
var application = AbpApplicationFactory.Create<Module>(options =>
{
options.UseAutofac(); // This line was missing.
});
application.Initialize();
return application;
We thought including the Autofac module in the DependsOn attribute would automatically add and use Autofac. But this seems not to be the case.
We also tried the following code in the module:
public override void PreConfigureServices(ServiceConfigurationContext context)
{
context.Services.PreConfigure<AbpHttpClientBuilderOptions>(options =>
{
options.ProxyClientBuildActions.Add((s, b) =>
{
b.ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
{
ClientCertificateOptions = ClientCertificateOption.Manual,
ServerCertificateCustomValidationCallback = (x, x1, x2, x3) => true,
});
});
});
}
The ServerCertificateCustomValidationCallback is called, but we then receive the following exception:
System.NullReferenceException: Object reference not set to an instance of an object.
at Volo.Abp.Http.Client.ClientProxying.ClientProxyBase`1[TService].get_ClientOptions () [0x00000] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Http.Client\Volo\Abp\Http\Client\ClientProxying\ClientProxyBase.cs:36
at Volo.Abp.Http.Client.ClientProxying.ClientProxyBase`1[TService].RequestAsync (Volo.Abp.Http.Client.ClientProxying.ClientProxyRequestContext requestContext) [0x00030] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Http.Client\Volo\Abp\Http\Client\ClientProxying\ClientProxyBase.cs:108
at Volo.Abp.Http.Client.ClientProxying.ClientProxyBase`1[TService].RequestAsync[T] (Volo.Abp.Http.Client.ClientProxying.ClientProxyRequestContext requestContext) [0x0003d] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Http.Client\Volo\Abp\Http\Client\ClientProxying\ClientProxyBase.cs:76
at Volo.Abp.Http.Client.DynamicProxying.DynamicHttpProxyInterceptorClientProxy`1[TService].CallRequestAsync[T] (Volo.Abp.Http.Client.ClientProxying.ClientProxyRequestContext requestContext) [0x0002d] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Http.Client\Volo\Abp\Http\Client\DynamicProxying\DynamicHttpProxyInterceptorClientProxy.cs:11
at Volo.Abp.Http.Client.DynamicProxying.DynamicHttpProxyInterceptor`1[TService].CallRequestAsync[T] (Volo.Abp.Http.Client.ClientProxying.ClientProxyRequestContext context) [0x00032] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Http.Client\Volo\Abp\Http\Client\DynamicProxying\DynamicHttpProxyInterceptor.cs:92
at Volo.Abp.Http.Client.DynamicProxying.DynamicHttpProxyInterceptor`1[TService].GetResultAsync (System.Threading.Tasks.Task task, System.Type resultType) [0x0001f] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Http.Client\Volo\Abp\Http\Client\DynamicProxying\DynamicHttpProxyInterceptor.cs:97
at Volo.Abp.Http.Client.DynamicProxying.DynamicHttpProxyInterceptor`1[TService].InterceptAsync (Volo.Abp.DynamicProxy.IAbpMethodInvocation invocation) [0x001a2] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Http.Client\Volo\Abp\Http\Client\DynamicProxying\DynamicHttpProxyInterceptor.cs:71
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1[TInterceptor].InterceptAsync[TResult] (Castle.DynamicProxy.IInvocation invocation, Castle.DynamicProxy.IInvocationProceedInfo proceedInfo, System.Func`3[T1,T2,TResult] proceed) [0x00059] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Castle.Core\Volo\Abp\Castle\DynamicProxy\CastleAsyncAbpInterceptorAdapter.cs:29
at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult] (Castle.DynamicProxy.IInvocation invocation, Castle.DynamicProxy.IInvocationProceedInfo proceedInfo) [0x00079] in <25225aa189ef4d0091cfe671f9159d35>:0
at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1[TResult].ProceedAsync () [0x00038] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Castle.Core\Volo\Abp\Castle\DynamicProxy\CastleAbpMethodInvocationAdapterWithReturnValue.cs:24
at Volo.Abp.Validation.ValidationInterceptor.InterceptAsync (Volo.Abp.DynamicProxy.IAbpMethodInvocation invocation) [0x0009c] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Validation\Volo\Abp\Validation\ValidationInterceptor.cs:19
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1[TInterceptor].InterceptAsync[TResult] (Castle.DynamicProxy.IInvocation invocation, Castle.DynamicProxy.IInvocationProceedInfo proceedInfo, System.Func`3[T1,T2,TResult] proceed) [0x00059] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Castle.Core\Volo\Abp\Castle\DynamicProxy\CastleAsyncAbpInterceptorAdapter.cs:29
at Conzepta.Lotus.Mobile.Client.Features.Scanner.Controller.FinishedNavigationAsync (System.Object[] parameters) [0x001bd] in D:\.net\Conzepta.Lotus.Mobile.Client\Conzepta.Lotus.Mobile.Client\Features\Scanner\Controller.cs:51 }
Is there maybe a way to override the DefaultDynamicProxyHttpClientFactory factory and return our own HttpClient? We already got the connection working with our own HttpClient.
I added the network_security_config.xml file like this:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">192.168.0.103</domain>
</domain-config>
</network-security-config>
And added android:networkSecurityConfig="@xml/network_security_config" to the application in the AndroidManifest.xml, but I still the the SSL exception.
I also tried setting the ServicePointManager.ServerCertificateValidationCallback to (x1, x2, x3, x4) => true, but does not help I still get the same SSL exception.
I also tried adding android:usesCleartextTraffic="true" to the application in the AndroidManifest.xml.
And I tried to change the HttpClient implementation in the Android project, but still get the SSL exception.
Can you check api gateway ocelot configuration? Change
DownstreamScheme
of your product routing to http if you are hosting product service on http.
Good idea, I added the change, but we still get the same SSL exception. Gateway logs are empty, so the client application does not even reach the gateway.
This is the appsettings file for web-gateway:
{
"DownstreamPathTemplate": "/api/product-service/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44361
}
],
"UpstreamPathTemplate": "/api/product-service/{everything}",
"UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
}
Your client (Xamarin-Forms) trying to make a request to Api Resource (IProductAppService) which is Http.Api.Host (.Net Core application) project. You are getting SSL error because Api Resource (.Net Core app) only allows https.
So you need set Api Resource to allow http also as the configuration above.
Thanks for the clarification. Currently we access the API Resources through the web-gateway gateway.
This is our appsettings file in the API Resource project ProductService.HttpApi.Host:
"AuthServer": {
"Authority": "https://localhost:44322",
"RequireHttpsMetadata": "false"
},
We also added this to the appsettings file for the web-gateway gateway:
"AuthServer": {
"Authority": "https://localhost:44322",
"RequireHttpsMetadata": "false",
"SwaggerClientId": "WebGateway_Swagger",
"SwaggerClientSecret": "1q2w3e*"
},
On the Xamarin-Forms client we have this module:
public class Module : AbpModule
{
public static string AccessToken { get; set; } // This is set when the browser returns the access token.
public override void ConfigureServices(ServiceConfigurationContext context)
{
var services = context.Services;
services.Configure<AbpHttpClientBuilderOptions>(options =>
{
options.ProxyClientActions.Add((name, p, c) =>
{
c.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
});
});
services.Configure<AbpRemoteServiceOptions>(options =>
{
options.RemoteServices.Default = new RemoteServiceConfiguration(Constants.BaseUrl); // URL of the Web-Gateway
});
services.AddHttpClientProxies(typeof(ProductServiceApplicationContractsModule).Assembly);
}
}
Then we resolve for the IProductAppService in the Xamarin-Forms project and try to call the GetListAsync method:
try
{
var t = await _productAppService.GetListAsync(new GetProductsInput());
}
catch (Exception ex)
{
}
We get this exception:
"The SSL connection could not be established, see inner exception."
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore (System.IO.Stream stream, System.Net.Security.SslClientAuthenticationOptions sslOptions, System.Threading.CancellationToken cancellationToken) [0x000f6] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/ConnectHelper.cs:176
at System.Threading.Tasks.ValueTask`1[TResult].get_Result () [0x0001b] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/Common/src/CoreLib/System/Threading/Tasks/ValueTask.cs:813
at System.Net.Http.HttpConnectionPool.CreateConnectionAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) [0x002d8] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs:408
at System.Threading.Tasks.ValueTask`1[TResult].get_Result () [0x0001b] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/Common/src/CoreLib/System/Threading/Tasks/ValueTask.cs:813
at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync (System.Threading.Tasks.ValueTask`1[TResult] creationTask) [0x000a2] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs:543
at System.Threading.Tasks.ValueTask`1[TResult].get_Result () [0x0001b] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/Common/src/CoreLib/System/Threading/Tasks/ValueTask.cs:813
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync (System.Net.Http.HttpRequestMessage request, System.Boolean doRequestAuth, System.Threading.CancellationToken cancellationToken) [0x0003f] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPool.cs:284
at System.Net.Http.RedirectHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) [0x00070] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/RedirectHandler.cs:32
at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) [0x000d7] in <831b7afb4f024d399aa7f21c2ef99b9c>:0
at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) [0x000ef] in <831b7afb4f024d399aa7f21c2ef99b9c>:0
at System.Net.Http.HttpClient.FinishSendAsyncBuffered (System.Threading.Tasks.Task`1[TResult] sendTask, System.Net.Http.HttpRequestMessage request, System.Threading.CancellationTokenSource cts, System.Boolean disposeCts) [0x0017e] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/HttpClient.cs:506
at Volo.Abp.Http.Client.DynamicProxying.ApiDescriptionFinder.GetApiDescriptionFromServerAsync (System.Net.Http.HttpClient client, System.String baseUrl) [0x0006d] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Http.Client\Volo\Abp\Http\Client\DynamicProxying\ApiDescriptionFinder.cs:109
at Volo.Abp.Http.Client.DynamicProxying.ApiDescriptionCache.GetAsync (System.String baseUrl, System.Func`1[TResult] factory) [0x000eb] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Http.Client\Volo\Abp\Http\Client\DynamicProxying\ApiDescriptionCache.cs:34
at Volo.Abp.Http.Client.DynamicProxying.ApiDescriptionFinder.GetApiDescriptionAsync (System.Net.Http.HttpClient client, System.String baseUrl) [0x0006c] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Http.Client\Volo\Abp\Http\Client\DynamicProxying\ApiDescriptionFinder.cs:90
at Volo.Abp.Http.Client.DynamicProxying.ApiDescriptionFinder.FindActionAsync (System.Net.Http.HttpClient client, System.String baseUrl, System.Type serviceType, System.Reflection.MethodInfo method) [0x00034] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Http.Client\Volo\Abp\Http\Client\DynamicProxying\ApiDescriptionFinder.cs:46
at Volo.Abp.Http.Client.DynamicProxying.DynamicHttpProxyInterceptor`1[TService].GetActionApiDescriptionModel (Volo.Abp.DynamicProxy.IAbpMethodInvocation invocation) [0x0012d] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Http.Client\Volo\Abp\Http\Client\DynamicProxying\DynamicHttpProxyInterceptor.cs:82
at Volo.Abp.Http.Client.DynamicProxying.DynamicHttpProxyInterceptor`1[TService].InterceptAsync (Volo.Abp.DynamicProxy.IAbpMethodInvocation invocation) [0x0003c] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Http.Client\Volo\Abp\Http\Client\DynamicProxying\DynamicHttpProxyInterceptor.cs:55
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1[TInterceptor].InterceptAsync[TResult] (Castle.DynamicProxy.IInvocation invocation, Castle.DynamicProxy.IInvocationProceedInfo proceedInfo, System.Func`3[T1,T2,TResult] proceed) [0x00059] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Castle.Core\Volo\Abp\Castle\DynamicProxy\CastleAsyncAbpInterceptorAdapter.cs:29
at Castle.DynamicProxy.AsyncInterceptorBase.ProceedAsynchronous[TResult] (Castle.DynamicProxy.IInvocation invocation, Castle.DynamicProxy.IInvocationProceedInfo proceedInfo) [0x00079] in <25225aa189ef4d0091cfe671f9159d35>:0
at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapterWithReturnValue`1[TResult].ProceedAsync () [0x00038] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Castle.Core\Volo\Abp\Castle\DynamicProxy\CastleAbpMethodInvocationAdapterWithReturnValue.cs:24
at Volo.Abp.Validation.ValidationInterceptor.InterceptAsync (Volo.Abp.DynamicProxy.IAbpMethodInvocation invocation) [0x0009c] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Validation\Volo\Abp\Validation\ValidationInterceptor.cs:19
at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter`1[TInterceptor].InterceptAsync[TResult] (Castle.DynamicProxy.IInvocation invocation, Castle.DynamicProxy.IInvocationProceedInfo proceedInfo, System.Func`3[T1,T2,TResult] proceed) [0x00059] in D:\ci\Jenkins\workspace\abp-commercial-release\abp\framework\src\Volo.Abp.Castle.Core\Volo\Abp\Castle\DynamicProxy\CastleAsyncAbpInterceptorAdapter.cs:29
The configuration did not change the SSL validation. We think the local HTTP client rejects the connection, because the web-gateway does not output any logs when trying to connect.
You can disable the SSL from API resource appsettings you are trying to make request to:
"AuthServer": { "Authority": "https://idsrvHost", "RequireHttpsMetadata": "false", // -> true by default },
This again seems to be for an ASP-NET Core application (appsettings.json). How does this work on Xamarin-Forms? Can I configure the "RequireHttpsMetadata" programmatically, instead from a configuration file?
There is also a community post from one of the community members: Consume ABP API from Xamarin App. Maybe it can help.
I read the tutorial you posted. Essentially the authentication call is made directly in the app via the HttpClient and then the access token is stored locally. But the access token is never used in combination with the dynamic HTTP proxies. How do I get the HTTP client proxies to use an access token I retrieved from the OIDC client and disable SSL for testing purposes?
services.AddHttpClientProxies(typeof(ProductServiceApplicationContractsModule).Assembly);
Thanks for the quick answer.
But the configuration section you posted is for the "Synchronous Communication between Microservices". However, I have an Xamarin-Forms application that is running on the users phone. In our workflow the app opens the browser for the user to perform the authentication (auth-server). The app then retrieves an access token. This is already working as expected so no problems here.
The ABP module I posted is running on the Xamarin-Forms application on the user side, because we would like to use the app services (e.g. IProductAppService) directly in the app. Is this possible? Or is it not supposed to be used on the client side like that. The mobile app should access the API gateway with this access token.
Thanks for the help.