Hello, If it is OK, in the next version, I hope you guys - ASPNETZero team should consider to add the authorize button by default for users to test the API easier.
Something just easy like this:
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new Info { Title = "O1 API", Version = "v1" });
options.DocInclusionPredicate((docName, description) => true);
options.IncludeXmlComments(Path.ChangeExtension(Assembly.GetEntryAssembly().Location, "xml"));
**options.AddSecurityDefinition("Bearer", new ApiKeyScheme()
{
In = "header",
Description = "Please insert JWT with Bearer into field",
Name = "Authorization",
Type = "apiKey"
});
});**
Hi @ismcagdas, Thank you very much, using IAppConfigurationAccessor help me pretty well. But why I need to use that instead of IConfigurationRoot?
<cite>ismcagdas: </cite> Hi @Khai,
I think you need to use IAppConfigurationAccessor instead of IConfigurationRoot. Can you try that ?
Hello @ismcagdas, Here is my ILibraryAppService, LibraryAppService. What should I do now?
public interface ILibraryAppService : IApplicationService
{
/// <summary>Get All Categories of Tenant or Building with Language</summary>
/// <param name="tenantId">Tenant (Project) - Ex: KRISTA - Required</param>
/// <param name="language">Language Code (3-chars - https://www.science.co.il/language/Codes.php) - Required</param>
/// <param name="buildingId">Building - Ex: KRISTA-T1 - Not-Required - Query String</param>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task<ObservableCollection<CategoryOutputWithLanguage>> ApiCategoryGetAllAsync(string tenantId, string language = null, string buildingId = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Create Category</summary>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task ApiCategoryPostAsync(string tenantId, CategoryInput entityInput = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Get Single Category object with its children.</summary>
/// <param name="categoryId">CategoryId</param>
/// <param name="language">Language Code in 3 characters</param>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task<CategoryOutputWithLanguage> ApiCategoryGetAsync(string categoryId, string tenantId, string language = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Update Category</summary>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task ApiCategoryPutAsync(string tenantId, string categoryId, CategoryInput entityInput = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Delete category (soft-delete)</summary>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task ApiCategoryDeleteAsync(string tenantId, string categoryId, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Get category object with all languages. Usually used for Get for editing</summary>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task<CategoryOutput> ApiCategoryDetailAsync(string categoryId, string tenantId, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Get All Documents in Category with translated Language</summary>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task<ObservableCollection<DocumentOutputWithLanguage>> ApiDocumentGetAllAsync(string tenantId, string categoryId = null, string language = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Create document info object</summary>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task ApiDocumentPostAsync(string tenantId, DocumentInput entityInput = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Get single document info with translated language</summary>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task<DocumentOutputWithLanguage> ApiDocumentGetAsync(string documentId, string tenantId, string language = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Update Document Info object</summary>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task ApiDocumentPutAsync(string tenantId, string documentId, DocumentInput entityInput = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Delete document info (soft-delete)</summary>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task ApiDocumentDeleteAsync(string tenantId, string documentId, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Get single document with all language.
/// Mostly used for getting data to edit</summary>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task<DocumentOutput> ApiDocumentDetailAsync(string documentId, string tenantId, CancellationToken cancellationToken = default(CancellationToken));
}
public partial class LibraryAppService : OnePlaceBaseService, ILibraryAppService
{
private LibraryHttpClient _libraryClient;
private string _baseUrl;
public LibraryAppService()
{
_baseUrl = "http://localhost:30001";
//_baseUrl = appConfigurationRoot["OnePlaceConfig:URL:LibraryManagement"];
}
[AbpAuthorize(AppPermissions.Staffs_Library_Category_ReadAll)]
public async Task<ObservableCollection<CategoryOutputWithLanguage>> ApiCategoryGetAllAsync(string tenantId, string language = null, string buildingId = null,
CancellationToken cancellationToken = default(CancellationToken))
{
_libraryClient = new LibraryHttpClient(_baseUrl, this.GetHttpClient());
return await _libraryClient.ApiCategoryGetAllAsync(tenantId, language, buildingId, cancellationToken);
}
[AbpAuthorize(AppPermissions.Staffs_Library_Category_Create)]
public async Task ApiCategoryPostAsync(string tenantId, CategoryInput entityInput = null,
CancellationToken cancellationToken = default(CancellationToken))
{
_libraryClient = new LibraryHttpClient(_baseUrl, this.GetHttpClient());
await _libraryClient.ApiCategoryPostAsync(tenantId, entityInput, cancellationToken);
}
[AbpAuthorize(AppPermissions.Staffs_Library_Category_Read)]
public async Task<CategoryOutputWithLanguage> ApiCategoryGetAsync(string categoryId, string tenantId, string language = null,
CancellationToken cancellationToken = default(CancellationToken))
{
_libraryClient = new LibraryHttpClient(_baseUrl, this.GetHttpClient());
return await _libraryClient.ApiCategoryGetAsync(categoryId, tenantId, language, cancellationToken);
}
[AbpAuthorize(AppPermissions.Staffs_Library_Category_Update)]
public async Task ApiCategoryPutAsync(string tenantId, string categoryId, CategoryInput entityInput = null,
CancellationToken cancellationToken = default(CancellationToken))
{
_libraryClient = new LibraryHttpClient(_baseUrl, this.GetHttpClient());
await _libraryClient.ApiCategoryPutAsync(tenantId, categoryId, entityInput, cancellationToken);
}
[AbpAuthorize(AppPermissions.Staffs_Library_Category_Delete)]
public async Task ApiCategoryDeleteAsync(string tenantId, string categoryId,
CancellationToken cancellationToken = default(CancellationToken))
{
_libraryClient = new LibraryHttpClient(_baseUrl, this.GetHttpClient());
await _libraryClient.ApiCategoryDeleteAsync(tenantId, categoryId, cancellationToken);
}
[AbpAuthorize(AppPermissions.Staffs_Library_Category_Update)]
public async Task<CategoryOutput> ApiCategoryDetailAsync(string categoryId, string tenantId,
CancellationToken cancellationToken = default(CancellationToken))
{
_libraryClient = new LibraryHttpClient(_baseUrl, this.GetHttpClient());
return await _libraryClient.ApiCategoryDetailAsync(categoryId, tenantId, cancellationToken);
}
[AbpAuthorize(AppPermissions.Staffs_Library_Document_ReadAll)]
public async Task<ObservableCollection<DocumentOutputWithLanguage>> ApiDocumentGetAllAsync(string tenantId, string categoryId = null, string language = null,
CancellationToken cancellationToken = default(CancellationToken))
{
_libraryClient = new LibraryHttpClient(_baseUrl, this.GetHttpClient());
return await _libraryClient.ApiDocumentGetAllAsync(tenantId, categoryId, language, cancellationToken);
}
[AbpAuthorize(AppPermissions.Staffs_Library_Document_Create)]
public async Task ApiDocumentPostAsync(string tenantId, DocumentInput entityInput = null,
CancellationToken cancellationToken = default(CancellationToken))
{
_libraryClient = new LibraryHttpClient(_baseUrl, this.GetHttpClient());
await _libraryClient.ApiDocumentPostAsync(tenantId, entityInput, cancellationToken);
}
[AbpAuthorize(AppPermissions.Staffs_Library_Document_Read)]
public async Task<DocumentOutputWithLanguage> ApiDocumentGetAsync(string documentId, string tenantId, string language = null,
CancellationToken cancellationToken = default(CancellationToken))
{
_libraryClient = new LibraryHttpClient(_baseUrl, this.GetHttpClient());
return await _libraryClient.ApiDocumentGetAsync(documentId, tenantId, language, cancellationToken);
}
[AbpAuthorize(AppPermissions.Staffs_Library_Document_Update)]
public async Task ApiDocumentPutAsync(string tenantId, string documentId, DocumentInput entityInput = null,
CancellationToken cancellationToken = default(CancellationToken))
{
_libraryClient = new LibraryHttpClient(_baseUrl, this.GetHttpClient());
await _libraryClient.ApiDocumentPutAsync(tenantId, documentId, entityInput, cancellationToken);
}
[AbpAuthorize(AppPermissions.Staffs_Library_Document_Delete)]
public async Task ApiDocumentDeleteAsync(string tenantId, string documentId,
CancellationToken cancellationToken = default(CancellationToken))
{
_libraryClient = new LibraryHttpClient(_baseUrl, this.GetHttpClient());
await _libraryClient.ApiDocumentDeleteAsync(tenantId, documentId, cancellationToken);
}
[AbpAuthorize(AppPermissions.Staffs_Library_Category_Update)]
public async Task<DocumentOutput> ApiDocumentDetailAsync(string documentId, string tenantId,
CancellationToken cancellationToken = default(CancellationToken))
{
_libraryClient = new LibraryHttpClient(_baseUrl, this.GetHttpClient());
return await _libraryClient.ApiDocumentDetailAsync(documentId, tenantId, cancellationToken);
}
}
<cite>ismcagdas: </cite> Hi @Khai,
You need to create the implementation of your App service as well.
<cite>ismcagdas: </cite> Hi @Khai,
Can you share your app service interface definition ?
Hi @ismcagdas, This is my app service interface.
public interface ILibraryAppService : IApplicationService
{
/// <summary>Get All Categories</summary>
/// <param name="tenantId">Tenant</param>
/// <param name="language">Language Code (3-chars - https://www.science.co.il/language/Codes.php) - Required</param>
/// <param name="buildingId">Building</param>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task<ObservableCollection<CategoryOutputWithLanguage>> ApiCategoryGetAllAsync(string tenantId, string language = null, string buildingId = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Create Category</summary>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task ApiCategoryPostAsync(string tenantId, CategoryInput entityInput = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Get Single Category object with its children.</summary>
/// <param name="categoryId">CategoryId</param>
/// <param name="language">Language Code in 3 characters</param>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task<CategoryOutputWithLanguage> ApiCategoryGetAsync(string categoryId, string tenantId, string language = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Update Category</summary>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task ApiCategoryPutAsync(string tenantId, string categoryId, CategoryInput entityInput = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Delete category (soft-delete)</summary>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task ApiCategoryDeleteAsync(string tenantId, string categoryId, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Get category object with all languages. Usually used for Get for editing</summary>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task<CategoryOutput> ApiCategoryDetailAsync(string categoryId, string tenantId, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Get All Documents in Category with translated Language</summary>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task<ObservableCollection<DocumentOutputWithLanguage>> ApiDocumentGetAllAsync(string tenantId, string categoryId = null, string language = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Create document info object</summary>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task ApiDocumentPostAsync(string tenantId, DocumentInput entityInput = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Get single document info with translated language</summary>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task<DocumentOutputWithLanguage> ApiDocumentGetAsync(string documentId, string tenantId, string language = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Update Document Info object</summary>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task ApiDocumentPutAsync(string tenantId, string documentId, DocumentInput entityInput = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Delete document info (soft-delete)</summary>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task ApiDocumentDeleteAsync(string tenantId, string documentId, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>Get single document with all language.
/// Mostly used for getting data to edit</summary>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task<DocumentOutput> ApiDocumentDetailAsync(string documentId, string tenantId, CancellationToken cancellationToken = default(CancellationToken));
}
I used NSwag to generate those things to make ASPNETZero become the gateway to my private API (generate HttpClient).
Hello @ismcagdas,
I have checked the Logs.txt file, and this is the result. It seems that the IConfigurationRoot didn't register.
ERROR 2017-11-29 23:53:40,698 [10 ] Mvc.ExceptionHandling.AbpExceptionFilter - Can't create component 'OnePlace.O1.OnePlace.Library.LibraryAppService' as it has dependencies to be satisfied.
'OnePlace.O1.OnePlace.Library.LibraryAppService' is waiting for the following dependencies:
- Service 'Microsoft.Extensions.Configuration.IConfigurationRoot' which was not registered.
Castle.MicroKernel.Handlers.HandlerException: Can't create component 'OnePlace.O1.OnePlace.Library.LibraryAppService' as it has dependencies to be satisfied.
'OnePlace.O1.OnePlace.Library.LibraryAppService' is waiting for the following dependencies:
- Service 'Microsoft.Extensions.Configuration.IConfigurationRoot' which was not registered.
at Castle.MicroKernel.Handlers.DefaultHandler.AssertNotWaitingForDependency()
at Castle.MicroKernel.Handlers.DefaultHandler.ResolveCore(CreationContext context, Boolean requiresDecommission, Boolean instanceRequired, Burden& burden)
at Castle.MicroKernel.Handlers.DefaultHandler.Resolve(CreationContext context, Boolean instanceRequired)
at Castle.MicroKernel.DefaultKernel.ResolveComponent(IHandler handler, Type service, IDictionary additionalArguments, IReleasePolicy policy)
at Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(Type service, IDictionary arguments, IReleasePolicy policy)
at Castle.Windsor.MsDependencyInjection.ScopedWindsorServiceProvider.GetServiceInternal(Type serviceType, Boolean isOptional) in D:\Github\castle-windsor-ms-adapter\src\Castle.Windsor.MsDependencyInjection\ScopedWindsorServiceProvider.cs:line 55
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.AspNetCore.Mvc.Controllers.ServiceBasedControllerActivator.Create(ControllerContext actionContext)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeInnerFilterAsync>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeNextExceptionFilterAsync>d__23.MoveNext()
<cite>ismcagdas: </cite> Hi @Khai,
Have you checked the Logs.txt file for error details ? Probably it contains a detailed error message.
Sorry for bringing it up again. I am using ASPNETZero version 5.0.0 (ASPNET Core + Angular). I wrote comments in my interface (ILibraryAppService) but it won't appear on Swagger. Please help me to figure out this.
/// <summary>Get Single Category object with its children.</summary>
/// <param name="categoryId">CategoryId</param>
/// <param name="language">Language Code in 3 characters</param>
/// <returns>Success</returns>
/// <exception cref="SwaggerException">A server side error occurred.</exception>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
Task<CategoryOutputWithLanguage> ApiCategoryGetAsync(string categoryId, string tenantId, string language = null, CancellationToken cancellationToken = default(CancellationToken));
<cite>ismcagdas: </cite> Hi,
- Can you try writing your comments on AppService interface, not in the AppService class.
- You can use Swagger's DocumentFilter for that. An example would be,
public class FilterRoutesDocumentFilter : IDocumentFilter { public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer) { swaggerDoc.paths["/api/services/app/role/GetRoleForEdit"].post = null; } }
I hope these help.
Hello,
For the first question, I figured out that I can use AbpSession to get UserId and TenantId. But to get the token, how to do that?
However, for the second question, I got some clue of injecting IConfigurationRoot into the constructor of my Service in ApplicationProject. But when I inject it, I got the unexpected error:
Please help me.
Hello, I want to ask a few questions about service in Application project.
1/ I am creating a service (let call it LibraryAppService) and in that service, I want to get the token from current request (or the UserId, TenantId to call other API - which can use the token that AspNetZero issued). How can I do that?
2/ I don't want to hardcode my other API URL inside the LibraryAppService but I want to put it inside AppSettings.json. How can I do that?
Thank you very much.
<cite>ismcagdas: </cite> Hi @Khai,
No, it is not supported yet. We will work on it for the next releases.
OK I will be waiting for this feature. Thank you.
Hello, Does the Angular project support Server-rendering from ASPNET Core or NodeJS? I need this to increase the speed of loading the login page. Thanks.