question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Typescript optional parameter null check

See original GitHub issue

Hi,

I’m using nswag 11.12.7 and I have a generated typescript method like this:

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

        let options_ : any = {
            method: "get",
            headers: new Headers({
                "Content-Type": "application/json", 
                "Accept": "application/json"
            })
        };

        return this.http.request(url_, options_).flatMap((response_ : any) => {
            return this.processGetAuditLogs(response_);
        }).catch((response_: any) => {
            if (response_ instanceof Response) {
                try {
                    return this.processGetAuditLogs(response_);
                } catch (e) {
                    return <Observable<PagedResultDtoOfAuditLogListDto>><any>Observable.throw(e);
                }
            } else
                return <Observable<PagedResultDtoOfAuditLogListDto>><any>Observable.throw(response_);
        });
    }

My problem is, when the optional integer parameter MinExecutionDuration or MaxExecutionDuration is null, it is added to query string for the request, so I get a get request like this:

http://localhost:8080/api/services/app/AuditLog/GetAuditLogs?...&MinExecutionDuration=null&

ASP.NET Core tries to convert null value to an integer and throws an exception.

So, my question is, is there any way not to add null values to query string for optional integer parameters ?

Thanks.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:13 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
ismcagdascommented, May 5, 2022

It was a long time and I don’t remember what we changed to solve this problem but I can share our latest service.config.nswag file, so you can compare it with your version.

{
  "runtime": "Default",
  "defaultVariables": null,
  "documentGenerator": {
    "fromDocument": {
      "url": "https://localhost:44301/swagger/v1/swagger.json",
      "output": null
    }
  },
  "codeGenerators": {
    "openApiToTypeScriptClient": {
      "className": "{controller}ServiceProxy",
      "moduleName": "",
      "namespace": "",
      "typeScriptVersion": 2.7,
      "template": "Angular",
      "promiseType": "Promise",
      "httpClass": "HttpClient",
      "useSingletonProvider": false,
      "injectionTokenType": "InjectionToken",
      "rxJsVersion": 6.0,
      "dateTimeType": "Luxon",
      "nullValue": "Undefined",
      "generateClientClasses": true,
      "generateClientInterfaces": false,
      "generateOptionalParameters": false,
      "exportTypes": true,
      "wrapDtoExceptions": false,
      "exceptionClass": "ApiException",
      "clientBaseClass": null,
      "wrapResponses": false,
      "wrapResponseMethods": [],
      "generateResponseClasses": true,
      "responseClass": "SwaggerResponse",
      "protectedMethods": [],
      "configurationClass": null,
      "useTransformOptionsMethod": false,
      "useTransformResultMethod": false,
      "generateDtoTypes": true,
      "operationGenerationMode": "MultipleClientsFromPathSegments",
      "markOptionalProperties": false,
      "generateCloneMethod": false,
      "typeStyle": "Class",
      "classTypes": [],
      "extendedClasses": [],
      "extensionCode": "service.extensions.ts",
      "generateDefaultValues": true,
      "excludedTypeNames": [],
      "excludedParameterNames": [],
      "handleReferences": false,
      "generateConstructorInterface": true,
      "convertConstructorInterfaceData": false,
      "importRequiredTypes": true,
      "useGetBaseUrlMethod": false,
      "baseUrlTokenName": "API_BASE_URL",
      "queryNullValue": "",
      "inlineNamedDictionaries": false,
      "inlineNamedAny": false,
      "templateDirectory": null,
      "typeNameGeneratorType": null,
      "propertyNameGeneratorType": null,
      "enumNameGeneratorType": null,
      "serviceHost": null,
      "serviceSchemes": null,
      "output": "../src/shared/service-proxies/service-proxies.ts"
    },
    "openApiToCSharpClient": {
      "clientBaseClass": null,
      "configurationClass": null,
      "generateClientClasses": true,
      "generateClientInterfaces": false,
      "injectHttpClient": false,
      "disposeHttpClient": true,
      "protectedMethods": [],
      "generateExceptionClasses": true,
      "exceptionClass": "SwaggerException",
      "wrapDtoExceptions": true,
      "useHttpClientCreationMethod": false,
      "httpClientType": "System.Net.Http.HttpClient",
      "useHttpRequestMessageCreationMethod": false,
      "useBaseUrl": true,
      "generateBaseUrlProperty": true,
      "generateSyncMethods": false,
      "exposeJsonSerializerSettings": false,
      "clientClassAccessModifier": "public",
      "typeAccessModifier": "public",
      "generateContractsOutput": false,
      "contractsNamespace": null,
      "contractsOutputFilePath": null,
      "parameterDateTimeFormat": "s",
      "generateUpdateJsonSerializerSettingsMethod": true,
      "serializeTypeInformation": false,
      "queryNullValue": "",
      "className": "{controller}Client",
      "operationGenerationMode": "MultipleClientsFromOperationId",
      "additionalNamespaceUsages": [],
      "additionalContractNamespaceUsages": [],
      "generateOptionalParameters": false,
      "generateJsonMethods": true,
      "enforceFlagEnums": false,
      "parameterArrayType": "System.Collections.Generic.IEnumerable",
      "parameterDictionaryType": "System.Collections.Generic.IDictionary",
      "responseArrayType": "System.Collections.ObjectModel.ObservableCollection",
      "responseDictionaryType": "System.Collections.Generic.Dictionary",
      "wrapResponses": false,
      "wrapResponseMethods": [],
      "generateResponseClasses": true,
      "responseClass": "SwaggerResponse",
      "namespace": "MyNamespace",
      "requiredPropertiesMustBeDefined": true,
      "dateType": "System.DateTime",
      "jsonConverters": null,
      "anyType": "object",
      "dateTimeType": "System.DateTime",
      "timeType": "System.TimeSpan",
      "timeSpanType": "System.TimeSpan",
      "arrayType": "System.Collections.ObjectModel.ObservableCollection",
      "arrayInstanceType": "System.Collections.ObjectModel.Collection",
      "dictionaryType": "System.Collections.Generic.Dictionary",
      "dictionaryInstanceType": "System.Collections.Generic.Dictionary",
      "arrayBaseType": "System.Collections.ObjectModel.ObservableCollection",
      "dictionaryBaseType": "System.Collections.Generic.Dictionary",
      "classStyle": "Inpc",
      "generateDefaultValues": true,
      "generateDataAnnotations": true,
      "excludedTypeNames": [],
      "excludedParameterNames": [],
      "handleReferences": false,
      "generateImmutableArrayProperties": false,
      "generateImmutableDictionaryProperties": false,
      "jsonSerializerSettingsTransformationMethod": null,
      "inlineNamedArrays": false,
      "inlineNamedDictionaries": false,
      "inlineNamedTuples": true,
      "inlineNamedAny": false,
      "generateDtoTypes": true,
      "generateOptionalPropertiesAsNullable": false,
      "templateDirectory": null,
      "typeNameGeneratorType": null,
      "propertyNameGeneratorType": null,
      "enumNameGeneratorType": null,
      "serviceHost": null,
      "serviceSchemes": null,
      "output": null
    },
    "openApiToCSharpController": {
      "controllerBaseClass": null,
      "controllerStyle": "Partial",
      "controllerTarget": "AspNet",
      "useCancellationToken": false,
      "useActionResultType": false,
      "generateModelValidationAttributes": false,
      "routeNamingStrategy": "None",
      "className": "{controller}",
      "operationGenerationMode": "MultipleClientsFromOperationId",
      "additionalNamespaceUsages": [
        "System.Web.Http"
      ],
      "additionalContractNamespaceUsages": [],
      "generateOptionalParameters": false,
      "generateJsonMethods": true,
      "enforceFlagEnums": false,
      "parameterArrayType": "System.Collections.Generic.IEnumerable",
      "parameterDictionaryType": "System.Collections.Generic.IDictionary",
      "responseArrayType": "System.Collections.ObjectModel.ObservableCollection",
      "responseDictionaryType": "System.Collections.Generic.Dictionary",
      "wrapResponses": false,
      "wrapResponseMethods": [],
      "generateResponseClasses": true,
      "responseClass": "SwaggerResponse",
      "namespace": "MyNamespace",
      "requiredPropertiesMustBeDefined": true,
      "dateType": "System.DateTime",
      "jsonConverters": null,
      "anyType": "object",
      "dateTimeType": "System.DateTime",
      "timeType": "System.TimeSpan",
      "timeSpanType": "System.TimeSpan",
      "arrayType": "System.Collections.Generic.IEnumerable",
      "arrayInstanceType": "System.Collections.ObjectModel.Collection",
      "dictionaryType": "System.Collections.Generic.Dictionary",
      "dictionaryInstanceType": "System.Collections.Generic.Dictionary",
      "arrayBaseType": "System.Collections.ObjectModel.ObservableCollection",
      "dictionaryBaseType": "System.Collections.Generic.Dictionary",
      "classStyle": "Inpc",
      "generateDefaultValues": true,
      "generateDataAnnotations": true,
      "excludedTypeNames": [],
      "excludedParameterNames": [],
      "handleReferences": false,
      "generateImmutableArrayProperties": false,
      "generateImmutableDictionaryProperties": false,
      "jsonSerializerSettingsTransformationMethod": null,
      "inlineNamedArrays": false,
      "inlineNamedDictionaries": false,
      "inlineNamedTuples": true,
      "inlineNamedAny": false,
      "generateDtoTypes": true,
      "generateOptionalPropertiesAsNullable": false,
      "templateDirectory": null,
      "typeNameGeneratorType": null,
      "propertyNameGeneratorType": null,
      "enumNameGeneratorType": null,
      "serviceHost": null,
      "serviceSchemes": null,
      "output": null
    }
  }
}
0reactions
zlowe747commented, May 4, 2022

@ismcagdas it’s not a problem with the AspNet Zero project. This addArtifact method is one that we added and for some reason nswag is not recognizing that there are optional parameters when it generates the typescript client. So what I’m wondering is how you fixed the problem with the methods that you wrote so I can do the same thing.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Can an optional parameter be null in TypeScript?
According to this article, when strict null checking is enabled in TypeScript, you cannot assign null or undefined to a variable unless it...
Read more >
Nullable types and optional parameters/properties (TypeScript)
An overview of how TypeScript deals with null, undefined and optional parameters/properties.
Read more >
TypeScript optional, nullable, and default parameters - byby.dev
TypeScript function parameters allow you to define the types of the values that are passed into a function, which helps with type checking...
Read more >
When to use typescript optional "?" parameter vs explicit ...
Typescript “?” operator means that parameter is optional, it's not necessary to pass it in component/function. Undefined means that parameter ...
Read more >
Documentation - TypeScript 2.0
TypeScript has two special types, Null and Undefined, that have the values null and undefined respectively. Previously it was not possible to explicitly...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found