Использование асинхронного .net WebApi от Angular 2+ и Swagger - PullRequest
0 голосов
/ 25 июня 2019

Я начинаю путешествие по Angular 2+ (v8) и натолкнулся на несколько вопросов о передовой практике использования асинхронных функций c # WebApi.Вопросы в конце:

В моем примере WebApi (обратите внимание, что в будущем это будет вызывать хранилище асинхронно, но не для краткости) У меня есть следующая функция:

// GET api/values
[HttpGet]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(Task<IEnumerable<SearchResult>>), (int)HttpStatusCode.OK)]
public async Task<IActionResult> Get([FromQuery]string searchText, [FromQuery]int pageSize = 10, [FromQuery]int pageIndex = 0)
{
  if (string.IsNullOrEmpty(searchText))
  {
    return BadRequest();
  }

  //Call a repository here and return a result
  var searchResults = new List<SearchResult>()
  {
    new SearchResult()
    {
      SearchResultType = SearchResultType.Law, Id = Guid.NewGuid(),
      Title = "A boring title",
      Description = "A boring decription"
    },
    new SearchResult()
    {
      SearchResultType = SearchResultType.Law, Id = Guid.NewGuid(),
      Title = "An interesting title",
      Description = "An exciting description"
    },
  };

  return Ok(await Task.FromResult(searchResults.Where(x => x.Title.Contains(searchText))));
}

Это возвращает Task<IActionResult>, и я использовал Декоратор Swagger, чтобы сказать, что маршрут возвращается [ProducesResponseType(typeof(Task<IEnumerable<SearchResult>>).Однако в примере с ответом swagger ожидается модель задачи:

{
  "result": [
    {
      "searchResultType": "Law",
      "id": "string",
      "title": "string",
      "description": "string"
    }
  ],
  "id": 0,
  "exception": {},
  "status": "Created",
  "isCanceled": true,
  "isCompleted": true,
  "isCompletedSuccessfully": true,
  "creationOptions": "None",
  "asyncState": {},
  "isFaulted": true
}

Где фактический ответ:

[
  {
    "searchResultType": 1,
    "id": "0ba4e4ef-37fd-4a76-98ed-4fad64d26b1b",
    "title": "A boring title",
    "description": "A boring description."
  },
  {
    "searchResultType": 1,
    "id": "e8c7e39d-cca6-43b2-90be-87537a4a0b8e",
    "title": "An exciting title",
    "description": "An exciting description."
  }
]

В Angular 8 мой сервис потребляет:

@Injectable()
export class SearchService {
  constructor(private http: HttpClient) {}

  search(
    filter: { searchTerm: string } = { searchTerm: "" },
    page = 1
  ): Observable<ISearchResult[]> {
    return this.http.get<ISearchResult[]>("api/v1/Search?searchText=" + filter.searchTerm);
  }
}

Итак, вопросы:

  1. Должно ли [ProducesResponseType(typeof(Task<IEnumerable<SearchResult>>) действительно быть [ProducesResponseType(typeof(IEnumerable<SearchResult>)?

  2. Будет ли Task<> когда-либовозвращено клиенту?

Я спрашиваю об этом, потому что я изначально забыл await возвращаемое значение в API и модель Task была фактически возвращена клиенту Angular, а затем в AngularСервис Я должен был использовать следующее, чтобы получить результат, который грязный:

  return this.http.get<ISearchResult[]>("api/v1/Search?searchText=" + filter.searchTerm)
 .pipe(
   map((res:ISearchResult[]) => res.result)
 );
Правильно ли я делаю это?Есть ли способ лучше ?

1 Ответ

1 голос
/ 25 июня 2019

Чтобы ответить на ваши вопросы:

  1. Вам необходимо использовать [ProducesResponseType(typeof(IEnumerable<SearchResult>).Вам не нужно добавлять Task здесь, просто укажите точный тип, который вы возвращаете.Поэтому ваше возвращение может быть просто:

  2. Нет.Единственный способ вернуть задание - это явный возврат задания.Например, возьмите следующий метод:

    [HttpGet("test")] [ProducesResponseType(typeof(Task<string>), (int)HttpStatusCode.OK)] public Task Get() { return Task.FromResult("snoop"); }

Это вернет вам задачу, но если ваш метод помечен как асинхронный, тип возврата будет всегдабыть типа Task или Task<type>, и компилятор будет жаловаться, если вы не ждете, или вы возвращаете что-либо, кроме Task.

Вам не нужно отображать ответ.result даже не существует в ваших возвращаемых данных.Вы можете просто иметь:

return this.http.get<ISearchResult[]>("api/v1/Search?searchText=" + filter.searchTerm);

, который вернет вам наблюдаемое ISearchResult[].

...