Skip to content

Commit fd2cf06

Browse files
authored
Document syntax highlighting (#637)
* copy code for StringSyntaxAttribute from original source * document syntax highlighting * add note on usage of GraphQLHttpClient * add note on response type * fix wording
1 parent 79b0161 commit fd2cf06

File tree

2 files changed

+82
-10
lines changed

2 files changed

+82
-10
lines changed

README.md

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ The Library will try to follow the following standards and documents:
2929
var graphQLClient = new GraphQLHttpClient("https://api.example.com/graphql", new NewtonsoftJsonSerializer());
3030
```
3131

32+
> [!NOTE]
33+
> *GraphQLHttpClient* is meant to be used as a single longlived instance per endpoint (i.e. register as singleton in a DI system), which should be reused for multiple requests.
34+
3235
### Create a GraphQLRequest:
3336
#### Simple Request:
3437
```csharp
@@ -64,7 +67,10 @@ var personAndFilmsRequest = new GraphQLRequest {
6467
};
6568
```
6669

67-
Be careful when using `byte[]` in your variables object, as most JSON serializers will treat that as binary data! If you really need to send a *list of bytes* with a `byte[]` as a source, then convert it to a `List<byte>` first, which will tell the serializer to output a list of numbers instead of a base64-encoded string.
70+
> [!WARNING]
71+
> Be careful when using `byte[]` in your variables object, as most JSON serializers will treat that as binary data.
72+
>
73+
> If you really need to send a *list of bytes* with a `byte[]` as a source, then convert it to a `List<byte>` first, which will tell the serializer to output a list of numbers instead of a base64-encoded string.
6874
6975
### Execute Query/Mutation:
7076

@@ -100,6 +106,11 @@ var graphQLResponse = await graphQLClient.SendQueryAsync(personAndFilmsRequest,
100106
var personName = graphQLResponse.Data.person.Name;
101107
```
102108

109+
> [!IMPORTANT]
110+
> Note that the field in the GraphQL response which gets deserialized into the response object is the `data` field.
111+
>
112+
> A common mistake is to try to directly use the `PersonType` class as response type (because thats the *thing* you actually want to query), but the returned response object contains a property `person` containing a `PersonType` object (like the `ResponseType` modelled above).
113+
103114
### Use Subscriptions
104115

105116
```csharp
@@ -141,6 +152,16 @@ var subscription = subscriptionStream.Subscribe(response =>
141152
subscription.Dispose();
142153
```
143154

155+
## Syntax Highlighting for GraphQL strings in IDEs
156+
157+
.NET 7.0 introduced the [StringSyntaxAttribute](https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.codeanalysis.stringsyntaxattribute?view=net-8.0) to have a unified way of telling what data is expected in a given `string` or `ReadOnlySpan<char>`. IDEs like Visual Studio and Rider can then use this to provide syntax highlighting and checking.
158+
159+
From v6.0.4 on all GraphQL string parameters in this library are decorated with the `[StringSyntax("GraphQL")]` attribute.
160+
161+
Currently, there is no native support for GraphQL formatting and syntax highlighting in Visual Studio, but the [GraphQLTools Extension](https://marketplace.visualstudio.com/items?itemName=codearchitects-research.GraphQLTools) provides that for you.
162+
163+
For Rider, JetBrains provides a [Plugin](https://plugins.jetbrains.com/plugin/8097-graphql), too.
164+
144165
## Useful Links:
145166

146167
* [StarWars Example Server (GitHub)](https://github.com/graphql/swapi-graphql)
Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,72 @@
11
#if !NET7_0_OR_GREATER
22

3+
// ReSharper disable InconsistentNaming
34
// ReSharper disable once CheckNamespace
45
namespace System.Diagnostics.CodeAnalysis;
56

6-
/// <summary>
7-
/// Stub
8-
/// </summary>
7+
/// <summary>Stub version of the StringSyntaxAttribute, which was introduced in .NET 7</summary>
98
public sealed class StringSyntaxAttribute : Attribute
109
{
11-
// ReSharper disable once InconsistentNaming
10+
/// <summary>Initializes the <see cref="StringSyntaxAttribute"/> with the identifier of the syntax used.</summary>
11+
/// <param name="syntax">The syntax identifier.</param>
12+
public StringSyntaxAttribute(string syntax)
13+
{
14+
Syntax = syntax;
15+
Arguments = Array.Empty<object?>();
16+
}
17+
18+
/// <summary>Initializes the <see cref="StringSyntaxAttribute"/> with the identifier of the syntax used.</summary>
19+
/// <param name="syntax">The syntax identifier.</param>
20+
/// <param name="arguments">Optional arguments associated with the specific syntax employed.</param>
21+
public StringSyntaxAttribute(string syntax, params object?[] arguments)
22+
{
23+
Syntax = syntax;
24+
Arguments = arguments;
25+
}
26+
27+
/// <summary>Gets the identifier of the syntax used.</summary>
28+
public string Syntax { get; }
29+
30+
/// <summary>Optional arguments associated with the specific syntax employed.</summary>
31+
public object?[] Arguments { get; }
32+
33+
/// <summary>The syntax identifier for strings containing composite formats for string formatting.</summary>
1234
#pragma warning disable IDE1006
1335
public const string CompositeFormat = nameof(CompositeFormat);
14-
#pragma warning restore IDE1006
1536

16-
#pragma warning disable IDE0060
17-
public StringSyntaxAttribute(string syntax)
18-
{ }
19-
#pragma warning restore IDE0060
37+
/// <summary>The syntax identifier for strings containing date format specifiers.</summary>
38+
public const string DateOnlyFormat = nameof(DateOnlyFormat);
39+
40+
/// <summary>The syntax identifier for strings containing date and time format specifiers.</summary>
41+
public const string DateTimeFormat = nameof(DateTimeFormat);
42+
43+
/// <summary>The syntax identifier for strings containing <see cref="Enum"/> format specifiers.</summary>
44+
public const string EnumFormat = nameof(EnumFormat);
45+
46+
/// <summary>The syntax identifier for strings containing <see cref="Guid"/> format specifiers.</summary>
47+
public const string GuidFormat = nameof(GuidFormat);
48+
49+
/// <summary>The syntax identifier for strings containing JavaScript Object Notation (JSON).</summary>
50+
public const string Json = nameof(Json);
51+
52+
/// <summary>The syntax identifier for strings containing numeric format specifiers.</summary>
53+
public const string NumericFormat = nameof(NumericFormat);
54+
55+
/// <summary>The syntax identifier for strings containing regular expressions.</summary>
56+
public const string Regex = nameof(Regex);
57+
58+
/// <summary>The syntax identifier for strings containing time format specifiers.</summary>
59+
public const string TimeOnlyFormat = nameof(TimeOnlyFormat);
60+
61+
/// <summary>The syntax identifier for strings containing <see cref="TimeSpan"/> format specifiers.</summary>
62+
public const string TimeSpanFormat = nameof(TimeSpanFormat);
63+
64+
/// <summary>The syntax identifier for strings containing URIs.</summary>
65+
public const string Uri = nameof(Uri);
66+
67+
/// <summary>The syntax identifier for strings containing XML.</summary>
68+
public const string Xml = nameof(Xml);
69+
#pragma warning restore IDE1006
2070
}
71+
2172
#endif

0 commit comments

Comments
 (0)