Base solution for your next web application

Activities of "khai"

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"
                });
            });**

And we will have this:

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?

  1. ILibraryAppService
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));
    }
  1. LibraryAppService
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,

  1. Can you try writing your comments on AppService interface, not in the AppService class.
  2. 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:

  • Build OK
  • Run-time OK And when I send a request to that service, I got 500 and "An internal error occurred during your request!" without any clue to figure out.

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.

Showing 11 to 20 of 27 entries