Skip to main content
Version: 3.9.0

v3.8.0 to v3.9.0

AUTOMATIC MIGRATION

  1. Update Visual Studio to the latest version ((Migration tested with Visual Studio 2022 version 17.10.3)). On Visual Studio Code, install extension ESLint and Prettier - Code formatter

  2. Use the BIAToolKit to migrate the project

  3. Delete all package-lock.json and node_modules folder

  4. Manage the conflict (2 solutions)

    1. In BIAToolKit click on "4 - merge Rejected" and search <<<<< in all files.
    • Resolve the conflict manually.
    1. Analyze the .rej file (search "diff a/" in VS code) that have been created in your project folder
    • Apply manually the change.
  5. Change source path and run the script V3.8.0_to_V3.9.0_Replacement.ps1

  6. Apply other manual step (describe bellow) at the end if all is ok, you can remove the .rej files (during the process they can be useful to resolve build problem)

MANUAL STEPS

FRONT

Warning : A bug exists in 3.9.0 and 3.10.0 that prevents to finish the authentication process and stops all call to the api by staying in the waitLogin function of the http interceptor. It happens in very specific cases where a call to the backend that needs a re-authentication (first call or needing token refresh) is cancelled for a reason or another (launching the same http request twice before the first is finished for example). To prevent this bug you can modify the token.interceptor.ts this way :

Replace login and waitLogin functions like this :

  protected login(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
this.isRefreshing = true;
this.authService.logout();
console.info('Login start from interceptor.');
const obs$: Observable<HttpEvent<any>> = this.authService.login().pipe(
switchMap((authInfo: AuthInfo) => {
console.info('Login end from interceptor.');
this.isRefreshing = false;
return next.handle(this.addToken(request, authInfo.token));
}),
finalize(() => {
// Requests can be canceled while login is ongoing.
// If it happens, we must set the information that the refresh is over to
// either let another request refresh the token
// or inform that this request has correctly refreshed the token despite the cancelling
if (this.isRefreshing) {
this.isRefreshing = false;
console.info('Login end from interceptor from finalize.');
}
})
);

if (this.appSettingsService.appSettings?.keycloak?.isActive === true) {
return from(this.keycloakService.isLoggedIn()).pipe(
filter(x => x === true),
switchMap(() => obs$)
);
} else {
return obs$;
}
}

protected waitLogin(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
return this.authService.authInfo$.pipe(
filter(authInfo => authInfo.token !== ''),
take(1),
switchMap(authInfo => {
return next.handle(
this.addToken(request, authInfo ? authInfo.token : '')
);
})
);
}

The correction is included in 4.0.0 and higher versions.

  1. If you don't use the Offline mode, disable the serviceWorker in the angular.json file : "serviceWorker": false

  2. Add selector on all component.

  • search in the Angular folder
@Component({
templateUrl:
  • add the selector (like on index file for item: just replace index by item) ex for plane item:
@Component({
selector: 'app-planes-item',
templateUrl: ...
  1. The boolean field of the hasFilter method of the TableHelperService class has been removed. deleted it if you used this method: this.tableHelperService.hasFilter(this.biaTableComponent, true)

  2. Search this.setPermissions() in all *index.component.ts. if this.setPermissions() is not in a authInfo$.subscribe, add it.

this.sub.add(
this.authService.authInfo$.subscribe((authInfo: AuthInfo) => {
if (authInfo && authInfo.token !== '') {
this.setPermissions();
}
})
);
  1. Run the cmd npm install then npm run clean. Fix all error lint

  2. Due to a breaking change in front with Numeric value, if you have decimal number to display in some crud Table or Forms, you should configure the displayFormat in the model > const FieldsConfiguration. Exemple:

    Object.assign(
new BiaFieldConfig('totalFlightHours', 'plane.totalFlightHours'),
{
isRequired: true,
type: PropType.Number,
filterMode: PrimeNGFiltering.Equals,
displayFormat: Object.assign(new BiaFieldNumberFormat(), {
mode: NumberMode.Decimal,
minFractionDigits: 6,
maxFractionDigits: 6,
}),
validators: [Validators.required, Validators.min(0)],
}
),
  1. Replace the code of the launchRequest method of the class Angular\src\app\core\bia-core\interceptors\ token.interceptor.ts by:
protected launchRequest(request: HttpRequest<any>, next: HttpHandler) {
if (this.authService.shouldRefreshToken) {
return this.handle401Error(request, next);
}
const jwtToken = this.authService.getToken();
request = this.addToken(request, jwtToken);

return next.handle(request).pipe(
catchError(error => {
if (
error instanceof HttpErrorResponse &&
(error.status === HttpStatusCode.Unauthorized ||
error.status === HttpStatusCodeCustom.InvalidToken)
) {
return this.handle401Error(request, next);
} else {
return throwError(() => error);
}
})
);
}

BACK

  1. There may be a difference in the namespace for the new classes regarding the first letter (lowercase, uppercase). For example, MyCompany.eSuitePortal instead of MyCompany.ESuitePortal. You can see this in one of the new classes like Domain.UserModule.Aggregate.TTeamMapper. If there is a difference, rename the namespaces of the new classes to match the project's namespaces.
  2. The migration script removes catch in controllers. Delete the try in error which no longer has a catch.
  3. Mapper injectable: UserContext should be injected (and no more pass from service) If you have mapper that need UserContext you have to injected it in the constructor (ex from RoleOptionMapper):
        /// <summary>
/// Initializes a new instance of the <see cref="RoleOptionMapper"/> class.
/// </summary>
/// <param name="userContext">the user context</param>
public RoleOptionMapper(UserContext userContext)
{
this.UserContext = userContext;
}

/// <summary>
/// The user context language and culture.
/// </summary>
private UserContext UserContext { get; set; }

And you can remove it from the service that use it:

      /// <summary>
/// Initializes a new instance of the <see cref="RoleAppService"/> class.
/// </summary>
/// <param name="repository">The repository.</param>
/// <param name="userContext">The user context.</param>
-- public RoleAppService(ITGenericRepository<Role, int> repository, UserContext userContext)
++ public RoleAppService(ITGenericRepository<Role, int> repository)
: base(repository)
{
-- this.userContext = userContext;
}
  1. With VSCode, Enable search with Regular Expression and fill the search form like this: Search: FirstName \+([\s\S]*)LastName Replace: LastName +$1FirstName files to include: *Mapper.cs And click on Replace All

  2. Search LastName in all mapper in EntityToDto function use user.Display() instead of user.LastName + " " + user.FirstName + " (" + user.Login + ")" And user.DisplayShort() instead of user.LastName + " " + user.FirstName

  3. Finalize the replacement in all files BUT: Ensure that it is an display related to a user before apply the change: Search: ([^\s-]*)FirstName \+ " " \+ ([^\s-]*)LastName Replace: $2LastName + " " + $1FirstName

  4. HandlerRepository change Constructor base parameter: For classes that inherit of DatabaseHandlerRepository change the constructor base parameters 2 and 3 from string to SqlCommand. ex :

        public PlaneHandlerRepository(IConfiguration configuration)
: base(
configuration.GetConnectionString("BIADemoDatabase"),
-- "SELECT RowVersion FROM [dbo].[Planes]",
++ new SqlCommand("SELECT RowVersion FROM [dbo].[Planes]"),
-- "SELECT TOP (1) [SiteId] FROM [dbo].[Planes] ORDER BY [RowVersion] DESC",
++ new SqlCommand("SELECT TOP (1) [SiteId] FROM [dbo].[Planes] ORDER BY [RowVersion] DESC"),
r => PlaneChange(r))
{
}
  1. In Crosscutting.Ioc.IocContainer.ConfigureApplicationContainer, If you have this line of code twice, delete the one that is not contained in the if (isApi)
collection.AddTransient<IAuthAppService, AuthAppService>(); // To remove
...
if (isApi)
{
collection.AddTransient<IAuthAppService, AuthAppService>();
}
  1. If you used SortField of LazyLoadDto class on the BackEnd side, replace it with MultiSortMeta
  2. To fix the null display bug after adding a member : In your UserAppService.cs replace (2 occurences)
Display = entity.FirstName + " " + entity.LastName + " (" + entity.Login + ")",

by

Display = entity.LastName + " " + entity.FirstName + " (" + entity.Login + ")",

And in your UserFromDirectoryMapper.cs replace :

DisplayName = entity.FirstName + " " + entity.LastName + "(" + entity.Domain + "\\" + entity.Login + ")",

by

DisplayName = entity.LastName + " " + entity.FirstName + "(" + entity.Domain + "\\" + entity.Login + ")",

BUILD

  1. Based on the BIADemo-V3.9.0 (With BIACompanyFiles) example, add the ng lint task and redo the ng build prod task using a command line task and no longer an npm task.

  2. Use Visual Studio 2022, change in task:

  • Build solution > Visual Studio Version Visual Studio 2022
  1. Change the path (net6.0 => net 8.0) in the task:
  • API Tests > Test files
**\$(BuildConfiguration)\net8.0\*$(ProjectName).*.Test.dll
!**\obj\**
  • Copy Files Presentation Api > Source Folder
DotNet/$(CompanyName).$(ProjectName).Presentation.Api/bin/$(BuildConfiguration)/net8.0
  • Copy Files Worker service > Source Folder
DotNet/$(CompanyName).$(ProjectName).WorkerService/bin/$(BuildConfiguration)/net8.0
  • Copy Files DeployDB
DotNet/$(CompanyName).$(ProjectName).DeployDB/bin/$(BuildConfiguration)/net8.0

DEPLOY

The dev environment is now deployed on int server but with e separate url. 1- in variable local remove : -ConnectionStrings.BIADemoDatabase -all RootWebSite

2- in variable groups: add :

  • V2-DEV Servers
  • V3-DEV DB LAN change the scope of
  • V2-INT Servers
  • V3-INT DB LAN

-------------------------------Added the 20/08/2024-------------------------------- 3- in task PRA/DeployService set AutomaticStartup to false 4- disable task PRA/End Deploy - Service