I have integrated the singalr in administration microservice.
private hubConnection: signalR.HubConnection
public startConnection = () => {
this.hubConnection = new signalR.HubConnectionBuilder()
.withUrl('https://localhost:44367/signalr-hubs/change-detection')
.build();
console.log(this.hubConnection, 'hub connection');
this.hubConnection
.start()
.then(() => console.log('Connection started'))
.catch(err => console.log('Error while starting connection: ' + err));
this.hubConnection.on('BroadcastMessage', (data) => {
console.log(data);
});
}
constructor(){
this.startConnection();
}
I have put the above code in the appcomponent.ts file. The above code is working fine and when I send the signal from the administration microservice, I receive the message on "BroadcastMessage". I have used the administration service URL "https://localhost:44367".
Now I don't want to use the administration service URL, I want to use the gateway URL https://localhost:44325 so I configured the ocelot.json file as below.
{
"ServiceKey": "Administration Service",
"DownstreamPathTemplate": "/signalr-hubs/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44367
}
],
"UpstreamPathTemplate": "/signalr-hubs/{everything}",
"UpstreamHttpMethod": [ "Put", "Delete", "Get", "Post" ]
},
{
"DownstreamPathTemplate": "/ws",
"UpstreamPathTemplate": "/",
"DownstreamScheme": "ws",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 44367
}
]
}
When I use the above code, I am getting the below error in console.
[2023-01-17T11:47:29.510Z] Information: WebSocket connected to wss://localhost:44325/signalr-hubs/change-detection?id=Oiwz6joKZs_dxyeYKdUsHg.
Utils.js:141 [2023-01-17T11:47:29.513Z] Error: Connection disconnected with error 'Error: Server returned handshake error: Handshake was canceled.'.
log @ Utils.js:141
_stopConnection @ HttpConnection.js:396
transport.onclose @ HttpConnection.js:334
_close @ WebSocketTransport.js:144
webSocket.onmessage @ WebSocketTransport.js:84
wrapFn @ zone.js:766
invokeTask @ zone.js:406
onInvokeTask @ core.mjs:26218
invokeTask @ zone.js:405
runTask @ zone.js:178
invokeTask @ zone.js:487
invokeTask @ zone.js:1661
globalCallback @ zone.js:1692
globalZoneAwareCallback @ zone.js:1725
Show 14 more frames
app.component.ts:22 Error while starting connection: Error: Server returned handshake error: Handshake was canceled.
If I integrated the singalr into the web gateway then I am getting the ocelot configuration not found error.
This is the administration service log
[administration-service_786370b9-c]: [17:17:09 INF] Request starting HTTP/1.1 POST https://localhost:44367/signalr-hubs/change-detection/negotiate?negotiateVersion=1 - 0
[administration-service_786370b9-c]: [17:17:09 INF] CORS policy execution successful.
[administration-service_786370b9-c]: [17:17:09 INF] Executing endpoint '/signalr-hubs/change-detection/negotiate'
[administration-service_786370b9-c]: [17:17:09 INF] Executed endpoint '/signalr-hubs/change-detection/negotiate'
[administration-service_786370b9-c]: [17:17:09 INF] Request finished HTTP/1.1 POST https://localhost:44367/signalr-hubs/change-detection/negotiate?negotiateVersion=1 - 0 - 200 316 application/json 1.8707ms
[administration-service_786370b9-c]: [17:17:09 INF] Request starting HTTP/1.1 GET https://localhost:44367/signalr-hubs/change-detection?id=Oiwz6joKZs_dxyeYKdUsHg - 0
[administration-service_786370b9-c]: [17:17:09 INF] CORS policy execution successful.
[administration-service_786370b9-c]: [17:17:09 INF] Executing endpoint '/signalr-hubs/change-detection'
[administration-service_786370b9-c]: [17:17:29 INF] Executed endpoint '/signalr-hubs/change-detection'
[administration-service_786370b9-c]: [17:17:29 INF] Request finished HTTP/1.1 GET https://localhost:44367/signalr-hubs/change-detection?id=Oiwz6joKZs_dxyeYKdUsHg - 0 - 101 - - 20029.8655ms
This is the web gateway log:
[web-gateway_8b434f23-f]: [17:17:29 DBG] requestId: 0HMNOG1S5794U:00000002, previousRequestId: no previous request id, message: ocelot pipeline finished
[web-gateway_8b434f23-f]: [17:17:29 INF] Request finished HTTP/1.1 GET https://localhost:44325/signalr-hubs/change-detection?id=Oiwz6joKZs_dxyeYKdUsHg - - - 101 42 - 20035.4048ms
I am getting below error when build the project from Azure pipeline.
error NU1101: Unable to find package Volo.Abp.Account.Pro.Public.Web.OpenIddict. No packages exist with this id in source(s): ABP Commercial NuGet Source, nuget.org [/src/ChurchPharmacy.sln]
error NU1101: Unable to find package Volo.Abp.Account.Pro.Public.HttpApi. No packages exist with this id in source(s): ABP Commercial NuGet Source, nuget.org [/src/ChurchPharmacy.sln]
error NU1101: Unable to find package Volo.Abp.Account.Pro.Public.Application. No packages exist with this id in source(s): ABP Commercial NuGet Source, nuget.org [/src/ChurchPharmacy.sln]
error NU1101: Unable to find package Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonX. No packages exist with this id in source(s): ABP Commercial NuGet Source, nuget.org [/src/ChurchPharmacy.sln]
Failed to restore /src/apps/auth-server/src/ChurchPharmacy.AuthServer/ChurchPharmacy.AuthServer.csproj (in 27.05 sec).
https://github.com/abpframework/abp-samples/tree/master/ConcurrentLogin
But this sample is integrated with the identity server 4 and the microservice template has OpenID configuration.
I want to integrate the concurrent login feature. I downloaded the sample code from GitHub. I have a microservice template. What is the best practice to integrate the concurrent login feature, with Auth Server or Identity service or any other way?
I have microservice architecture. I have configured the blog provider in the administration microservice. I have a multi-tenancy configuration as well. I want to use different azure connection strings based on tenant configuration. I want to give the setting for the blob storage provider and the tenant can change the setting. I also want to give choices to tenants either they can use azure storage or aws storage. So basically I want blob configuration based on the settings of the tenant.
I am trying to integrate concurrent login in the Identity service but the problem is I have version 6.0rc.5 with OpenIdDict integration and the concurrent login sample version is 6.0rc.2 with Identity server 4 integration.
I am struggling to replace the below file to convert into OpenIdDict.
using System;
using System.Threading.Tasks;
using IdentityServer4.AspNetIdentity;
using IdentityServer4.Validation;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Identity;
using Volo.Abp.IdentityServer.AspNetIdentity;
using Volo.Abp.IdentityServer.Localization;
using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace ChurchPharmacy.IdentityService.AspNetIdentity;
public class ConcurrentLoginResourceOwnerPasswordValidator : AbpResourceOwnerPasswordValidator
{
public ConcurrentLoginResourceOwnerPasswordValidator(
Microsoft.AspNetCore.Identity.UserManager<IdentityUser> userManager,
Microsoft.AspNetCore.Identity.SignInManager<IdentityUser> signInManager,
IdentitySecurityLogManager identitySecurityLogManager,
ILogger<ResourceOwnerPasswordValidator<IdentityUser>> logger,
IStringLocalizer<AbpIdentityServerResource> localizer, IOptions<AbpIdentityOptions> abpIdentityOptions,
IHybridServiceScopeFactory serviceScopeFactory, IOptions<IdentityOptions> identityOptions) : base(userManager,
signInManager, identitySecurityLogManager, logger, localizer, abpIdentityOptions, serviceScopeFactory,
identityOptions)
{
}
protected override async Task SetSuccessResultAsync(ResourceOwnerPasswordValidationContext context, IdentityUser user)
{
user.SetProperty(ConcurrentLoginConsts.ConcurrentLoginToken, Guid.NewGuid().ToString("N"));
await UserManager.UpdateAsync(user);
await base.SetSuccessResultAsync(context, user);
}
}
I have microservice architecture and I want to integrate concurrent modules as a plugin.
I have downloaded the sample concurrent login module and built the project and put the dls in a folder.
I have registered this module as a plugin in the web gateway configuration.
context.Services.AddApplication<ChurchPharmacyWebGatewayModule>(options =>
{
options.PlugInSources.AddFolder(@"D:\abp\abp6\ChurchPharmacy\plugins", System.IO.SearchOption.AllDirectories);
});
When I run the project I am getting the below error in the web gateway.
I read the documentation on background jobs and worker processes but I have a requirement to schedule the task to run on a specific date and time. I don't want to use the worker process which will run on every seconds or minutes to check the schedular and execute the task.
Suppose, I have a task to change the product price at midnight or a specific date and time so I can schedule the new product price and that job should trigger exact the date and time and change the product price.
I fixed the issue. I registered a domain resolver on the gateway level. I removed from gateway and registered in administration microservice level.
I have created my custom domain tenant resolver class. I have the below configuration in a microservice architecture. I am using the 6.0 preview version.
Angular Host Domain: abp.mydomain.com Gateway domain: abpapi.mydomain.com AuthServer domain: abpauth.mydomain.com
Tenant domain: tenant.mydomain.com The gateway and auth server are the same as above.
Configure<AbpTenantResolveOptions>(options =>
{
options.TenantResolvers.Clear();
options.TenantResolvers.Add(new TenantDomainResolver("{0}.mydomain.com"));
});
Tenant Domain Resolver
public class TenantDomainResolver: TenantResolveContributorBase
{
public const string ContributorName = "Custom";
public override string Name => ContributorName;
private static readonly string[] ProtocolPrefixes = { "http://", "https://" };
private readonly string _domainFormat;
public TenantDomainResolver(string domainFormat)
{
_domainFormat = domainFormat;
}
public override async Task ResolveAsync(ITenantResolveContext context)
{
var httpContext = context.GetHttpContext();
var referer = httpContext.Request.Headers["Referer"].ToString();
if (string.IsNullOrEmpty(referer))
{
return;
}
referer = referer.RemovePreFix(ProtocolPrefixes);
var extractResult = FormattedStringValueExtracter.Extract(referer, _domainFormat, ignoreCase: true);
if (extractResult != null && extractResult.IsMatch)
{
if (extractResult.Matches[0].Value != "abp") // if referer is not host domain
{
context.Handled = true;
context.TenantIdOrName = extractResult.Matches[0].Value;
}
}
}
It's working fine as the host domain 'abp.mydomain.com' from the angular application but when I browse by the 'tenant.mydomain.com' angular application, its calls API 'https://abpapi.mydomain.com/api/abp/multi-tenancy/tenants/by-name/tenant' and throwing an exception as below.
There is no tenant with the tenant id or name: tenant
but when I copy the endpoint URL and directly call in the browser, it's showing the tenant data.
{"success":true,"tenantId":"40cd013e-dfb4-e3e7-e205-3a0653710d75","name":"tenant","isActive":true}
These are the logs of web gateway.
2022-09-16 18:24:23.492 +05:30 [INF] Application started. Press Ctrl+C to shut down.
2022-09-16 18:24:23.492 +05:30 [INF] Hosting environment: Production
2022-09-16 18:24:23.492 +05:30 [INF] Content root path: D:\abp\abp6\publish\web
2022-09-16 18:24:23.516 +05:30 [INF] Request starting HTTP/2 OPTIONS https://abpapi.mydomain.com/api/abp/multi-tenancy/tenants/by-name/tenant - -
2022-09-16 18:24:23.530 +05:30 [INF] CORS policy execution successful.
2022-09-16 18:24:23.541 +05:30 [INF] Request starting HTTP/2 GET https://abpapi.mydomain.com/api/abp/multi-tenancy/tenants/by-name/tenant - -
2022-09-16 18:24:23.542 +05:30 [INF] CORS policy execution successful.
2022-09-16 18:24:23.547 +05:30 [INF] Request finished HTTP/2 OPTIONS https://abpapi.mydomain.com/api/abp/multi-tenancy/tenants/by-name/tenant - - - 204 - - 31.0747ms
2022-09-16 18:24:23.573 +05:30 [INF] Request finished HTTP/2 GET https://abpapi.mydomain.com/api/abp/multi-tenancy/tenants/by-name/tenant - - - 500 - text/html 31.7616ms