【问题标题】:Consuming an async .net WebApi from Angular 2+ and Swagger从 Angular 2+ 和 Swagger 使用异步 .net WebApi
【发布时间】:2019-06-25 20:48:43
【问题描述】:

我开始了 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&lt;IActionResult&gt; 并且我已经使用 Swagger 装饰器说路线返回 [ProducesResponseType(typeof(Task&lt;IEnumerable&lt;SearchResult&gt;&gt;) 。然而,在招摇示例响应中,则需要一个任务模型:

{
  "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&lt;IEnumerable&lt;SearchResult&gt;&gt;) 真的应该是[ProducesResponseType(typeof(IEnumerable&lt;SearchResult&gt;) 吗?

  2. Task&lt;&gt; 会返回给客户吗?

我问这个是因为我最初忘记了await api 中的返回值,并且任务模型实际上返回给了 Angular 客户端,然后在 Angular 服务中我不得不使用以下内容来获得混乱的结果:

  return this.http.get<ISearchResult[]>("api/v1/Search?searchText=" + filter.searchTerm)
 .pipe(
   map((res:ISearchResult[]) => res.result)
 );
  1. 我这样做是否正确?有没有更好的办法 ?

【问题讨论】:

    标签: angular async-await task swagger asp.net-core-webapi


    【解决方案1】:

    回答您的问题:

    1. 您需要使用[ProducesResponseType(typeof(IEnumerable&lt;SearchResult&gt;)。您无需在此处添加Task,只需指定您要返回的确切类型。因此,您的回报可以是:

    2. 没有。返回任务的唯一方法是显式返回任务。例如,采取以下方法:

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

    这会给你返回一个任务,但是如果你的方法被标记为异步,那么返回类型将始终是TaskTask&lt;type&gt;类型,如果你不等待,编译器会抱怨,或者你返回除了Task 之外的任何东西。

    1. 您不需要映射响应。 result 甚至不存在于您的返回数据中。你可以简单地拥有:

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

    这将返回一个 ISearchResult[] 的 observable。

    【讨论】:

    • 抱歉,我认为我的示例 api 是不言自明的,但显然不是!我打算以异步方式与存储库或其他来源交谈。我会修改问题
    • 谢谢。我想让我感到困惑的是“公共异步任务”的Webapi函数返回类型,对我来说,这个函数将返回一个任务类型的IActionResult。但是,您是说除非明确要求,否则永远不会将其返回给客户。需要阅读更多相关信息。
    • This 将是一个很好的起点。
    猜你喜欢
    • 2017-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-03
    • 2020-06-12
    • 1970-01-01
    • 1970-01-01
    • 2013-05-13
    相关资源
    最近更新 更多