Skip to main content
Version: V6

V5 to V6

Prerequisites

Angular V20 Migration

Editor's migration guides

Deprecation of Angular's animations package

warning

Angular has deprecated the animations package to use the native CSS instead.
Your project can lead to some warning issues when linting.

To fix them, follow the official migration documentation

Manual migration instructions

For each Angular project :

info
  1. Decline use-application-builder migration
  2. Decline control-flow-migration migration
  3. Accept router-current-navigation migration

EF Migration History table migration

BIA Framework Migration

info

Run it automatically by clicking on Migrate button
or
Execute each step manually until step 3 - Apply Diff

warning

Mind to check the output logs to check any errors or missing deleted files

info
  • SOLUTION 1 : Merging rejected files

  • SOLUTION 2 : Analyzing rejected files - MANUAL MIGRATION ONLY

tip

Use the conflict resolution chapter to help you


For each Angular project :

Download the migration script (.txt - Save link as), then :

For each Angular project :

info
  1. validate current path as target path
  2. accept reformat templates option
warning

If some warning about deprecation of NgIf, NgFor or NgSwitch are printed from the final linting, it means that the execution of ng generate @angular/core:control-flow has ignored the migration for concerned file due to some safety constraints.

You have to manually migrate to control flow instructions the identified files (Angular Documentation)



tip

For manual management of conflitcs case : you can remove the .rej files




warning

Conflict Resolution

all-environments.ts

Keep all your teams definition, there will be used by the migration script for the Team Configuration step

AuditFeature.cs

Into AuditTypeMapper method, integrate your old switch case conditions into the new one :

AuditFeature.cs (OLD)
public override Type AuditTypeMapper(Type type)
{
switch(type.Name)
{
case "MyEntity":
return typeof(MyEntityAudit);
default:
return base.AuditTypeMapper(type);
}
}
AuditFeature.cs (NEW)
public override Type AuditTypeMapper(Type type)
{
return type.Name switch
{
// Your previous mapping here
nameof(MyEntity) => typeof(MyEntityAudit),

// BIAToolKit - Begin AuditTypeMapper
// BIAToolKit - End AuditTypeMapper
nameof(User) => typeof(UserAudit),
_ => base.AuditTypeMapper(type),
};
}

CS projects packages references

Keep your packages references into your .csproj, they will be modified by the migration script on the next steps

Front Manual Steps

Full code Index Component

For your full code feature-index.component.html, you will have to add into the .ts the following method :

feature-index.component.ts
onViewNameChange(viewName: string | null) {}

Or, you can simply remove from the .html the following binding : (viewNameChange)="onViewNameChange($event)"

Team Configuration

tip

Automatically handled by migration script, for information purpose and manual adjustement only.

From the file all-environments.ts, move the content of your teams configuration into back-end file TeamConfig.cs :

all-environments.ts
export const allEnvironments = {
teams: [
{
teamTypeId: TeamTypeId.MyTeam,
// Configuration to move below
roleMode: RoleMode.AllRoles,
inHeader: true,
displayOne: false,
displayAlways: false,
teamSelectionCanBeEmpty: false,
label: 'myTeam.headerLabel',
},
]
}
TeamConfig.cs
public static class TeamConfig
{
public static readonly ImmutableList<BiaTeamConfig<BaseEntityTeam>> Config = new ImmutableListBuilder<BiaTeamConfig<BaseEntityTeam>>()
{
new BiaTeamConfig<BaseEntityTeam>()
{
TeamTypeId = (int)TeamTypeId.MyTeam,
RightPrefix = "MyTeam",
AdminRoleIds = [(int)RoleId.MyTeamAdmin],
TeamAutomaticSelectionMode = BIA.Net.Core.Common.Enum.TeamSelectionMode.None,
// Configuration from TS
RoleMode = BIA.Net.Core.Common.Enum.RoleMode.AllRoles,
DisplayInHeader = true,
DisplayOne = false,
DisplayAlways = false,
TeamSelectionCanBeEmpty = false
Label = "myTeam.headerLabel",
},
}
}

Then, remove the teams from all-environments.ts

useRefreshAtLanguageChange

In previous version, you'll have to use useRefreshAtLanguageChange property defined into your index components, usually to handle changes of current culture to refresh your data by calling onLoadLazy :

my-features-index.component.ts
ngOnInit(): void {
super.ngOnInit();

if (this.useRefreshAtLanguageChange) {
this.sub.add(
this.biaTranslationService.currentCulture$
.pipe(skip(1))
.subscribe(() => {
this.onLoadLazy(this.crudItemListComponent.getLazyLoadMetadata());
})
);
}
}

By now, this refresh is automatically handled into the CrudItemsIndexCompoent by using the property useRefreshAtLanguageChange from the crudConfiguration.
So, you can remove from your index component the handler of this.biaTranslationService.currentCulture$ to call onLoadLazy, and set into your feature constants the useRefreshAtLanguageChange to true :

my-feature.constants.ts
export const announcementCRUDConfiguration: CrudConfig<MyFeature> =
new CrudConfig({
// [...]
useRefreshAtLanguageChange: true,
});

For all cases using the previous useRefreshAtLanguageChange from CrudItemIndexComponent, simply use now the same property from the crudConfiguration.

Back Manual Steps

Package Version

Open the DotNet\Directory.Packages.Project.props file and check that no package version contains a wildcard (*). If a wildcard is found, replace it with the desired version number.

Example Before

<Project>
<ItemGroup>
<!-- Add the versions of your packages here. -->
<!-- <PackageVersion Include="MyPackageNameExample" Version="6.0.4" /> -->
<PackageVersion Include="Microsoft.AspNetCore.Http.Features" Version="2.2.0" />
<PackageVersion Include="System.Security.Principal.Windows" Version="5.0.*" />
</ItemGroup>
</Project>

Example After

<Project>
<ItemGroup>
<!-- Add the versions of your packages here. -->
<!-- <PackageVersion Include="MyPackageNameExample" Version="6.0.4" /> -->
<PackageVersion Include="Microsoft.AspNetCore.Http.Features" Version="2.2.0" />
<PackageVersion Include="System.Security.Principal.Windows" Version="5.0.0" />
</ItemGroup>
</Project>

Audit Entities

For all your previous audit entities inherited from AuditEntity :

  • inherits from AuditKeyedEntity<TEntity, TEntityKey, TAuditKey> for audited entities with single PK
  • inherits from AuditEntity<TEntity, TAuditKey> for audited join entities with composite PK
tip

See Audit documentation for dedicated audit tables.

OperationalDomainServiceBase inheritage and override

Inheritage

You must fix your class that inherits from OperationalDomainServiceBase by providing new required generic types :

  • TDto : DTO mapped to your TEntity
  • TDtoListItem : DTO mapped to your TEntity for your lists display and export
  • TMapper : mapper between your entity and the DTO
  • TMapperListItem : mapper between your entity and the DTO used for lists
  • TFilterDto : filter type of your entity
tip

Prefer to inherit from CrudAppServiceBase or CrudAppServiceListAndItemBase when you need the OperationDomainServiceBase methods.
Inherit directly from DomainServiceBase if you just need to access to the IRepository.

BEFORE
public class MyService : OperationDomainServiceBase<MyEntity, int>
AFTER
public class MyService : OperationDomainServiceBase<MyEntityDto, MyEntityDto, MyEntity, int, PagingFilterFormatDto, MyEntityMapper, MyEntityMapper>
tip

You can inherits your class interface from the dedicated interface IOperationDomainServiceBase<TDto, TDtoListItem, TEntity, TKey, TFilterDto> if needed

Overrides

warning
  • These methods have been renamed as {MethodName}GenericAsync :
    • GetRangeAsync<TOtherDto, TOtherMapper, TOtherFilterDto>
    • GetAllAsync<TOtherDto, TOtherMapper>
    • GetCsvAsync<TOtherDto, TOtherMapper, TOtherFilterDto>
    • GetAsync<TOtherDto, TOtherMapper>
    • AddAsync<TOtherDto, TOtherMapper>
    • UpdateAsync<TOtherDto, TOtherMapper>
    • RemoveAsync<TOtherDto, TOtherMapper>
    • SaveSafeAsync<TOtherDto, TOtherMapper>
    • SaveAsync<TOtherDto, TOtherMapper>
    • UpdateFixedAsync<TOtherDto, TOtherMapper>

You should only override the public non generic methods equivalent

BEFORE
public class MyService : OperationDomainServiceBase<MyEntity, int>
{
protected override async Task<(IEnumerable<TOtherDto> Results, int Total)> GetRangeAsync<TOtherDto, TOtherMapper, TOtherFilterDto>(TOtherFilterDto filters = null, int id = default, Specification<MyEntity> specification = null, Expression<Func<MyEntity, bool>> filter = null, string accessMode = "Read", string queryMode = "ReadList", string mapperMode = null, bool isReadOnlyMode = false)
{
// Custom code...

return await base.GetRangeAsync<TOtherDto, TOtherMapper, TOtherFilterDto>(filters, id, specification, filter, accessMode, queryMode, mapperMode, isReadOnlyMode);
}
}
AFTER
public class MyService : OperationDomainServiceBase<MyEntityDto, MyEntityDto, MyEntity, int, PagingFilterFormatDto, MyEntityMapper, MyEntityMapper>
{
public override async Task<(IEnumerable<MyEntityDto> Results, int Total)> GetRangeAsync(PagingFilterFormatDto filters = null, int id = 0, Specification<MyEntity> specification = null, Expression<Func<MyEntity, bool>> filter = null, string accessMode = "Read", string queryMode = "ReadList", string mapperMode = null, bool isReadOnlyMode = false)
{
// Custom code...

return await base.GetRangeAsync(filters, id, specification, filter, accessMode, queryMode, mapperMode, isReadOnlyMode);
}
}
info

The transformation for the previous overrides of the protected generic methods into public non generic, and the rename of the generic methods usage, are automatically handled by migration script for classes that inherits from CrudAppServiceBase or CrudAppServiceListAndItemBase.

Please review the migration script actions into your application services.

warning
  • Following methods required now one or multiple delegate parameter in order to execute their algorithm with overriden methods :
    • GetCsvGenericAsync<TOtherDto, TOtherMapper, TOtherFilterDto>
    • SaveSafeGenericAsync<TOtherDto, TOtherMapper>
    • SaveGenericAsync<TOtherDto, TOtherMapper>
    • UpdateFixedGenericAsync<TOtherDto, TOtherMapper>

Example below shows you how to call properly one of them with the correct delegate :

MyService
public class MyService : OperationDomainServiceBase<MyEntityDto, MyEntityDto, MyEntity, int, PagingFilterFormatDto, MyEntityMapper, MyEntityMapper>
{
public Task<byte[]> GetCsvCustomAsync()
{
// Use of non generic GetRangeAsync
return this.GetCsvGenericAsync<MyEntityDto, MyEntityMapper, PagingFilterFormatDto>(this.GetRangeAsync);

// Use of generic GetRangeGenericAsync with custom types
return this.GetCsvGenericAsync<MyOtherEntityDto, MyOtherEntityMapper, CustomPagingFilterFormatDto>(this.GetRangeGenericAsync<MyOtherEntityDto, MyOtherEntityMapper, CustomPagingFilterFormatDto>);

// Use of custom generic GetRangeGenericAsync with custom types
return this.GetCsvGenericAsync<MyOtherEntityDto, MyOtherEntityMapper, CustomPagingFilterFormatDto>(this.GetRangeGenericCustomAsync<MyOtherEntityDto, MyOtherEntityMapper, CustomPagingFilterFormatDto>);
}

// Must respect the signature of the delegate GetRangeGenericAsyncDelegate
private async Task<(IEnumerable<TOtherDto> Results, int Total)> GetRangeGenericCustomAsync<TOtherDto, TOtherMapper, TOtherFilterDto>(TOtherFilterDto filters = null, Guid id = default, Specification<Pilot> specification = null, Expression<Func<Pilot, bool>> filter = null, string accessMode = "Read", string queryMode = "ReadList", string mapperMode = null, bool isReadOnlyMode = false)
{
// Custom code...
}
}

:::

Database Migration

You must create a new database migration in order to apply framework changes to your database scheme :

  1. add-migration MigrationBiaFrameworkV6 -c datacontext
  2. update-database -context datacontext

Build Pipeline

  1. Set the Visual Studio version

    • Task: Build solution → Visual Studio Version
    • Value: Visual Studio 2026
  2. Declare pipeline variables

    • Name: DotNetVersion
    • Value: net10.0
  3. Update paths to target .NET 10.0

    • API Tests → Test files
      **\$(BuildConfiguration)\$(DotNetVersion)\*$(ProjectName).Test.dll
      !**\obj\**
    • Copy Files Presentation Api → Source Folder
      DotNet/$(CompanyName).$(ProjectName).Presentation.Api/bin/$(BuildConfiguration)/$(DotNetVersion)
    • Copy Files Worker service → Source Folder
      DotNet/$(CompanyName).$(ProjectName).WorkerService/bin/$(BuildConfiguration)/$(DotNetVersion)
    • Copy Files DeployDB → Source Folder
      DotNet/$(CompanyName).$(ProjectName).DeployDB/bin/$(BuildConfiguration)/$(DotNetVersion)