Skip to content

Commit 9bdac6f

Browse files
Add more demo API endpoints, fix couple small issues
1 parent 47c1cd7 commit 9bdac6f

File tree

45 files changed

+2268
-341
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+2268
-341
lines changed

Demo/ReQuesty.Demo.Api/Controllers/Base/DemoControllerBase.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ namespace ReQuesty.Demo.Api.Controllers.Base;
1212
[Route("[controller]")]
1313
[Consumes(MediaTypeNames.Application.Json)]
1414
[Produces(MediaTypeNames.Application.Json)]
15-
[ProducesResponseType<ProblemDetails>(StatusCodes.Status500InternalServerError)]
1615
public abstract class DemoControllerBase : ControllerBase
1716
{
1817
/// <summary>
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
using System.Text.Json.Serialization;
2+
using Microsoft.AspNetCore.Mvc;
3+
using ReQuesty.Demo.Api.Controllers.Base;
4+
5+
namespace ReQuesty.Demo.Api.Controllers;
6+
7+
/// <summary>
8+
/// A controller to test the behavior of enum return types
9+
/// </summary>
10+
public class EnumReturnController : DemoControllerBase
11+
{
12+
#region IntegerValues enum
13+
/// <summary>
14+
/// Example enum with its values as integers
15+
/// </summary>
16+
public enum IntegerValues
17+
{
18+
/// <summary>
19+
/// Zero value
20+
/// </summary>
21+
Zero = 0,
22+
23+
/// <summary>
24+
/// One value
25+
/// </summary>
26+
One = 1,
27+
28+
/// <summary>
29+
/// Two value
30+
/// </summary>
31+
Two = 2
32+
}
33+
34+
/// <summary>
35+
/// Gets a IntegerValues enum based on the specified return type.
36+
/// </summary>
37+
/// <returns></returns>
38+
[HttpGet("integer", Name = "GetIntegerValuesEnum")]
39+
[ProducesResponseType<IntegerValues>(StatusCodes.Status200OK)]
40+
public async ValueTask<ActionResult<IntegerValues>> GetIntegerValuesEnumAsync([FromQuery] ReturnType returnType)
41+
{
42+
return Ok(returnType switch
43+
{
44+
ReturnType.Null => null,
45+
ReturnType.Random => IntegerValues.One,
46+
ReturnType.Invalid => (IntegerValues)(-1),
47+
_ => throw new()
48+
});
49+
}
50+
51+
/// <summary>
52+
/// Gets a nullable IntegerValues enum based on the specified return type.
53+
/// </summary>
54+
/// <returns></returns>
55+
[HttpGet("integer/nullable", Name = "GetNullableIntegerValuesEnum")]
56+
[ProducesResponseType<IntegerValues?>(StatusCodes.Status200OK)]
57+
public async ValueTask<ActionResult<IntegerValues?>> GetNullableIntegerValuesEnumAsync([FromQuery] ReturnType returnType)
58+
{
59+
return Ok(returnType switch
60+
{
61+
ReturnType.Null => null,
62+
ReturnType.Random => IntegerValues.One,
63+
ReturnType.Invalid => (IntegerValues)(-1),
64+
_ => throw new()
65+
});
66+
}
67+
#endregion
68+
69+
#region StringValues enum
70+
/// <summary>
71+
/// Example enum with its values as strings
72+
/// </summary>
73+
[JsonConverter(typeof(JsonStringEnumConverter))]
74+
public enum StringValues
75+
{
76+
/// <summary>
77+
/// North value
78+
/// </summary>
79+
North,
80+
81+
/// <summary>
82+
/// East value
83+
/// </summary>
84+
East,
85+
86+
/// <summary>
87+
/// South value
88+
/// </summary>
89+
South,
90+
91+
/// <summary>
92+
/// West value
93+
/// </summary>
94+
West
95+
}
96+
97+
/// <summary>
98+
/// Gets a StringValues enum based on the specified return type.
99+
/// </summary>
100+
/// <returns></returns>
101+
[HttpGet("string", Name = "GetStringValuesEnum")]
102+
[ProducesResponseType<StringValues>(StatusCodes.Status200OK)]
103+
public async ValueTask<ActionResult<StringValues>> GetStringValuesEnumAsync([FromQuery] ReturnType returnType)
104+
{
105+
return Ok(returnType switch
106+
{
107+
ReturnType.Null => null,
108+
ReturnType.Random => StringValues.North,
109+
ReturnType.Invalid => (StringValues)(-1),
110+
_ => throw new()
111+
});
112+
}
113+
114+
/// <summary>
115+
/// Gets a nullable StringValues enum based on the specified return type.
116+
/// </summary>
117+
/// <returns></returns>
118+
[HttpGet("string/nullable", Name = "GetNullableStringValuesEnum")]
119+
[ProducesResponseType<StringValues?>(StatusCodes.Status200OK)]
120+
public async ValueTask<ActionResult<StringValues?>> GetNullableStringValuesEnumAsync([FromQuery] ReturnType returnType)
121+
{
122+
return Ok(returnType switch
123+
{
124+
ReturnType.Null => null,
125+
ReturnType.Random => StringValues.North,
126+
ReturnType.Invalid => (StringValues)(-1),
127+
_ => throw new()
128+
});
129+
}
130+
#endregion
131+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
using ReQuesty.Demo.Api.Controllers.Base;
3+
using ReQuesty.Demo.Api.Models;
4+
5+
namespace ReQuesty.Demo.Api.Controllers;
6+
7+
/// <summary>
8+
/// A controller to test the behavior of object return types
9+
/// </summary>
10+
public class ObjectReturnController : DemoControllerBase
11+
{
12+
/// <summary>
13+
/// Gets a SomeObject based on the specified return type.
14+
/// </summary>
15+
/// <returns></returns>
16+
[HttpGet("some-object", Name = "GetSomeObject")]
17+
[ProducesResponseType<SomeObject>(StatusCodes.Status200OK)]
18+
public async ValueTask<ActionResult<SomeObject>> GetSomeObjectAsync([FromQuery] ReturnType returnType)
19+
{
20+
return Ok(returnType switch
21+
{
22+
ReturnType.Null => null,
23+
ReturnType.Random => new SomeObject
24+
{
25+
Id = Guid.NewGuid(),
26+
Name = "Sample Object",
27+
Age = 25,
28+
RequestedAt = DateTimeOffset.UtcNow,
29+
Cost = 100.0
30+
},
31+
ReturnType.Invalid => -1,
32+
_ => throw new()
33+
});
34+
}
35+
}

Demo/ReQuesty.Demo.Api/Controllers/PrimativeReturnController.cs

Lines changed: 83 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
namespace ReQuesty.Demo.Api.Controllers;
55

66
/// <summary>
7-
///
7+
/// A controller to test the behavior of primative return types
88
/// </summary>
99
public class PrimativeReturnController : DemoControllerBase
1010
{
11+
#region Strings
1112
/// <summary>
1213
/// Gets a string based on the specified return type.
1314
/// </summary>
@@ -29,7 +30,7 @@ public async ValueTask<ActionResult<string>> GetStringAsync([FromQuery] ReturnTy
2930
/// Gets a nullable string based on the specified return type.
3031
/// </summary>
3132
/// <returns></returns>
32-
[HttpGet("nullable-string", Name = "GetNullableString")]
33+
[HttpGet("string/nullable", Name = "GetNullableString")]
3334
[ProducesResponseType<string>(StatusCodes.Status200OK)] // <string?> isn't valid here
3435
public async ValueTask<ActionResult<string?>> GetNullableStringAsync([FromQuery] ReturnType returnType)
3536
{
@@ -41,12 +42,14 @@ public async ValueTask<ActionResult<string>> GetStringAsync([FromQuery] ReturnTy
4142
_ => throw new()
4243
});
4344
}
45+
#endregion
4446

47+
#region Integers
4548
/// <summary>
4649
/// Gets an int based on the specified return type.
4750
/// </summary>
4851
/// <returns></returns>
49-
[HttpGet("int", Name = "GetInt")]
52+
[HttpGet("integer", Name = "GetInt")]
5053
[ProducesResponseType<int>(StatusCodes.Status200OK)]
5154
public async ValueTask<ActionResult<int>> GetIntAsync([FromQuery] ReturnType returnType)
5255
{
@@ -63,7 +66,7 @@ public async ValueTask<ActionResult<int>> GetIntAsync([FromQuery] ReturnType ret
6366
/// Gets a nullable int based on the specified return type.
6467
/// </summary>
6568
/// <returns></returns>
66-
[HttpGet("nullable-int", Name = "GetNullableInt")]
69+
[HttpGet("integer/nullable", Name = "GetNullableInt")]
6770
[ProducesResponseType<int?>(StatusCodes.Status200OK)]
6871
public async ValueTask<ActionResult<int?>> GetNullableIntAsync([FromQuery] ReturnType returnType)
6972
{
@@ -75,7 +78,81 @@ public async ValueTask<ActionResult<int>> GetIntAsync([FromQuery] ReturnType ret
7578
_ => throw new()
7679
});
7780
}
81+
#endregion
7882

83+
#region Doubles
84+
/// <summary>
85+
/// Gets an int based on the specified return type.
86+
/// </summary>
87+
/// <returns></returns>
88+
[HttpGet("double", Name = "GetDouble")]
89+
[ProducesResponseType<double>(StatusCodes.Status200OK)]
90+
public async ValueTask<ActionResult<double>> GetDoubleAsync([FromQuery] ReturnType returnType)
91+
{
92+
return Ok(returnType switch
93+
{
94+
ReturnType.Null => null,
95+
ReturnType.Random => Random.Shared.NextDouble(),
96+
ReturnType.Invalid => "not a double",
97+
_ => throw new()
98+
});
99+
}
100+
101+
/// <summary>
102+
/// Gets a nullable double based on the specified return type.
103+
/// </summary>
104+
/// <returns></returns>
105+
[HttpGet("double/nullable", Name = "GetNullableDouble")]
106+
[ProducesResponseType<double?>(StatusCodes.Status200OK)]
107+
public async ValueTask<ActionResult<double?>> GetNullableDoubleAsync([FromQuery] ReturnType returnType)
108+
{
109+
return Ok(returnType switch
110+
{
111+
ReturnType.Null => null,
112+
ReturnType.Random => Random.Shared.NextDouble(),
113+
ReturnType.Invalid => "not a double",
114+
_ => throw new()
115+
});
116+
}
117+
#endregion
118+
119+
#region Floats
120+
/// <summary>
121+
/// Gets a float based on the specified return type.
122+
/// </summary>
123+
/// <returns></returns>
124+
[HttpGet("float", Name = "GetFloat")]
125+
[ProducesResponseType<float>(StatusCodes.Status200OK)]
126+
public async ValueTask<ActionResult<float>> GetFloatAsync([FromQuery] ReturnType returnType)
127+
{
128+
return Ok(returnType switch
129+
{
130+
ReturnType.Null => null,
131+
ReturnType.Random => (float)Random.Shared.NextDouble(),
132+
ReturnType.Invalid => "not a float",
133+
_ => throw new()
134+
});
135+
}
136+
137+
/// <summary>
138+
/// Gets a nullable float based on the specified return type.
139+
/// </summary>
140+
/// <returns></returns>
141+
[HttpGet("float/nullable", Name = "GetNullableFloat")]
142+
[ProducesResponseType<float?>(StatusCodes.Status200OK)]
143+
public async ValueTask<ActionResult<float?>> GetNullableFloatAsync([FromQuery] ReturnType returnType)
144+
{
145+
return Ok(returnType switch
146+
{
147+
ReturnType.Null => null,
148+
ReturnType.Random => (float)Random.Shared.NextDouble(),
149+
ReturnType.Invalid => "not a float",
150+
_ => throw new()
151+
});
152+
}
153+
#endregion
154+
155+
#region Guids
79156
/// <summary>
80157
/// Gets an Guid based on the specified return type.
81158
/// </summary>
@@ -97,7 +174,7 @@ public async ValueTask<ActionResult<Guid>> GetGuidAsync([FromQuery] ReturnType r
97174
/// Gets a nullable guid based on the specified return type.
98175
/// </summary>
99176
/// <returns></returns>
100-
[HttpGet("nullable-guid", Name = "GetNullableGuid")]
177+
[HttpGet("guid/nullable", Name = "GetNullableGuid")]
101178
[ProducesResponseType<Guid?>(StatusCodes.Status200OK)]
102179
public async ValueTask<ActionResult<Guid?>> GetNullableGuidAsync([FromQuery] ReturnType returnType)
103180
{
@@ -109,4 +186,5 @@ public async ValueTask<ActionResult<Guid>> GetGuidAsync([FromQuery] ReturnType r
109186
_ => throw new()
110187
});
111188
}
189+
#endregion
112190
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
namespace ReQuesty.Demo.Api.Models;
2+
3+
/// <summary>
4+
/// A sample object model to be used in the demo API
5+
/// </summary>
6+
public sealed record SomeObject
7+
{
8+
/// <summary>
9+
/// The unique identifier of the object
10+
/// </summary>
11+
public required Guid Id { get; init; }
12+
13+
/// <summary>
14+
/// The name of the object
15+
/// </summary>
16+
public required string Name { get; init; }
17+
18+
/// <summary>
19+
/// The age of the object
20+
/// </summary>
21+
public required int Age { get; init; }
22+
23+
/// <summary>
24+
/// The timestamp of when the object was requested
25+
/// </summary>
26+
public required DateTimeOffset RequestedAt { get; init; }
27+
28+
/// <summary>
29+
/// The cost of the object
30+
/// </summary>
31+
public required double Cost { get; init; }
32+
}

Demo/ReQuesty.Demo.Api/Program.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ private static WebApplication BuildBonesApi(this WebApplicationBuilder builder)
3131
{
3232
configure.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
3333
configure.JsonSerializerOptions.WriteIndented = true;
34-
configure.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
3534
configure.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
3635
configure.JsonSerializerOptions.AllowTrailingCommas = true;
3736
configure.JsonSerializerOptions.RespectNullableAnnotations = true;

0 commit comments

Comments
 (0)