Activities of "GregB"

  • ABP Framework version: v4.3.3
  • UI type: Angular
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): no
  • Exception message and stack trace: N/A
  • Steps to reproduce the issue:"

How can I force all validation errors to show in an Angular form?

I've got a simple form with a required field

 this.form = this.fb.group({
            name: [name ?? null, [Validators.required]]
           });

But when I click submit, no errors are shown.

submitForm()
{
   if(!this.form.valid)
   {
       // How do I show the errors?
       return;
   }
   
   // ...
}

If I type something into the field, then delete it, the required validation message shows.

I want to show all validation errors when the user tries to submit an invalid form.

  • ABP Framework version: v4.3.3
  • UI type: Angular
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Separated (Angular): no (Angular)
  • Exception message and stack trace: N/A
  • Steps to reproduce the issue:"

How do I set the default culture and UI culture of my Angular app?

I've configured my FooApiHostModule like so

private void ConfigureLocalization()
{
    Configure<AbpLocalizationOptions>(options =>
    {
        options.Languages.Clear();
        options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English"));
    });
}

I've duplicated the en.json localization file and renamed it en-GB, I've changed the Culture elemein in the top of that file like so

{
  "Culture": "en-GB",
  "Texts": {
    ...
  }
}

If I put a breakpoint in a controller action, and inspect System.Threading.Thread.CurrentThread.CurrentCulture and System.Threading.Thread.CurrentThread.CurrentUICulture they're both "en", not "en-GB".

How do I get my application to run in en-GB ?

I've also cahnged my Startup.Configure() method like so, but this doesn't fix it either.

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
    {
        app.InitializeApplication();

        app.UseRequestLocalization(new RequestLocalizationOptions
        {
            DefaultRequestCulture = new RequestCulture("en-GB"),
            SupportedCultures =
            {
                new CultureInfo("en-GB")
            },
            SupportedUICultures =
            {
                new CultureInfo("en-GB")
            }
        });
    }
  • ABP Framework version: v4.3.0
  • UI type: Angular
  • DB provider: EF Core / MongoDB
  • Tiered (MVC) or Identity Server Separated (Angular): no
  • Exception message and stack trace: N/A
  • Steps to reproduce the issue:"

I've got an entity with a backing field navigation property like so.

   public class Customer : FullAuditedAggregateRoot<Guid>, IHasTimelineTopic, IHasAttachments
    {
        private readonly HashSet<Contact> _contacts = new();
        public IEnumerable<Contact> Contacts => _contacts?.ToList();
        
        public void AddContacts(IEnumerable<Contact> contacts)
        {
            Check.NotNull(contacts, nameof(contacts));

            foreach (var contact in contacts)
            {
                _contacts.Add(contact);
            }
        }

        public void RemoveContacts(IEnumerable<Contact> contacts)
        {
            Check.NotNull(contacts, nameof(contacts));

            foreach (var contact in contacts)
            {
                _contacts.Remove(contact);
            }
        }
    }

it's EF config looks like

            builder.Entity<Customer>(b =>
            {
                b.ToTable(FooConsts.DbTablePrefix + "Customers", FooConsts.DbSchema);
                b.ConfigureByConvention();
                b.HasMany(x => x.Contacts).WithMany(x => x.Customers)
                    .UsingEntity(join => join.ToTable("AppCustomerContacts"));
                b.Navigation(nameof(Customer.Contacts))
                    .UsePropertyAccessMode(PropertyAccessMode.Field);
            });

In my AppService I can update it like so

    [Authorize(FooPermissions.Customers.Edit)]
    public virtual async Task&lt;CustomerDto&gt; UpdateAsync(Guid id, CustomerUpdateDto input)
    {
        var customer = await _customerRepository.GetAsync(id);
        ObjectMapper.Map(input, customer);

        var contacts = await _contactRepository.FindListAsync(input.ContactIds);
        customer.AddContacts(contacts);

        var toRemove = customer.Contacts.Where(x => input.ContactIds.Contains(x.Id) == false).ToList();
        customer.RemoveContacts(toRemove);

        customer = await _customerRepository.UpdateAsync(customer, autoSave: true);
        return ObjectMapper.Map&lt;Customer, CustomerDto&gt;(customer);
    }

this works fine and generates two SQL statements, one to update the AppCustomerContacts xref table and one to update the entity itself.

I'm trying to write a console aplication to load some data from an Excel file. I followed the strucure of the included DbMigratior app and I've got :

  • Program.cs which configures the Logger and creates the HstBuilder, registering a hosted service...
  • DataSeederHostedService whichis an IHostedService and takes an IHostApplicationLifetime as a constructor parameter. It has a StartAsync() method which does just like the DbMigratior. It creates a DataSeederModule from the AbpApplicationfactory, calls UseAutoFac() and AddLogging(). Initializes the application, gets a DataSeedingService from the ServiceProvider and calls my SeedAsync() method.
  • My DataSeedingService is an IDomainService which takes a few repositories, the IGuidGenerator and IUnitOfWork as constructor paramerters.

The DataSeedingService adds Contacts to my Customers in the same way as above, using .AddContacts() but when I call await _customerRepository.UpdateAsync(customer, true); it only generates a single SQL statement to update the entity and doesn't insert anything into AppCustomerContacts.

What am I missing?

Here's how SeedAsync() calls the

contact = await _contactRepository.InsertAsync(contact, true);
customer = await _customerRepository.GetAsync(customerId);
customer.AddContact(contact);

_logger.LogInformation($"\t Adding contact to customer {customer.Name}");

customer = await _customerRepository.UpdateAsync(customer, true);

My DataSeederModule looks like this

    [DependsOn(
        typeof(AbpAutofacModule),
        typeofFooDomainModule),
        typeof(EFooEntityFrameworkCoreModule),
        typeof(FooApplicationContractsModule)
        )]
    public class FooDataSeederModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            Configure<AbpBackgroundJobOptions>(options =>
            {
                options.IsJobExecutionEnabled = false;
            });
        }
    }

Why isn't my console app generating two SQL statements? What am I missing? Do I need to reference another module or configure something at app startup?

  • ABP Framework version: v3.3.2
  • UI type: Angular
  • Tiered (MVC) or Identity Server Seperated (Angular): no
  • Exception message and stack trace: N/A
  • Steps to reproduce the issue:

I can't get login to work reliably after deploying to a server. It works sometimes, at a guess about 3% of the time, but I can't reproduce it reliably to get an accurate number. It only happens once deployed, but I've deployed to two separate environments, a VPS and Azure and ended up with the same situation. This suggests it's something I'm doing (or not doing) but the lack of deployment instructions makes it hard to know.

Here's what I'm doing:

  1. I've got a pretty vanilla ABP Commercial 3.3.2 app. It's gota few entities and a few custom Angiular components. I haven't changed any configuration options (in ConfigureServices etc).
  2. This all works fine locally.
  3. I've added an environment.azure.ts file to the angular project like
import { Config } from '@abp/ng.core';

/* web URL */
const baseUrl = 'https://example.z33.web.core.windows.net';

export const environment = {
  production: true,
  application: {
    baseUrl,
    name: 'MyApp',
  },
  oAuthConfig: {
    issuer: 'https://example-api.azurewebsites.net',
    redirectUri: baseUrl,
    clientId: 'MyApp_App',
    responseType: 'code',
    scope: 'offline_access MyApp',
  },
  apis: {
    default: {
      url: 'https://example-api.azurewebsites.net',
      rootNamespace: 'MyApp',
    },
  },
} as Config.Environment;

  1. I've added a corresponding configuration to the angular.json
"configurations": {
                        "production": {
                            ...
                        },
                        "azure": {
                            "fileReplacements": [
                                {
                                    "replace": "src/environments/environment.ts",
                                    "with": "src/environments/environment.azure.ts"
                                }
                            ],
                            "optimization": true,
                            ...
                        }
                }
  1. I've build this with yarn build:azure and upload the output to Static Website in blob storage at https://example.z33.web.core.windows.net.
  2. In the API project I've added an apsettings.Staging_2.json like so
{
  "App": {
    "SelfUrl": "https://example-api.azurewebsites.net",
    "ClientUrl": "https://example.z33.web.core.windows.net",
    "CorsOrigins": "https://example.z33.web.core.windows.net,http://example.z33.web.core.windows.net"
  },
  "ConnectionStrings": {
    "Default": "xxxx"
  },
  "AuthServer": {
    "Authority": "https://example-api.azurewebsites.net",
    "RequireHttpsMetadata": "true"
  },
 }
  1. I've build and deployed this to an Azure AppService
  2. Next I create a SQL Azure database and allow my client IP. Configure users and confirm I can connect via SSMS
  3. I go to Example.DbMigrator\bin\Debug\netcoreapp3.1 and edit the appSettings.json and add in the connection string from step #7 above . I change the IdentityServer section to
      "ExcelErp_App": {
        "ClientId": "ExcelErp_App",
        "RootUrl": "https://example.z33.web.core.windows.net"
      },

(as per https://support.abp.io/QA/Questions/524/UNAUTHORIZEDCLIENT-after-deploying-to-test-server, no trailing slash) 9. I run the DbMigrator and confirm the tables have been created and the seed data added. The Admin user is there and if I check [IdentityServerClientRedirectUris] I can see a row for ClientId RedirectUri CDFEC9FC-51C9-A562-089C-39F953F0ECAB https://example.z33.web.core.windows.net

  1. Now I visit https://example.z33.web.core.windows.net and get the login screeen fine.
  2. If I visit https://example-api.azurewebsites.net/.well-known/openid-configuration I get what appears to be a valid configuration document wiht the correct URLs as per my config.
  3. If I visit https://example.azurewebsites.net/swagger/index.html I get the swagger UI as expected.
  4. Now, back in the Angular app at https://example.z33.web.core.windows.net, if I enter the default admin un/pw the form POSTs to /Account/Login, the broswer spins until it times out.
  5. Now, here's the interesting bit, as mentioned at the top, some tiny percentage of the time, if you go back to the Angular UI and refresh, you are logged in, but that's probably <3% of the time. The other 97%+ you're just greeted with the Login screen again.

What's happening? What am I doing wrong?

  • ABP Framework version: v3.3.1
  • UI type: Angular
  • Tiered (MVC) or Identity Server Seperated (Angular): no
  • Exception message and stack trace: n/a
  • Steps to reproduce the issue: n/a

I want to integrate the file management system into my UI. I want my users to be able to select a file to associate it with an entity.

How can I put a file picker component in my Angular component so the user can pick a file from the File Mangement system?

Suite is generating invalid C#. It's looks like it's leaving a replacement token on the end of property definitions.

I'm using Suite 3.3.1

[StringLength(BomListConsts.DescriptionMaxLength)]
public string Description { get; set; } %%initial-value%%

I've tried creating a brand new Suite project and adding a simple Foo entity with a sinle int property and I get the following code for the DTOs.

public class FoooCreateDto
    {
        public int? F1 { get; set; } %%initial-value%%
    }
    
    
    public class FoooDto : FullAuditedEntityDto<Guid>
    {
        public int? F1 { get; set; } %%initial-value%%
    }
    
    
    public class FoooUpdateDto
    {
        public int? F1 { get; set; } %%initial-value%%
    }

The tool is absolutely unusable and I've wasted half a day trying different things to get it working thinking it was something wrong with my object definition.

This is unacceptable.

Please advise

Check the docs before asking a question: https://docs.abp.io/en/commercial/latest/ Check the samples, to see the basic tasks: https://docs.abp.io/en/commercial/latest/samples/index The exact solution to your question may have been answered before, please use the search on the homepage.

  • ABP Framework version: v3.3.0
  • UI type: Angular
  • Tiered (MVC) or Identity Server Seperated (Angular): no
  • Exception message and stack trace:

500 Internal Server Error UNAUTHORIZED_CLIENT

2020-11-02 11:04:48.240 +00:00 [ERR] Invalid redirect_uri: https://dev-web.example.com/ {"ClientId":"Example_App","ClientName":"Example_App","RedirectUri":null,"AllowedRedirectUris":["https://dev-api.example.com","https://dev-web.example.com"],"SubjectId":"anonymous","ResponseType":null,"ResponseMode":null,"GrantType":null,"RequestedScopes":"","State":null,"UiLocales":null,"Nonce":null,"AuthenticationContextReferenceClasses":null,"DisplayMode":null,"PromptMode":null,"MaxAge":null,"LoginHint":null,"SessionId":null,"Raw":{"response_type":"code","client_id":"Example_App","state":"MldHMGt1TnZkS0ItcnBXQzU1WGROck9LTWp5MGlzdFJEdjV0UE9sMS5DUjdD","redirect_uri":"https://dev-web.example.com/","scope":"openid offline_access Example","code_challenge":"vXXK9P8NZ7zMPbzktJetY4amyp5F1sqWU-rYTpQPJ3c","code_challenge_method":"S256","nonce":"MldHMGt1TnZkS0ItcnBXQzU1WGROck9LTWp5MGlzdFJEdjV0UE9sMS5DUjdD"},"$type":"AuthorizeRequestValidationLog"}

  • Steps to reproduce the issue:
  1. I've added a "development" environment to the Angular project, changing the values like so
import { Config } from '@abp/ng.core';

const baseUrl = 'https://dev-web.example.com/';

export const environment = {
  production: true,
  application: {
    baseUrl,
    name: 'Example',
  },
  oAuthConfig: {
    issuer: 'https://dev-api.example.com',
    redirectUri: baseUrl,
    clientId: 'Example_App',
    responseType: 'code',
    scope: 'offline_access Example',
  },
  apis: {
    default: {
      url: 'https://dev-api.example.com',
      rootNamespace: 'Example',
    },
  },
} as Config.Environment;

  1. I've added a new task to the package and run it. "build:dev": "ng build --configuration development" and yarn build:dev
  2. I've copied the DbMigrator to my server. Updated appsettings.json as follows and run the migrator
{
    "ConnectionStrings": {
      "Default": "Server=localhost\\sqlexpress;Database=Example-Dev;Trusted_Connection=True;MultipleActiveResultSets=true"
    },
    "IdentityServer": {
      "Clients": {
        "Example_Web": {
          "ClientId": "Example_Web",
          "RootUrl": "https://dev-web.example.com/"
        },
        "Example_App": {
          "ClientId": "Example_App",
          "RootUrl": "https://dev-api.example.com/"
        },
        "Example_Blazor": {
          "ClientId": "Example_Blazor",
          "RootUrl": "https://localhost:44307"
        }
      }
    },
    "AbpLicenseCode": "..."
  }
  
  1. I've deployed the API project with matching values in the appsettings.json
{
  "App": {
    "SelfUrl": "https://dev-api.example.com/",
    "ClientUrl": "https://dev-web.example.com/",
    "CorsOrigins": "http://dev-web.example.com/,https://dev-web.example.com/"
  },
  "ConnectionStrings": {
    "Default": "Server=localhost\\SQLExpress;Database=Example-Dev;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
  "AuthServer": {
    "Authority": "https://dev-api.example.com",
    "RequireHttpsMetadata": "true"
  },
}

The Issue I can browse the Swagger document and the Angular app fine, but when I try to log in I get the error screen from the API stating
500 Internal Server Error UNAUTHORIZED_CLIENT

and the following messages in the log 2020-11-02 11:04:48.240 +00:00 [ERR] Invalid redirect_uri: https://dev-web.example.com/ {"ClientId":"Example_App","ClientName":"Example_App","RedirectUri":null,"AllowedRedirectUris":["https://dev-api.example.com","https://dev-web.example.com"],"SubjectId":"anonymous","ResponseType":null,"ResponseMode":null,"GrantType":null,"RequestedScopes":"","State":null,"UiLocales":null,"Nonce":null,"AuthenticationContextReferenceClasses":null,"DisplayMode":null,"PromptMode":null,"MaxAge":null,"LoginHint":null,"SessionId":null,"Raw":{"response_type":"code","client_id":"Example_App","state":"MldHMGt1TnZkS0ItcnBXQzU1WGROck9LTWp5MGlzdFJEdjV0UE9sMS5DUjdD","redirect_uri":"https://dev-web.example.com/","scope":"openid offline_access Example","code_challenge":"vXXK9P8NZ7zMPbzktJetY4amyp5F1sqWU-rYTpQPJ3c","code_challenge_method":"S256","nonce":"MldHMGt1TnZkS0ItcnBXQzU1WGROck9LTWp5MGlzdFJEdjV0UE9sMS5DUjdD"},"$type":"AuthorizeRequestValidationLog"}

What's wrong, and what is the processess for deploying an appilcation to a live environment?

Check the docs before asking a question: https://docs.abp.io/en/commercial/latest/ Check the samples, to see the basic tasks: https://docs.abp.io/en/commercial/latest/samples/index The exact solution to your question may have been answered before, please use the search on the homepage.

  • ABP Framework version: v3.3.0
  • UI type: Angular
  • Tiered (MVC) or Identity Server Seperated (Angular): no
  • Exception message and stack trace: N/A
  • Steps to reproduce the issue: N/A

The documenation makes reference to DDD and describes the use of Entities and Aggregate Roots but I can't see an example of the right* way to implement this.

When you generate an Entity (FullyAuditedEntity) with ABP Suite it generates an AppService, Repository, UI and all the other bits for that entity. My understanding (which is far from complete admittedly).

Let's take an example of a simple order form or invoice (not ecommerce). The user creates a new Invoice (Aggregate Root) and adds LineItems to it. This is pretty much the canoncial example of an Aggreagate Root (, right?) and we're told the Invoice should be bring with it the line items, and then you add new items to that Aggregate Root, and then persist the Aggregate Root and it's line items as a whole.

How does this map to the patterns in ABP? Should we use standard EF functionality to Include() the line items, map those to LineItemDtos and put a IList<LineItemDto> on the Invoice aggregate root? Or should we use the service and repository provided when we create the entity?

Thinking specifically about the Angular UI, should we be loading the line items in a separate AJAX call or do they come from the Invoice service?

As a new ABP customer I feel this information is missing from the documentation and that an explanation of this canonical DDD example would be a great addition to the platform.

Thanks, Greg

  • according to the patterns and best practices of the ABP framework

Check the docs before asking a question: https://docs.abp.io/en/commercial/latest/ Check the samples, to see the basic tasks: https://docs.abp.io/en/commercial/latest/samples/index The exact solution to your question may have been answered before, please use the search on the homepage.

  • ABP Framework version: v3.2.1
  • UI type: Angular
  • Tiered (MVC) or Identity Server Seperated (Angular): Tiered
  • Exception message and stack trace: N/A
  • Steps to reproduce the issue:

How can I add a custom theme to an ABP app using Angular UI?

Showing 1 to 9 of 9 entries
Made with ❤️ on ABP v9.1.0-preview. Updated on November 11, 2024, 11:11