Клиент Angular TypeScript, созданный из приложения ASP.NET Core 3.1, не работает

У меня возникают трудности со сгенерированным клиентом Swagger Angular из Asp.Net Core 3.1.

Я создал приложение ASP.NET Core и добавил следующее в TestController.cs.

[HttpGet]
[Route("TList")]
[Produces("application/json")]
public ActionResult<TestDto> TList()
{
  TestDto result = new TestDto();
  result.Title = "Title";
  result.DataList = new List<TestItem>();
  result.DataList.Add(new TestItem() { Title = "Test" });
  return Ok(result);
}

DTO был определен как:

  public class TestDto
  {
    public string Title { get; set; }
    public List<TestItem> DataList { get; set; }
  }
  public class TestItem
  {
    public string Title { get; set; }
  }

Я создаю файл swagger из:

gulp.task('swagger-json', function (cb) {
 exec('node_modules\\nswag\\bin\\binaries\\NetCore30\\dotnet-nswag webapi2swagger /assembly:..\\bin\\Debug\\netcoreapp3.1\\WebApplication1.dll /output:WebApplication1.swagger.json', function (err, stdout, stderr) {
  console.log(stdout);
  console.log(stderr);
  cb(err);
 });
});

gulp.task('swagger-angular', function (cb) {
 exec('node_modules\\nswag\\bin\\binaries\\win\\nswag swagger2tsclient /input:WebApplication1.swagger.json /output:src/generated/Backend.ts /template:Angular /injectionTokenType:InjectionToken /httpClass:HttpClient /rxJsVersion:6.0', function (err, stdout, stderr) {
  console.log(stdout);
  console.log(stderr);
  cb(err);
 });
});

Я вызываю интерфейс Rest с помощью

 public getDataWithSwagger() {
  this.testClient.tList().subscribe((data) => {
   this.myData = data;
   this.title = data.title;
  },
   () => { console.warn("Could not call REST") }
  );
 }
}

Но данные переменной не заполняются, заголовок не определен, а список данных вообще не отображается.

Но работает следующий код, заполняются Title и dataList

public getData() {
  this.http.get('https://localhost:44383/api/test/TList').subscribe((data: TestDto) => {
   this.myData = data;
   this.title = data.title;
  });
 }

Какие дополнительные параметры мне нужно указать в командах dotnet-nswag или nswag?

Ниже часть сгенерированного кода из nswag

tList(): Observable<TestDto | null> {
    let url_ = this.baseUrl + "/api/Test/TList";
    url_ = url_.replace(/[?&]$/, "");

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

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

protected processTList(response: HttpResponseBase): Observable<TestDto | null> {
    const status = response.status;

const responseBlob = 
    response instanceof HttpResponse ? response.body : 
    (<any>response).error instanceof Blob ? (<any>response).error : undefined;

let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }};
if (status === 200) {
    return blobToText(responseBlob).pipe(_observableMergeMap(_responseText => {
    let result200: any = null;
    let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
    result200 = resultData200 ? TestDto.fromJS(resultData200) : <any>null;
    return _observableOf(result200);
    }));
} else if (status !== 200 && status !== 204) {
    return blobToText(responseBlob).pipe(_observableMergeMap(_responseText => {
    return throwException("An unexpected server error occurred.", status, _responseText, _headers);
    }));
}
    return _observableOf<TestDto | null>(<any>null);
}

person Nigel Findlater    schedule 23.12.2019    source источник
comment
вопрос не ясен. Откуда взялась первая часть кода?   -  person Sajeetharan    schedule 26.12.2019
comment
Я создал TestController из шаблона, включая операции чтения и записи. Первая часть кода была помещена в класс TestController.   -  person Nigel Findlater    schedule 26.12.2019
comment
Как выглядит функция this.testClient.tList()? Не могли бы вы добавить его в пост?   -  person Milan Tenk    schedule 27.12.2019
comment
@tenkmilan Я добавил сгенерированный код в конец вопроса.   -  person Nigel Findlater    schedule 28.12.2019
comment
Вы наблюдали свой запрос во вкладке сети? какой адрес запроса? и я не знаю, почему swagger генерирует запрос большого двоичного объекта для результата json.   -  person Eldar    schedule 29.12.2019
comment
@Eldar URL-адрес запроса был localhost:44383/api/Test/TList. Я думаю, вы правы насчет запроса blob для ответа json. Знаете ли вы, есть ли переключатель командной строки nswag, чтобы изменить это?   -  person Nigel Findlater    schedule 30.12.2019
comment
Ошибка возникает на test=TestDto.fromJS(resultData200) ; Хотя resultData200 имеет правильный объект, fromJS возвращает неправильные значения, т.е. undefined...   -  person Nigel Findlater    schedule 30.12.2019
comment
Это работает, если я возвращаю _observableOf(resultData200); Но я хотел бы сгенерировать клиент автоматически, поэтому остается вопрос, как мне сгенерировать функционирующий бэкэнд с помощью nswag?   -  person Nigel Findlater    schedule 30.12.2019
comment
@NigelFindlater извините, я понятия не имею о ngswag, но не могли бы вы поделиться с файлом конфигурации nswag тура.   -  person Eldar    schedule 30.12.2019
comment
Еще одно отличие, которое я заметил в проекте .Net Framework, заключалось в том, что при повторении этих шагов я получил tList(): Observable‹TestDtol›, а не tList(): Observable‹TestDto | нулевой> . Может быть, я неправильно определяю свой публичный ActionResult‹TestDto› TList()?   -  person Nigel Findlater    schedule 30.12.2019


Ответы (1)


Проблема была вызвана тем, что сгенерированный Swagger бэкэнд ожидал свойства Pascal Cased Json, но ASP.NET Core по умолчанию предоставляет camelCase. Чтобы исправить это:

        services.AddControllersWithViews()
            .AddJsonOptions(options =>
            {
                options.JsonSerializerOptions.PropertyNamingPolicy=null;
            });

Если вы предпочитаете Camel Case, вы можете изменить это в NSwagStudio.

person Nigel Findlater    schedule 03.01.2020