hi
You just need to replace the default mailing service, it's that simple.
Ok Means this is not out of box functionality. I think you guys may need to think to have a optional configuration for SendGrid Integration.
To inject IWorkflowInvoker in Application, which module dependencies need to be added in which modules in sample project. Could you try with the sample project and guide us.
Dear Maliming
We emailed the Sample project to malimings@gmail.com
We can inject IWorkflowInvoker in web project and it is working. whenever trying to inject in Application project, We are getting ActivatorChain error.
We emailed the log file to liming.ma@volosoft.com
We are able to inject IWorkflowInvoker in web project and it is working. whenever trying to inject in AppService/Controller, We are getting ActivatorChain error.
Based on our custom requirement we had to include the custom page and controller with in Web application(MVC) and those controller/page can't be placed in any of the micro services or in web gateway.
Then, where are you hosting these pages?
This will be part of our Web Layer (UI) layer and will be hosted along with that
We don't want to have anonymous access for those controller/page. So we would like to know what are the parameters (Cookies/Headers) need to be passed to the respective page to access those as a Authenticated user. Please advise.....
I can't say that I understand what you mean.
Do you have a controller method returning a page with an [Authorize] attribute and you want to call this from an external service (like a .NET or Java application)?
There are authorization flows for these kinds of interactions. If you are making a request without a user (backend-to-backend) you need to configure a Client Credentials authentication. Or if it is related with user that needs to be logged in, you can use Authorization Code or Hybrid flow.
Eventually, behind the scenes, you request an access token and this is added to the authorization header as Bearer and the request is made.
Yes this stands valid if we would like to make a call to services , but in this case we want to call a page with in our UI layer by authenticating the request
We would like to understand the http request flow between Web(MVC UI) Layer and WebGateway.
From the microservice solution perspective, WebUI (I am assuming you mean public-web application) is not a layer but an application.
Can you please provide more details on communication between WebUI & WebGateway (for http requests) and relevant code which passes Barer token etc...
I think you want to learn generally how the proxying works; how an HTTP request is done, headers are set and forwarded; not just microservice specific. So I will try to explain better.
Your request is created by ClientProxyBase (or DynamicHttpProxyInterceptor if you are using dynamic proxying):
protected IRemoteServiceHttpClientAuthenticator ClientAuthenticator => LazyServiceProvider.LazyGetRequiredService<IRemoteServiceHttpClientAuthenticator>(); protected virtual async Task<HttpContent> RequestAsync(ClientProxyRequestContext requestContext) { ... // Gets the remote service configuration RemoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync(clientConfig.RemoteServiceName); // Creates the HttpClient service configuration var client = HttpClientFactory.Create(clientConfig.RemoteServiceName); ... // Authentication headers are forwarded or set in here based on remoteServiceConfig if (requestContext.Action.AllowAnonymous != true) { await ClientAuthenticator.Authenticate( new RemoteServiceHttpClientAuthenticateContext( client, requestMessage, remoteServiceConfig, clientConfig.RemoteServiceName ) ); } ... }
IRemoteServiceHttpClientAuthenticator is implemented by:
- IdentityModelRemoteServiceHttpClientAuthenticator under Volo.Abp.Http.Client.IdentityModel module:
await IdentityModelAuthenticationService.TryAuthenticateAsync( context.Client, context.RemoteService.GetIdentityClient() ?? context.RemoteServiceName );
Uses IdentityModelAuthenticationService to authenticate the service as below:
public async Task<bool> TryAuthenticateAsync( [NotNull] HttpClient client, string identityClientName = null) { var accessToken = await GetAccessTokenOrNullAsync(identityClientName); if (accessToken == null) { return false; } SetAccessToken(client, accessToken); return true; } protected virtual void SetAccessToken(HttpClient client, string accessToken) { //TODO: "Bearer" should be configurable client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); }
- HttpContextIdentityModelRemoteServiceHttpClientAuthenticator under Volo.Abp.Http.Client.IdentityModel.Web module that extends
IdentityModelRemoteServiceHttpClientAuthenticator
and handles authentication when HTTP context is available (For UI based applications like Razor/MVC):public override async Task Authenticate(RemoteServiceHttpClientAuthenticateContext context) { if (context.RemoteService.GetUseCurrentAccessToken() != false) { var accessToken = await GetAccessTokenFromHttpContextOrNullAsync(); if (accessToken != null) { context.Request.SetBearerToken(accessToken); return; } } await base.Authenticate(context); } protected virtual async Task<string> GetAccessTokenFromHttpContextOrNullAsync() { var httpContext = HttpContextAccessor?.HttpContext; if (httpContext == null) { return null; } return await httpContext.GetTokenAsync("access_token"); }
- There is also AccessTokenProviderIdentityModelRemoteServiceHttpClientAuthenticator under Volo.Abp.Http.Client.IdentityModel.WebAssembly module that extends
IdentityModelRemoteServiceHttpClientAuthenticator
and usesIAccessTokenProvider
for getting/setting authorization headers for blazor applications.Basically, how to set the authorization header is based on application type;
- Server-to-server communication without HTTP context uses
Volo.Abp.Http.Client.IdentityModel
module- MVC/Razor application uses
Volo.Abp.Http.Client.IdentityModel.Web
module- Blazor application uses
Volo.Abp.Http.Client.IdentityModel.WebAssembly
module
Thanks for the details, now we are able to over ride the specific method to add additional headers (in our sample solution) . Thanks for the support
After that work around, it worked fine. by the way the issue is because of PageResultDTO, when we are having that API definition with references is showing with List'[] and it violates Open API definition rules. So we had to restrict full path definitions in references.
The trick is to add below code
//options.CustomSchemaIds(type => type.FullName); (comment this)
options.UseAllOfToExtendReferenceSchemas(); (add this)
What error do you get when you use it in shared project?
We got below error when paring the swagger json file (definition)
Parsing error(s): The key 'Volo.Abp.Application.Dtos.ListResultDto1[[Volo.Abp.Account.LinkUserDto, Volo.Abp.Account.Pro.Public.Application.Contracts, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9\.\-_]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.ListResultDto
1[[Volo.Abp.Identity.IdentityRoleDto, Volo.Abp.Identity.Pro.Application.Contracts, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9.-]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.ListResultDto1[[Volo.Abp.Identity.OrganizationUnitWithDetailsDto, Volo.Abp.Identity.Pro.Application.Contracts, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9\.\-_]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.ListResultDto
1[[Volo.Abp.LanguageManagement.Dto.LanguageDto, Volo.Abp.LanguageManagement.Application.Contracts, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9.-]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.ListResultDto1[[Volo.Abp.Users.UserData, Volo.Abp.Users.Abstractions, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9\.\-_]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.PagedResultDto
1[[TestURI.Employees.EmployeeDto, TestURI.Application.Contracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9.-]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.PagedResultDto1[[Volo.Abp.AuditLogging.AuditLogDto, Volo.Abp.AuditLogging.Application.Contracts, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9\.\-_]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.PagedResultDto
1[[Volo.Abp.AuditLogging.EntityChangeDto, Volo.Abp.AuditLogging.Application.Contracts, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9.-]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.PagedResultDto1[[Volo.Abp.Identity.ClaimTypeDto, Volo.Abp.Identity.Pro.Application.Contracts, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9\.\-_]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.PagedResultDto
1[[Volo.Abp.Identity.IdentityRoleDto, Volo.Abp.Identity.Pro.Application.Contracts, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9.-]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.PagedResultDto1[[Volo.Abp.Identity.IdentitySecurityLogDto, Volo.Abp.Identity.Pro.Application.Contracts, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9\.\-_]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.PagedResultDto
1[[Volo.Abp.Identity.IdentityUserDto, Volo.Abp.Identity.Pro.Application.Contracts, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9.-]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.PagedResultDto1[[Volo.Abp.Identity.OrganizationUnitWithDetailsDto, Volo.Abp.Identity.Pro.Application.Contracts, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9\.\-_]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.PagedResultDto
1[[Volo.Abp.IdentityServer.ApiResource.Dtos.ApiResourceWithDetailsDto, Volo.Abp.IdentityServer.Application.Contracts, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9.-]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.PagedResultDto1[[Volo.Abp.IdentityServer.ApiScope.Dtos.ApiScopeWithDetailsDto, Volo.Abp.IdentityServer.Application.Contracts, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9\.\-_]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.PagedResultDto
1[[Volo.Abp.IdentityServer.Client.Dtos.ClientWithDetailsDto, Volo.Abp.IdentityServer.Application.Contracts, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9.-]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.PagedResultDto1[[Volo.Abp.IdentityServer.IdentityResource.Dtos.IdentityResourceWithDetailsDto, Volo.Abp.IdentityServer.Application.Contracts, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9\.\-_]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.PagedResultDto
1[[Volo.Abp.LanguageManagement.Dto.LanguageDto, Volo.Abp.LanguageManagement.Application.Contracts, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9.-]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.PagedResultDto1[[Volo.Abp.LanguageManagement.Dto.LanguageTextDto, Volo.Abp.LanguageManagement.Application.Contracts, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9\.\-_]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.PagedResultDto
1[[Volo.Abp.TextTemplateManagement.TextTemplates.TemplateDefinitionDto, Volo.Abp.TextTemplateManagement.Application.Contracts, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9.-]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.PagedResultDto1[[Volo.Saas.Host.Dtos.EditionDto, Volo.Saas.Host.Application.Contracts, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9\.\-_]+$'. [#/components] The key 'Volo.Abp.Application.Dtos.PagedResultDto
1[[Volo.Saas.Host.Dtos.SaasTenantDto, Volo.Saas.Host.Application.Contracts, Version=5.1.4.0, Culture=neutral, PublicKeyToken=null]]' in 'schemas' of components MUST match the regular expression '^[a-zA-Z0-9.-_]+$'. [#/components]
Parsing error(s): The input OpenAPI file is not valid for the OpenAPI specification https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md (schema https://github.com/OAI/OpenAPI-Specification/blob/master/schemas/v3.0/schema.yaml).
We handled this by adding below code
private static void ConfigureSwagger(ServiceConfigurationContext context, IConfiguration configuration)
{
context.Services.AddAbpSwaggerGenWithOAuth(
configuration["AuthServer:Authority"],
new Dictionary<string, string>
{
{"HeadersSample", "HeadersSample API"}
},
options =>
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = "HeadersSample API", Version = "v1" });
options.DocInclusionPredicate((docName, description) => true);
//options.CustomSchemaIds(type => type.FullName);
options.UseAllOfToExtendReferenceSchemas();
});
}
Volo.Abp.Http.Client.IdentityModel
Thanks for the detailed explanation, Yes this is what we expected. I am going through the details will let you know in case of any queries
You may want to check these framework modules:
Can you please validate our understanding which I mentioned in my Question Posting.