aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Timeline.Tests/Helpers/ResponseAssertions.cs25
-rw-r--r--Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs6
-rw-r--r--Timeline/Models/Converters/JsonDateTimeConverter.cs23
-rw-r--r--Timeline/Models/Http/Common.cs4
-rw-r--r--Timeline/Startup.cs16
5 files changed, 66 insertions, 8 deletions
diff --git a/Timeline.Tests/Helpers/ResponseAssertions.cs b/Timeline.Tests/Helpers/ResponseAssertions.cs
index 6d764c68..301ceef6 100644
--- a/Timeline.Tests/Helpers/ResponseAssertions.cs
+++ b/Timeline.Tests/Helpers/ResponseAssertions.cs
@@ -2,11 +2,13 @@
using FluentAssertions.Execution;
using FluentAssertions.Formatting;
using FluentAssertions.Primitives;
-using Newtonsoft.Json;
using System;
using System.Net;
using System.Net.Http;
using System.Text;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using Timeline.Models.Converters;
using Timeline.Models.Http;
namespace Timeline.Tests.Helpers
@@ -88,8 +90,25 @@ namespace Timeline.Tests.Helpers
return new AndWhichConstraint<HttpResponseMessageAssertions, T>(this, null);
}
- var result = JsonConvert.DeserializeObject<T>(body); // TODO! catch and throw on bad format
- return new AndWhichConstraint<HttpResponseMessageAssertions, T>(this, result);
+
+ try
+ {
+ var options = new JsonSerializerOptions
+ {
+ PropertyNamingPolicy = JsonNamingPolicy.CamelCase
+ };
+ options.Converters.Add(new JsonStringEnumConverter());
+ options.Converters.Add(new JsonDateTimeConverter());
+
+ var result = JsonSerializer.Deserialize<T>(body, options);
+
+ return new AndWhichConstraint<HttpResponseMessageAssertions, T>(this, result);
+ }
+ catch (JsonException e)
+ {
+ a.FailWith("Expected response body of {context:HttpResponseMessage} to be json string{reason}, but failed to deserialize it. Exception is {0}.", e);
+ return new AndWhichConstraint<HttpResponseMessageAssertions, T>(this, null);
+ }
}
}
diff --git a/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs b/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs
index 483499fb..c5d0addd 100644
--- a/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs
+++ b/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs
@@ -169,6 +169,12 @@ namespace Timeline.Tests.IntegratedTests
{
const string userUrl = "users/user/timeline/posts";
const string adminUrl = "users/admin/timeline/posts";
+ {
+ using var client = await CreateClientAsUser();
+ var res = await client.PostAsync("users/user/timeline/op/property",
+ new StringContent(@"{""visibility"":""abcdefg""}", System.Text.Encoding.UTF8, System.Net.Mime.MediaTypeNames.Application.Json));
+ res.Should().BeInvalidModel();
+ }
{ // default visibility is registered
{
using var client = await CreateClientWithNoAuth();
diff --git a/Timeline/Models/Converters/JsonDateTimeConverter.cs b/Timeline/Models/Converters/JsonDateTimeConverter.cs
new file mode 100644
index 00000000..551bbbaa
--- /dev/null
+++ b/Timeline/Models/Converters/JsonDateTimeConverter.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Diagnostics;
+using System.Globalization;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace Timeline.Models.Converters
+{
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1062:Validate arguments of public methods")]
+ public class JsonDateTimeConverter : JsonConverter<DateTime>
+ {
+ public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ Debug.Assert(typeToConvert == typeof(DateTime));
+ return DateTime.Parse(reader.GetString(), CultureInfo.InvariantCulture);
+ }
+
+ public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
+ {
+ writer.WriteStringValue(value.ToUniversalTime().ToString("s", CultureInfo.InvariantCulture));
+ }
+ }
+}
diff --git a/Timeline/Models/Http/Common.cs b/Timeline/Models/Http/Common.cs
index 2a88b3a3..d1e95397 100644
--- a/Timeline/Models/Http/Common.cs
+++ b/Timeline/Models/Http/Common.cs
@@ -72,6 +72,8 @@ namespace Timeline.Models.Http
{
public class ResponseData
{
+ public ResponseData() { }
+
public ResponseData(bool create)
{
Create = create;
@@ -106,6 +108,8 @@ namespace Timeline.Models.Http
{
public class ResponseData
{
+ public ResponseData() { }
+
public ResponseData(bool delete)
{
Delete = delete;
diff --git a/Timeline/Startup.cs b/Timeline/Startup.cs
index b2e958f9..672e5f15 100644
--- a/Timeline/Startup.cs
+++ b/Timeline/Startup.cs
@@ -8,11 +8,13 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System.Collections.Generic;
using System.Globalization;
+using System.Text.Json.Serialization;
using Timeline.Auth;
using Timeline.Configs;
using Timeline.Entities;
using Timeline.Formatters;
using Timeline.Helpers;
+using Timeline.Models.Converters;
using Timeline.Services;
namespace Timeline
@@ -36,11 +38,15 @@ namespace Timeline
{
setup.InputFormatters.Add(new StringInputFormatter());
})
- .ConfigureApiBehaviorOptions(options =>
- {
- options.InvalidModelStateResponseFactory = InvalidModelResponseFactory.Factory;
- })
- .AddNewtonsoftJson(); // TODO: Remove this.
+ .AddJsonOptions(options =>
+ {
+ options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
+ options.JsonSerializerOptions.Converters.Add(new JsonDateTimeConverter());
+ })
+ .ConfigureApiBehaviorOptions(options =>
+ {
+ options.InvalidModelStateResponseFactory = InvalidModelResponseFactory.Factory;
+ });
services.Configure<JwtConfig>(Configuration.GetSection(nameof(JwtConfig)));
var jwtConfig = Configuration.GetSection(nameof(JwtConfig)).Get<JwtConfig>();