nswag генерирует прокси, который портит URL

Общая идея nswag программного обеспечения потрясающая.

Но ребята его полностью испортили.

Я действительно сейчас думаю о том, чтобы отказаться от него по следующим причинам:

  • чрезмерно сложный

  • проблемный

  • крайне плохо задокументирован

  • непопулярный

По поводу моей версии - "[email protected]".

Моя служба должна передавать составную структуру (например, вложенные массивы), но в последних версиях она передает весь контент через URL-адрес, и вот что я имею в виду:

введите здесь описание изображения

Более того, его последние версии не генерируют входные классы - например, у моего контроллера API есть действие ImportEntries(ImportEntriesInput input)

nswag больше не генерирует входной класс (я имею в виду ImportEntriesInput) - вместо этого он просто перечисляет всех своих членов:

Например сравните

importEntries(input: ImportEntriesInput | null | undefined): Observable<VocabularyDto> {

с участием

importEntries(entries: CrawlerEntryDto[] | null | undefined, vocabularyId: number | undefined, newVocabulary: boolean | undefined, typeId: number | undefined, name: string | null | undefined, notes: string | null | undefined): Observable<VocabularyDto | null> {

Может быть, парни, которые его разрабатывают, сочтут это приемлемым, но я бы сказал, что это полностью усложняет весь подход и очень плохо.

Мне не удалось найти документацию по этой части.

Кто-нибудь знает, как это решить?


Кроме того, вот бит, в котором он создает контент, передаваемый в URL:

importEntries(entries: CrawlerEntryDto[] | null | undefined, vocabularyId: number | undefined, newVocabulary: boolean | undefined, typeId: number | undefined, name: string | null | undefined, notes: string | null | undefined): Observable<VocabularyDto | null> {
    let url_ = this.baseUrl + "/api/Import/ImportEntries?";
    if (entries !== undefined)
        entries && entries.forEach((item, index) => { 
            for (let attr in item)
                url_ += "entries[" + index + "]." + attr + "=" + encodeURIComponent("" + item[attr]) + "&";
        });
    if (vocabularyId === null)
        throw new Error("The parameter 'vocabularyId' cannot be null.");
    else if (vocabularyId !== undefined)
        url_ += "vocabularyId=" + encodeURIComponent("" + vocabularyId) + "&"; 
    if (newVocabulary === null)
        throw new Error("The parameter 'newVocabulary' cannot be null.");
    else if (newVocabulary !== undefined)
        url_ += "newVocabulary=" + encodeURIComponent("" + newVocabulary) + "&"; 
    if (typeId === null)
        throw new Error("The parameter 'typeId' cannot be null.");
    else if (typeId !== undefined)
        url_ += "typeId=" + encodeURIComponent("" + typeId) + "&"; 
    if (name !== undefined)
        url_ += "name=" + encodeURIComponent("" + name) + "&"; 
    if (notes !== undefined)
        url_ += "notes=" + encodeURIComponent("" + notes) + "&"; 
    url_ = url_.replace(/[?&]$/, "");

    let options_ : any = {
        observe: "response",
        responseType: "blob",
        headers: new HttpHeaders({
            "Content-Type": "application/json", 
            "Accept": "application/json",
            'Authorization': 'Bearer ' + localStorage.getItem('token')
        })
    };

    return this.http.request("post", url_, options_).flatMap((response_ : any) => {
        return this.processImportEntries(response_);
    }).catch((response_: any) => {
        if (response_ instanceof HttpResponseBase) {
            try {
                return this.processImportEntries(<any>response_);
            } catch (e) {
                return <Observable<VocabularyDto | null>><any>Observable.throw(e);
            }
        } else
            return <Observable<VocabularyDto | null>><any>Observable.throw(response_);
    });
}

Довольно ужасно, не правда ли?

swaggerToTypeScriptClient бит из конфигурации:

"codeGenerators": {
    "swaggerToTypeScriptClient": {
      "className": "{controller}ServiceProxy",
      "moduleName": "",
      "namespace": "",
      "typeScriptVersion": 2.0,
      "template": "Angular",
      "promiseType": "Promise",
        "httpClass": "HttpClient",
      "dateTimeType": "MomentJS",
      "nullValue": "Undefined",
      "generateClientClasses": true,
      "generateClientInterfaces": false,
      "generateOptionalParameters": false,
      "wrapDtoExceptions": false,
      "wrapResponses": false,
      "generateResponseClasses": true,
      "responseClass": "SwaggerResponse",
      "useTransformOptionsMethod": false,
      "useTransformResultMethod": false,
      "generateDtoTypes": true,
      "operationGenerationMode": "MultipleClientsFromPathSegments"
      "markOptionalProperties": false,
      "generateCloneMethod": true,
      "typeStyle": "Class",
      "extensionCode": "service.extensions.ts",
      "generateDefaultValues": true,
      "excludedTypeNames": [],
      "handleReferences": false,
      "generateConstructorInterface": true,
      "importRequiredTypes": true,
      "useGetBaseUrlMethod": false,
      "baseUrlTokenName": "API_BASE_URL",
      "injectionTokenType": "InjectionToken",
      "output": "../src/shared/service-proxies/service-proxies.ts"
    },

person Alex Herman    schedule 09.07.2018    source источник
comment
Я, вероятно, добавлю это как комментарий - действительно, nswag даже не смог включить дополнительный заголовок для аутентификации JWT, однако я указал это в Startup.cs. new SwaggerSecurityScheme { Type = SwaggerSecuritySchemeType.ApiKey, Name = "Authorization", Description = "Copy 'Bearer ' + localStorage.getItem('token')", In = SwaggerSecurityApiKeyLocation.Header...   -  person Alex Herman    schedule 09.07.2018


Ответы (1)


Это устраняет проблему с URL, упомянутым в моем сообщении выше.

Это не было задокументировано, но для правильной работы nswag с ASP.NET Core вы должны применять атрибут [FromBody] к каждому действию, принимающему данные.

e.g.

public async Task<VocabularyDto> ImportEntries([FromBody] ImportEntriesInput input)
person Alex Herman    schedule 09.07.2018