Base solution for your next web application

Activities of "quantavn"

I'm trying upgrading my solution (ASP.NET Core + Angular) from v10.2.0 to v10.3.0 but I observed that the 'service-proxies.ts' file is generated in a different way than before.

Here is the comparison of generated source code of AuditLogServiceProxy.getAuditLogs() method:

As you can see, one of the parameters, userName is generated from nullable to un-nullable and it will throw new Error("The parameter 'endDate' cannot be null.") I wonder if there is any way to prevent this behavior, because it makes most of my business logic goes wrong after upgrading.

Here is the full source code of AuditLogServiceProxy.getAuditLogs() method: Before:

    /**
     * @param startDate (optional) 
     * @param endDate (optional) 
     * @param userName (optional) 
     * @param serviceName (optional) 
     * @param methodName (optional) 
     * @param browserInfo (optional) 
     * @param hasException (optional) 
     * @param minExecutionDuration (optional) 
     * @param maxExecutionDuration (optional) 
     * @param sorting (optional) 
     * @param maxResultCount (optional) 
     * @param skipCount (optional) 
     * @return Success
     */
    getAuditLogs(startDate: DateTime | undefined, endDate: DateTime | undefined, userName: string | null | undefined, serviceName: string | null | undefined, methodName: string | null | undefined, browserInfo: string | null | undefined, hasException: boolean | null | undefined, minExecutionDuration: number | null | undefined, maxExecutionDuration: number | null | undefined, sorting: string | null | undefined, maxResultCount: number | undefined, skipCount: number | undefined): Observable<PagedResultDtoOfAuditLogListDto> {
        let url_ = this.baseUrl + "/api/services/app/AuditLog/GetAuditLogs?";
        if (startDate === null)
            throw new Error("The parameter 'startDate' cannot be null.");
        else if (startDate !== undefined)
            url_ += "StartDate=" + encodeURIComponent(startDate ? "" + startDate.toJSON() : "") + "&";
        if (endDate === null)
            throw new Error("The parameter 'endDate' cannot be null.");
        else if (endDate !== undefined)
            url_ += "EndDate=" + encodeURIComponent(endDate ? "" + endDate.toJSON() : "") + "&";
        if (userName !== undefined && userName !== null)
            url_ += "UserName=" + encodeURIComponent("" + userName) + "&";
        if (serviceName !== undefined && serviceName !== null)
            url_ += "ServiceName=" + encodeURIComponent("" + serviceName) + "&";
        if (methodName !== undefined && methodName !== null)
            url_ += "MethodName=" + encodeURIComponent("" + methodName) + "&";
        if (browserInfo !== undefined && browserInfo !== null)
            url_ += "BrowserInfo=" + encodeURIComponent("" + browserInfo) + "&";
        if (hasException !== undefined && hasException !== null)
            url_ += "HasException=" + encodeURIComponent("" + hasException) + "&";
        if (minExecutionDuration !== undefined && minExecutionDuration !== null)
            url_ += "MinExecutionDuration=" + encodeURIComponent("" + minExecutionDuration) + "&";
        if (maxExecutionDuration !== undefined && maxExecutionDuration !== null)
            url_ += "MaxExecutionDuration=" + encodeURIComponent("" + maxExecutionDuration) + "&";
        if (sorting !== undefined && sorting !== null)
            url_ += "Sorting=" + encodeURIComponent("" + sorting) + "&";
        if (maxResultCount === null)
            throw new Error("The parameter 'maxResultCount' cannot be null.");
        else if (maxResultCount !== undefined)
            url_ += "MaxResultCount=" + encodeURIComponent("" + maxResultCount) + "&";
        if (skipCount === null)
            throw new Error("The parameter 'skipCount' cannot be null.");
        else if (skipCount !== undefined)
            url_ += "SkipCount=" + encodeURIComponent("" + skipCount) + "&";
        url_ = url_.replace(/[?&]$/, "");

        let options_ : any = {
            observe: "response",
            responseType: "blob",
            headers: new HttpHeaders({
                "Accept": "text/plain"
            })
        };

        return this.http.request("get", url_, options_).pipe(_observableMergeMap((response_ : any) => {
            return this.processGetAuditLogs(response_);
        })).pipe(_observableCatch((response_: any) => {
            if (response_ instanceof HttpResponseBase) {
                try {
                    return this.processGetAuditLogs(<any>response_);
                } catch (e) {
                    return <Observable<PagedResultDtoOfAuditLogListDto>><any>_observableThrow(e);
                }
            } else
                return <Observable<PagedResultDtoOfAuditLogListDto>><any>_observableThrow(response_);
        }));
    }

After:

    /**
     * @param startDate (optional) 
     * @param endDate (optional) 
     * @param userName (optional) 
     * @param serviceName (optional) 
     * @param methodName (optional) 
     * @param browserInfo (optional) 
     * @param hasException (optional) 
     * @param minExecutionDuration (optional) 
     * @param maxExecutionDuration (optional) 
     * @param sorting (optional) 
     * @param maxResultCount (optional) 
     * @param skipCount (optional) 
     * @return Success
     */
    getAuditLogs(startDate: DateTime | undefined, endDate: DateTime | undefined, userName: string | undefined, serviceName: string | undefined, methodName: string | undefined, browserInfo: string | undefined, hasException: boolean | undefined, minExecutionDuration: number | undefined, maxExecutionDuration: number | undefined, sorting: string | undefined, maxResultCount: number | undefined, skipCount: number | undefined): Observable<PagedResultDtoOfAuditLogListDto> {
        let url_ = this.baseUrl + "/api/services/app/AuditLog/GetAuditLogs?";
        if (startDate === null)
            throw new Error("The parameter 'startDate' cannot be null.");
        else if (startDate !== undefined)
            url_ += "StartDate=" + encodeURIComponent(startDate ? "" + startDate.toJSON() : "") + "&";
        if (endDate === null)
            throw new Error("The parameter 'endDate' cannot be null.");
        else if (endDate !== undefined)
            url_ += "EndDate=" + encodeURIComponent(endDate ? "" + endDate.toJSON() : "") + "&";
        if (userName === null)
            throw new Error("The parameter 'userName' cannot be null.");
        else if (userName !== undefined)
            url_ += "UserName=" + encodeURIComponent("" + userName) + "&";
        if (serviceName === null)
            throw new Error("The parameter 'serviceName' cannot be null.");
        else if (serviceName !== undefined)
            url_ += "ServiceName=" + encodeURIComponent("" + serviceName) + "&";
        if (methodName === null)
            throw new Error("The parameter 'methodName' cannot be null.");
        else if (methodName !== undefined)
            url_ += "MethodName=" + encodeURIComponent("" + methodName) + "&";
        if (browserInfo === null)
            throw new Error("The parameter 'browserInfo' cannot be null.");
        else if (browserInfo !== undefined)
            url_ += "BrowserInfo=" + encodeURIComponent("" + browserInfo) + "&";
        if (hasException === null)
            throw new Error("The parameter 'hasException' cannot be null.");
        else if (hasException !== undefined)
            url_ += "HasException=" + encodeURIComponent("" + hasException) + "&";
        if (minExecutionDuration === null)
            throw new Error("The parameter 'minExecutionDuration' cannot be null.");
        else if (minExecutionDuration !== undefined)
            url_ += "MinExecutionDuration=" + encodeURIComponent("" + minExecutionDuration) + "&";
        if (maxExecutionDuration === null)
            throw new Error("The parameter 'maxExecutionDuration' cannot be null.");
        else if (maxExecutionDuration !== undefined)
            url_ += "MaxExecutionDuration=" + encodeURIComponent("" + maxExecutionDuration) + "&";
        if (sorting === null)
            throw new Error("The parameter 'sorting' cannot be null.");
        else if (sorting !== undefined)
            url_ += "Sorting=" + encodeURIComponent("" + sorting) + "&";
        if (maxResultCount === null)
            throw new Error("The parameter 'maxResultCount' cannot be null.");
        else if (maxResultCount !== undefined)
            url_ += "MaxResultCount=" + encodeURIComponent("" + maxResultCount) + "&";
        if (skipCount === null)
            throw new Error("The parameter 'skipCount' cannot be null.");
        else if (skipCount !== undefined)
            url_ += "SkipCount=" + encodeURIComponent("" + skipCount) + "&";
        url_ = url_.replace(/[?&]$/, "");

        let options_ : any = {
            observe: "response",
            responseType: "blob",
            headers: new HttpHeaders({
                "Accept": "text/plain"
            })
        };

        return this.http.request("get", url_, options_).pipe(_observableMergeMap((response_ : any) => {
            return this.processGetAuditLogs(response_);
        })).pipe(_observableCatch((response_: any) => {
            if (response_ instanceof HttpResponseBase) {
                try {
                    return this.processGetAuditLogs(<any>response_);
                } catch (e) {
                    return <Observable<PagedResultDtoOfAuditLogListDto>><any>_observableThrow(e);
                }
            } else
                return <Observable<PagedResultDtoOfAuditLogListDto>><any>_observableThrow(response_);
        }));
    }

We have a plan to upgrade to the new version too, looking forward to the solution from ANZ team!

I've solved the issue temporarily by:

  1. Adding Application Settings WEBSITE_TIME_ZONE to the Web Host's App Service
  2. Use Clock.Provider = ClockProviders.Local;

It's better if we check deeper to know why not using Clock.Provider = ClockProviders.Utc the time is still normalized.

Hi @ismcagdas,

In List view, I'm using this momentFormat:'HH:mm'

I've just update to not use ClockProvider.Utc, I still got this strange issue: In CreateOrEdit view, input 15:30 ~ 16:00: Then in List view, it displays as : Open CreateOrEdit view again: In Server: In DB:

Wonder if it is related to this or not:

UPDATE: Try to udpate the date to September, the issue still occurs: In CreateOrEdit: In Server: Then in List: In DB:

UPDATE 2: In Client, CreateOrEdit component: In Client, ProxyService:

UPDATE 3: After deploying to Azure, the time is input as 15:30 but inserted into DB as 05:30 (PC's timezone: UTC+10:00)

Hi @ismcagdas,

About #1, I've tried several options when deploying to Azure:

  1. First, don't use either ClockProvider or DisableDateTimeNormalization:
    1. In CreateOrEdit view: input a date with value the '15:30'
    2. In List view: the date is display as '08:30'
  2. Use ClockProvider.Local and DisableDateTimeNormalization:
    1. It displays well in both views (CreateOrEdit and List) in my laptop (Vietnam, Hanoi timezone) with the value '15:30'
    2. But in my partner laptop (another TimeZone, Sydney), it displays as '08:30' in both views
  3. Use ClockProvider.Utc and DisableDateTimeNormalization (the same result as the 1st option)
    1. In CreateOrEdit view: input a date with value the '15:30'
    2. In List view: the date is display as '08:30'

About #2, here is the string I got from my laptop when using Option 3:

  1. Client: The string content at service-proxies.ts after using JSON.stringify(body)
  2. Server:
  3. DB (MS SQL Server):

What I want is: the value '15:30' is displayed in both views (CreateOrEdit and List), at any TimeZone.

I got a strange error related to this issue, don't know where and how to investigate. Hope DEV team can help! It works as usual at LOCALHOST (Vietnam time GMT+7) when developing but the DateTime is substract by 7 hours (-7 hours) when deploying to Azure (location: Southeast Asia). I've tried using DisableDateTimeNormalization (applied to the CreateOrEdit DTOs) but it did not work (there's no differences before and after changed).

We are trying migrating our project (ANZ v7.2.0 - ASP.NET Core + Angular) from MS SQL Server to Oracle 11g but we got this error when running "Update-Database":

PM> update-database --verbose
Applying migration '20170406083347_Initial_Migration'.
2020-07-27 23:02:16.447396 ThreadID:1   (ERROR)   OracleRelationalCommand.Execute() :  Oracle.ManagedDataAccess.Client.OracleException (0x80004005): ORA-00972: identifier is too long
ORA-06512: at line 2
   at OracleInternal.ServiceObjects.OracleConnectionImpl.VerifyExecution(Int32& cursorId, Boolean bThrowArrayBindRelatedErrors, SqlStatementType sqlStatementType, Int32 arrayBindCount, OracleException& exceptionForArrayBindDML, Boolean& hasMoreRowsInDB, Boolean bFirstIterationDone)
   at OracleInternal.ServiceObjects.OracleCommandImpl.ExecuteNonQuery(String commandText, OracleParameterCollection paramColl, CommandType commandType, OracleConnectionImpl connectionImpl, Int32 longFetchSize, Int64 clientInitialLOBFS, OracleDependencyImpl orclDependencyImpl, Int64[]& scnFromExecution, OracleParameterCollection& bindByPositionParamColl, Boolean& bBindParamPresent, OracleException& exceptionForArrayBindDML, OracleConnection connection, OracleLogicalTransaction& oracleLogicalTransaction, Boolean isFromEF)
   at Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteNonQuery()
   at Oracle.EntityFrameworkCore.Storage.Internal.OracleRelationalCommandBuilderFactory.OracleRelationalCommandBuilder.OracleRelationalCommand.Execute(IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary`2 parameterValues)
Failed executing DbCommand (38ms) [Parameters=[], CommandType='Text', CommandTimeout='0']
BEGIN 
EXECUTE IMMEDIATE 'CREATE TABLE 
"AbpNotifications" (
    "Id" RAW(16) NOT NULL,
    "CreationTime" TIMESTAMP(7) NOT NULL,
    "CreatorUserId" NUMBER(19),
    "Data" NCLOB,
    "DataTypeName" NVARCHAR2(512),
    "EntityId" NVARCHAR2(96),
    "EntityTypeAssemblyQualifiedName" NVARCHAR2(512),
    "EntityTypeName" NVARCHAR2(250),
    "ExcludedUserIds" NCLOB,
    "NotificationName" NVARCHAR2(96) NOT NULL,
    "Severity" NUMBER(3) NOT NULL,
    "TenantIds" NCLOB,
    "UserIds" NCLOB,
    CONSTRAINT "PK_AbpNotifications" PRIMARY KEY ("Id")
)';
END;

After investigating, we found the problem is because the column name is too long (EntityTypeAssemblyQualifiedName: 31 vs the limitation of Oracle 11g is 30).

Is there any suggestion to solve this issue? I know this limitation is solve from Oracle 12c but we must use Oracle 11g (even older versions as well).

Hi @bobingham,

Can you share me your email, I have some information need to discuss with you in private? Here is my email: [email protected]

To whom it may concern, I've solved this problem by 02 options: Option 1: UserAppService.cs: users.component.html:

<td style="width: 150px">
    <span class="ui-column-title"> {{'UserName' | localize}}</span>
    <div class="kt-user-card-v2">
        <div class="kt-user-card-v2__pic">
            <img *ngIf="!record.profilePictureId" src="./assets/common/images/default-profile-picture.png" alt="pic" />
            <img *ngIf="record.profilePictureId" [src]="record.profilePicture" alt="pic" />
        </div>
        <div class="kt-user-card-v2__details">
            <span class="kt-user-card-v2__name">{{record.userName}}</span>
        </div>
    </div>
</td>

Option 2: ProfileController.cs:

[AllowAnonymous]
public async Task<ActionResult> GetProfilePicture(Guid profilePictureId)
{
    var defaultProfilePicture = "/Common/Images/SampleProfilePics/sample-profile-01.jpg";
    var file = await _binaryObjectManager.GetOrNullAsync(profilePictureId);
    if (file == null)
    {
        return File(defaultProfilePicture, MimeTypeNames.ImageJpeg);
    }

    return File(file.Bytes, MimeTypeNames.ImageJpeg);
}

users.component.html:

<td style="width: 150px">
    <span class="ui-column-title"> {{'UserName' | localize}}</span>
    <div class="kt-user-card-v2">
        <div class="kt-user-card-v2__pic">
            <img *ngIf="!record.profilePictureId" src="./assets/common/images/default-profile-picture.png" alt="pic" />
            <img *ngIf="record.profilePictureId" [src]="remoteServiceBaseUrl + '/Profile/GetProfilePicture?profilePictureId=' + record.profilePictureId" alt="pic" />
        </div>
        <div class="kt-user-card-v2__details">
            <span class="kt-user-card-v2__name">{{record.userName}}</span>
        </div>
    </div>
</td>
<td style="width: 150px">

No, there's no javascript error. The request is keeping generated and my CPU is 100% then I need to close Google Chrome.

Showing 1 to 10 of 24 entries