Activities of "hikalkan"

Answer

Hi,

Every module can be a separate solution (like we did for the modules) or you can develop it under a single Visual Studio solution (for example, in the microservice demo, we've included a product module into the solution).

I suggest you to go with a single solution at the beginning since it is easier to develop, test, run and maintain. You know, in a single solution, you can cross reference projects. Assuming you will create your module as layered (like this), your application's domain layer should depend on the module's domain layer and so on (as a good practice, but you don't have to do). Also, add standard DependsOn attribute (see the document) when you add a project reference.

You can create a new module (using abp new MyProductName.MyModuleName -t module-pro - see), then add its projects to the application's solution then add references and dependson attributes. In the future, we will also automate this.

For the UI part, you can investigate the Angular UI modules we've created to understand how a module is developed. We are using them as NPM packages in the main application, however it may not be practical in development. @mehmet can write you more about that.

  1. options.UseSqlServer() is an extension method defined in the https://www.nuget.org/packages/Volo.Abp.EntityFrameworkCore.SqlServer package and there is no Oracle package. However, Volo.Abp.EntityFrameworkCore.SqlServer is just a simple wrapper. See https://docs.abp.io/en/abp/latest/Entity-Framework-Core-Other-DBMS to understand how to directly use DBMS extension method. This is for MySQL, but will be similar for Oracle too.
  2. Yes. You can have both SQL Server and Oracle nuget package references and call the extension method(s) conditionally.
  3. Yes, in current code AbpEntityFrameworkCoreSqlServerModule is an empty module. But I suggest to remove the related NuGet package when you remove a DependsOn dependency, as a good practice.
  4. See https://github.com/abpframework/abp/issues/2131#issuecomment-563354065

Have a nice day.

Answer

Thank you Don. We'll answer this via email.

Hi,

Lepton theme is bootstrap compatible. Currently, the best way is to override styles by your custom CSS file.

Example For MVC:

Add a style file (e.g. "mystyles.css") into the wwwroot folder:

.lp-opened-sidebar .lp-sidebar, .lp-closed .lp-sidebar {
    background-color: blue;
}

Then add this file to the global bundle (in the ConfigureServices method of your module) to add it to all the pages:

Configure<AbpBundlingOptions>(options =>
{
    options.StyleBundles
        .Get(LeptonThemeBundles.Styles.Global)
        .AddFiles("/mystyles.css");
});

Before the style:

After the style:

It is similar for the angular side.

Inspect element with your browser's developer tools to check the class names to override.

In the future, we will create a theme builder to change color schema easier.

You've written:

abp new abp new Acme.BokStore.... (2 times abp new). Is the problem related to that?

Hi,

Did you run the .DbMigrator application to create the database? It has a seed code to create clients for the auhentication (your error says "invalid_client"). If this doesn't solve the problem, please also share logs in the server side (inside the Logs folder of the application). Also, are you using separated identity server configuration (you can share screenshot of your solution structure in Visual Studio)?

Answer

Hi @trendline

module creates a new module with a sample host application uses the free and open source modules and themes. module-pro uses the commercial modules and themes. It doesn't have much difference for a module development but we suggest you use module pro if you then will use this module in an ABP Commercial based solution.

We will check the problem for module pro, thank you for reporting this.

app creates a free startup template based project with free modules and themes included. if you want to use it, no need to pay for the ABP Commercial :) app-pro creates a startup project based on the commercial modules and themes.

Answer

There is no such a feature yet. Actually, it is a good practice to separate them. However, you can do it manually if you need. We can try to help you if you have any problem on your implementation.

Answer

I created an issue for this: https://github.com/abpframework/abp/issues/2791

Hi,

We are using the Identity Server for authentication. There are some different flows, but I think the most convinient way is to use the resource owner password flow for your case.

The downloaded startup template has a .HttpApi.Client.ConsoleTestApp project which authenticates using this flow by default. However, it assumes that username and password is hard-coded in the appsettings.json. I will explain you how to convert this project to dynamically get username & password from user, then authenticate and get access token.

  1. Create an AccessTokenManager class like that:
using System;
using System.Net.Http;
using System.Threading.Tasks;
using IdentityModel.Client;
using Volo.Abp.DependencyInjection;

namespace MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp
{
    public class AccessTokenManager : ISingletonDependency
    {
        public string AccessToken { get; private set; }

        private readonly IHttpClientFactory _httpClientFactory;

        public AccessTokenManager(IHttpClientFactory httpClientFactory)
        {
            _httpClientFactory = httpClientFactory;
        }

        public async Task ObtainAccessToken()
        {
            Console.Write("Username: ");
            var userName = Console.ReadLine();

            Console.Write("Password: ");
            var password = Console.ReadLine();

            var discoveryResponse = await GetDiscoveryResponse();
            var tokenResponse = await GetTokenResponse(discoveryResponse, userName, password);

            AccessToken = tokenResponse.AccessToken;
        }

        protected async Task<DiscoveryDocumentResponse> GetDiscoveryResponse()
        {
            using (var httpClient = _httpClientFactory.CreateClient())
            {
                return await httpClient.GetDiscoveryDocumentAsync(new DiscoveryDocumentRequest
                {
                    Address = "https://localhost:44301",
                    Policy = { RequireHttps = true }
                });
            }
        }

        protected async Task<TokenResponse> GetTokenResponse(
            DiscoveryDocumentResponse discoveryResponse,
            string userName,
            string password
        )
        {
            using (var httpClient = _httpClientFactory.CreateClient())
            {
                return await httpClient.RequestPasswordTokenAsync(
                    await CreatePasswordTokenRequestAsync(discoveryResponse, userName, password)
                );
            }
        }

        protected virtual Task<PasswordTokenRequest> CreatePasswordTokenRequestAsync(
            DiscoveryDocumentResponse discoveryResponse,
            string userName,
            string password)
        {
            var request = new PasswordTokenRequest
            {
                Address = discoveryResponse.TokenEndpoint,
                Scope = "MyProjectName",
                ClientId = "MyProjectName_App",
                ClientSecret = "1q2w3e*",
                UserName = userName,
                Password = password
            };

            return Task.FromResult(request);
        }

    }
}

ObtainAccessToken() method gets user & pass from console, authenticates to the identity server (just as described in the IDS4 documentation), then sets it to the AccessToken property. This class is singleton, so you can access the token from another service later.

I've written the configuration hard-coded, you need to refactor the code :)

  1. ABP Framework's dynamic c# proxy system uses the IRemoteServiceHttpClientAuthenticator to get the access token. So, you need to implement it:
using System.Threading.Tasks;
using IdentityModel.Client;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Http.Client.Authentication;

namespace MyCompanyName.MyProjectName.HttpApi.Client.ConsoleTestApp
{
    public class MyRemoteServiceHttpClientAuthenticator : IRemoteServiceHttpClientAuthenticator, ITransientDependency
    {
        private readonly AccessTokenManager _accessTokenManager;

        public MyRemoteServiceHttpClientAuthenticator(AccessTokenManager accessTokenManager)
        {
            _accessTokenManager = accessTokenManager;
        }

        public Task Authenticate(RemoteServiceHttpClientAuthenticateContext context)
        {
            context.Client.SetBearerToken(_accessTokenManager.AccessToken);
            return Task.CompletedTask;
        }
    }
}

This gets the token from the AccessTokenManager. It is very simple.

  1. Call the AccessTokenManager.ObtainAccessToken() on your login screen of the WPF app. In this console app, I called it inside the ConsoleTestAppHostedService, before the ClientDemoService usage:
await application.ServiceProvider
    .GetRequiredService<AccessTokenManager>()
    .ObtainAccessToken();

var demo = application.ServiceProvider.GetRequiredService<ClientDemoService>();
await demo.RunAsync();

That's all! Enjoy with the ABP Framework :)

Showing 1 to 10 of 75 entries
Made with ❤️ on ABP v8.2.0-preview Updated on March 25, 2024, 15:11