14. 突变输入
5m

概述

让我们完成我们的!

在本课中,我们将

  • 了解有关的常见约定以及input 类型
  • 了解如何使用响应来处理成功和失败的操作

突变参数和输入

我们之前在中使用过,我们传入了一个名为id

GraphQL 模式
type Query {
playlist(id: ID!): Playlist
}

对于addItemsToPlaylist,我们需要不止一个

来自文档,我们需要以下参数:

  • playlist_id - 播放列表的 ID,作为string
  • position - 一个integer,从零开始的索引,我们要在该位置插入曲目。
  • uris - 以逗号分隔的string,包含我们要添加的轨道的uri值。

我们可以将所有三个都用作,但是一个好的做法是将输入类型用作,用于

中,input类型是一种特殊的,它将一组组合在一起,然后可以作为另一个的参数使用。

作为一种命名约定,我们在类型的名称后面添加Input后缀,并赋予它与关联的相同名称。

在本例中,我们可以将命名为AddItemsToPlaylistInput,用于addItemsToPlaylist字段。让我们开始创建它吧!

AddItemsToPlaylistInput 类型

Types文件夹下,让我们添加一个新的类,用于AddItemsToPlaylistInput

Types/AddItemsToPlaylistInput.cs
namespace Odyssey.MusicMatcher;
public class AddItemsToPlaylistInput
{
}

正如我们所提到的,一个常见的约定是在input类型的名称末尾添加Input。此外,当我们使用Input后缀时,在幕后,Hot Chocolate 会将这个类转换为input类型。当我们进入 Explorer 时,我们将看到这一点!

接下来,我们将添加属性。请记住,我们需要播放列表的 ID 和 URI 列表,至少。我们可以在播放列表中指定这些项目添加的位置,但这对于 REST API 来说不是必需的。默认情况下,曲目将追加到播放列表的末尾,因此我们可以从我们的中省略它。请记住,你的 GraphQL API 不需要完全匹配你的 REST API!

Types/AddItemsToPlaylistInput.cs
[ID]
[GraphQLDescription("The ID of the playlist.")]
public string PlaylistId { get; set;}
[GraphQLDescription("A comma-separated list of Spotify URIs to add.")]
public List<string> Uris { get; set; }

不要忘记构造函数!

Types/AddItemsToPlaylistInput.cs
public AddItemsToPlaylistInput(string playlistId, List<string> uris)
{
PlaylistId = playlistId;
Uris = uris;
}

更新解析器

现在让我们确保我们的了解这个输入。回到Mutation.cs中,我们可以将它添加到我们函数的参数中。我们将这个命名为input

请注意,input参数可以命名为任何名称,例如playlistTrackstracksInput!我们建议与团队协作,决定命名约定。使用input作为名称是一个常见的约定。

Mutation.cs
public AddItemsToPlaylistPayload AddItemsToPlaylist(
AddItemsToPlaylistInput input
)

趁我们在这里,让我们也连接SpotifyService,使这个函数异步,并将返回类型编辑为Task<T>

Mutation.cs
public async Task<AddItemsToPlaylistPayload> AddItemsToPlaylist(
AddItemsToPlaylistInput input,
SpotifyService spotifyService)

同样,不要忘记在顶部导入SpotifyWeb命名空间!

Mutation.cs
using SpotifyWeb;

现在该使用我们的服务和输入类型了!在函数的主体中,我们将使用AddTracksToPlaylistAsync方法,该方法来自spotifyService

Mutation.cs
var snapshot_id = await spotifyService.AddTracksToPlaylistAsync(
input.PlaylistId,
null,
string.Join(",", input.Uris)
);

使用方法签名作为指南,我们可以添加来自input的对应值,用于PlaylistId,并将null传递给position

对于最后一个参数,我们需要稍微调整一下格式。因为 input.Uris 是一个 list 类型的 string,而方法需要一个以逗号分隔的 string 类型的值,所以我们会使用 string.Join.

我们 await 方法的结果,并将其存储在一个名为 的变量中,名为 snapshot_id。这是方法的返回类型, 不是 我们架构期望的播放列表对象。

这仅仅是我们要使用的 REST 端点的特性。为了检索 playlist 对象,我们需要使用之前用过的 GetPlaylistAsync 方法进行后续调用。

但是我们应该在哪里进行调用呢?如果我们将它包含在这个 中,这意味着即使 playlist 没有包含在 中,也会进行额外的 REST 调用!

我们之前已经遇到过这种情况,当时我们使用了 链。但是,在这种情况下,我们将保持 REST 调用包含在这个解析器中。考虑到客户端应用程序的需求,如果他们要向播放列表添加曲目,他们 很可能 会将播放列表及其曲目列表包含在 中!他们想要看到 结果 他们的 毕竟。

让我们继续。在 Playlist 中,我们将调用 spotifyService.GetPlaylistAsync 方法。

Mutation.cs
var response = await spotifyService.GetPlaylistAsync(input.PlaylistId);
var playlist = new Playlist(response);

看起来熟悉吗?这是我们在 Query.Playlist 中使用的代码。

最后,让我们更新 AddItemsToPlaylistPayload 实例中的返回值,具体来说,用 playlist 替换硬编码的播放列表。

Mutation.cs
return new AddItemsToPlaylistPayload(
"200",
true,
"Successfully added items to playlist",
playlist
);

成功路径已经处理好了!现在如果出现错误怎么办?让我们将到目前为止的代码包装在 try 块中,并 catch 任何抛出的 Exception

Mutation.cs
try
{
var snapshot_id = await spotifyService.AddTracksToPlaylistAsync(
input.PlaylistId,
input.Position,
string.Join(",", input.Uris)
);
var response = await spotifyService.GetPlaylistAsync(input.PlaylistId);
var playlist = new Playlist(response);
return new AddItemsToPlaylistPayload(
200,
true,
"Successfully added items to playlist",
playlist
);
}
catch (Exception e)
{
// return something
}

如果出现错误,我们的返回值应该略有不同。我们仍然会返回 AddItemsToPlaylistPayload 类型,但这次代码将是 500,成功状态将是 false,我们还会返回异常包含的任何消息。 playlist 参数将被设置为 null

Mutation.cs
return new AddItemsToPlaylistPayload(500, false, e.Message, null);

探索时间!

在服务器运行了我们最新的更改之后,让我们打开一个新的工作区选项卡,从头开始构建我们的 。随着 input 的添加,当我们添加 addItemsToPlaylist 时, 看起来有点不同了:

https://studio.apollographql.com/sandbox/explorer

Explorer - AddItemsToPlaylist mutation

GraphQL 操作
mutation AddItemsToPlaylist($input: AddItemsToPlaylistInput!) {
addItemsToPlaylist(input: $input) {
}
}

我们还可以看到 变量 部分,其中在 JSON 对象中有一个 input 属性:

变量
{
"input": null
}

让我们开始填充这个 input 对象。在 文档 面板中,点击 input ,并添加 AddItemsToPlaylistInput 中的三个字段。Explorer 会自动更新你的

https://studio.apollographql.com/sandbox/explorer

Explorer - AddItemsToPlaylist mutation adding variables for input

变量
{
"input": {
"playlistId": null,
"uris": null
}
}

我们只需要更新这些 null!我们将使用一个新的播放列表 ID 并添加一个包含一个 URI 的数组。这些都是模拟数据,所以你可以随意放入任何你想放入的东西作为占位符。它不需要实际存在于 Spotify 数据库中。

变量
{
"input": {
"playlistId": "6LB6g7S5nc1uVVfj00Kh6Z",
"uris": ["ASongAboutGraphQL"]
}
}
https://studio.apollographql.com/sandbox/explorer

Explorer - AddItemsToPlaylist mutation adding variables for input

最后,让我们用我们需要的字段填充 的其余部分。添加 codesuccessmessage 。然后对于播放列表,添加其详细信息 以及 其曲目!

GraphQL 操作
mutation AddItemsToPlaylist($input: AddItemsToPlaylistInput!) {
addItemsToPlaylist(input: $input) {
code
message
success
playlist {
id
name
tracks {
id
name
}
}
}
}

这是一个很大的 ,按播放运行!我们应该看到我们的数据成功返回。在 tracks 列表的底部,我们将看到 id 设置为我们传递给 uri,以及名称。

https://studio.apollographql.com/sandbox/explorer

Explorer - AddItemsToPlaylist mutation adding variables for input

注意:你的响应看起来有点不同吗?因为 REST API 是所有 学习者共享的,你可能会在响应中看到更多或更少的曲目。这很可能是因为 其他 学习者将他们自己的曲目添加到播放列表中。我们也会定期重置数据以保持数据干净。

太棒了!现在看看如果你将播放列表 ID 更新为一个不存在的值会发生什么。

变量
{
"input": {
"playlistId": "DoesNotExist",
"uris": ["ASongAboutGraphQL"]
}
}
https://studio.apollographql.com/sandbox/explorer

Explorer - AddItemsToPlaylist mutation adding variables for input

当我们再次运行 时,我们仍然会收到数据,但这次我们得到了一个错误代码,一个失败消息,以及一个 null 播放列表。

我们的 mutation 工作了! 🎉

练习

我们如何在 schema 中使用 input 类型?
在为 mutation 创建输入类型时,通常使用什么命名约定?

关键要点

  • 中通常需要多个 来执行操作。为了将参数分组在一起,我们使用 input 类型来提高清晰度和可维护性。
  • 当我们在类中添加 "Input" 后缀时,Hot Chocolate 会将这个 C# 类转换为 input 类型到 schema 中。
  • 我们可以像访问其他任何 参数一样访问 input 函数中。

结论

太棒了,您成功了,您构建了一个 API!您拥有一个运行良好的,其中包含使用 Spotify REST API 作为的播放列表和曲目。您已经编写了查询和,并在此过程中了解了一些常见的 GraphQL 约定。您已经探索了如何在 GraphQL 中使用和输入类型进行模式设计。花点时间庆祝一下;您学到了很多东西!

但这仅仅是开始:当您准备好进一步提升您的 API 时,请进入本系列的下一门课程: 使用 C# 和 Hot Chocolate 进行联合

如果您有任何想要看到的内容的请求,请在下面告诉我们!

上一步

分享您对本课的疑问和评论

本课程目前处于

测试版
.您的反馈对我们改进有帮助!如果您卡住了或感到困惑,请告诉我们,我们会帮助您。所有评论都是公开的,必须遵守 Apollo 行为准则。请注意,已解决或已解决的评论可能会被删除。

您需要一个 GitHub 帐户才能在下面发布。没有帐户? 请在我们的 Odyssey 论坛上发布。