C# microservice is not working

Product/components used and version/fix level:

Product - Cumulocity IoT, Custom dashboard app version - “@c8y/client”: “1018.503.118”,

Detailed explanation of the problem:

We developed a microservice for role synchronization by extending the LoginService in Angular. Recently, we upgraded the application to a new version. Since then, we have been receiving a 401 response to the microservice call, and there is no indication in the logs that the request is being received in microservice log.

There is no change in c# microservice after update
What is possible quick fix for this issue?

Error messages / full error message screenshot / log file:

401 Status code to microservice request

Question related to a free trial, or to a production (customer) instance?

Customer - Production

Hi @kiranpokharkar,

From what I’ve got, you have:

  1. developed a microservice in c#
  2. built an angular UI based on the Cumulocity Web SDK
  3. extended the LoginService of the angular app
  4. Upgraded to Cumulocity Web SDK version 1018.503.118

If everything worked until step 3 and stopped working after step 4, the obvious quick fix could be to revert your last change (the Web SDK upgrade).

For any further assistance it would help to know from which version you’ve upgraded and how your extension of the LoginService looks like.

Regards,
Tristan

We updated from Angular 12 to Angular 15 version 1018.157.0
We updated to this version as recommend by cumulocity team to resolve some issues, and got fixed
Revert the update is not option for us

LoginService

import { LocationStrategy } from '@angular/common'
import { Injectable, Injector } from '@angular/core'
import {
  IAuthentication,
  ICredentials,
  IUserInventoryRole,
  IFetchOptions,
} from '@c8y/client'
import {
  AlertService,
  AppStateService,
  LoginService,
  TenantUiService  
} from '@c8y/ngx-components'
import { ApiService, BasicAuth, CookieAuth, FetchClient, Realtime, TenantLoginOptionsService, TenantService, UserService } from '@c8y/ngx-components/api'
import { TranslateService } from '@ngx-translate/core'
import * as _ from 'lodash'

@Injectable({
  providedIn: 'root',
})
export class CustomLoginService extends LoginService {
  static ROLE_SYNCHRONIZED: string = 'roleSynchronized'

  constructor(
    injector : Injector,
    client : FetchClient,
    basicauth : BasicAuth,
    cookieAuth: CookieAuth,
    public app: AppStateService,
    public userService: UserService,
    tenant: TenantService,
    realtime: Realtime,
    public alertService: AlertService,
    api: ApiService,
    tenantUiService : TenantUiService,
    tenantLoginOptionsService : TenantLoginOptionsService,
    translateService : TranslateService,
    location: LocationStrategy,
  ) {
    super(
      injector,
      client,
      basicauth,
      cookieAuth,
      app,
      userService,
      tenant,
      realtime,
      alertService,
      api,
      tenantUiService,
      tenantLoginOptionsService,
      translateService,
      location,
    )
  }

  async login(
    auth?: IAuthentication,
    credentials?: ICredentials,
  ): Promise<void> {
    await super.login(auth, credentials)

    try {
      const currentUser = this.app.currentUser.value
      const currentTenant = this.app.currentTenant.value
      if (currentUser) {
        let userDetails = {
          username: currentUser.userName,
          tenantId: currentTenant.name,
        }
        const options: IFetchOptions = {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(userDetails),
        }
        //Calling microserve
        let url = `service/blim-ms-role-sync/sync`
        this.createHttpRequest(url, options);
      }
    }
    catch {
      //TODO: Remove this log.
      console.log("Unable to sync role.")
    }
  }
  createHttpRequest(url: string, options: IFetchOptions): Promise<Response> {
    const client = new FetchClient();
    return client.fetch(url, options);
  }
}

Deprecation of the Microservice SDK for C#?

I’m not sure if this ever worked beforehand, but creating a new instance of the FetchClient without providing an authentication strategy will probably lead to issues.

Can you try using this instead?

import { LocationStrategy } from '@angular/common';
import { Injectable, Injector } from '@angular/core';
import { IAuthentication, ICredentials, IUserInventoryRole, IFetchOptions } from '@c8y/client';
import { AlertService, AppStateService, LoginService, TenantUiService } from '@c8y/ngx-components';
import {
  ApiService,
  BasicAuth,
  CookieAuth,
  FetchClient,
  Realtime,
  TenantLoginOptionsService,
  TenantService,
  UserService
} from '@c8y/ngx-components/api';
import { TranslateService } from '@ngx-translate/core';
import * as _ from 'lodash';

@Injectable({
  providedIn: 'root'
})
export class CustomLoginService extends LoginService {
  static ROLE_SYNCHRONIZED: string = 'roleSynchronized';

  constructor(
    injector: Injector,
    private fetchClient: FetchClient,
    basicauth: BasicAuth,
    cookieAuth: CookieAuth,
    public app: AppStateService,
    public userService: UserService,
    tenant: TenantService,
    realtime: Realtime,
    public alertService: AlertService,
    api: ApiService,
    tenantUiService: TenantUiService,
    tenantLoginOptionsService: TenantLoginOptionsService,
    translateService: TranslateService,
    location: LocationStrategy
  ) {
    super(
      injector,
      fetchClient,
      basicauth,
      cookieAuth,
      app,
      userService,
      tenant,
      realtime,
      alertService,
      api,
      tenantUiService,
      tenantLoginOptionsService,
      translateService,
      location
    );
  }

  async login(auth?: IAuthentication, credentials?: ICredentials): Promise<void> {
    await super.login(auth, credentials);

    try {
      const currentUser = this.app.currentUser.value;
      const currentTenant = this.app.currentTenant.value;
      if (currentUser) {
        let userDetails = {
          username: currentUser.userName,
          tenantId: currentTenant.name
        };
        const options: IFetchOptions = {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(userDetails)
        };
        //Calling microserve
        let url = `service/blim-ms-role-sync/sync`;
        await this.fetchClient.fetch(url, options);
      }
    } catch {
      //TODO: Remove this log.
      console.log('Unable to sync role.');
    }
  }
}

It uses the same FetchClient instance the LoginService would use instead of creating a new one.

Regards,
Tristan

1 Like

This is exacly am using in the previous version(before updated), I used FetchClient same object as it was public in the constructor (DI), allowing us to use it in the login function. However, in Angular 15 version 1018.157.0, FetchClient is now private, preventing us from using it in the login service. As a result, I had to create a new object. Refer to the my code

Error Message whrn i try to declare it as public

Class ‘CustomLoginService’ incorrectly extends base class ‘LoginService’.
Property ‘client’ is private in type ‘LoginService’ but not in type ‘CustomLoginService’.ts(2415)

If you copy the code from above you should not have any issue as I named the property fetchClient instead if client.