diff --git a/CM.Voice.VoiceApi.Sdk/CM.Voice.VoiceApi.Sdk.csproj b/CM.Voice.VoiceApi.Sdk/CM.Voice.VoiceApi.Sdk.csproj index e68e1d4..f27c336 100644 --- a/CM.Voice.VoiceApi.Sdk/CM.Voice.VoiceApi.Sdk.csproj +++ b/CM.Voice.VoiceApi.Sdk/CM.Voice.VoiceApi.Sdk.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + net5.0 mjepson 1.0.0 SDK for use with the CM Voice API. @@ -18,6 +18,7 @@ + diff --git a/CM.Voice.VoiceApi.Sdk/Models/Events/Apps/CallQueuedEvent.cs b/CM.Voice.VoiceApi.Sdk/Models/Events/Apps/CallQueuedEvent.cs index 41bfcd8..410e4a1 100644 --- a/CM.Voice.VoiceApi.Sdk/Models/Events/Apps/CallQueuedEvent.cs +++ b/CM.Voice.VoiceApi.Sdk/Models/Events/Apps/CallQueuedEvent.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace CM.Voice.VoiceApi.Sdk.Models.Events.Apps { @@ -14,25 +14,25 @@ public class CallQueuedEvent : BaseEvent /// /// The id (e.g. number) of the caller. /// - [JsonProperty("caller", Order = 4)] + [JsonPropertyName("caller")] public string Caller { get; set; } /// /// The id (e.g. number) of the callee. /// - [JsonProperty("callee", Order = 5)] + [JsonPropertyName("callee")] public string Callee { get; set; } /// /// True iff the PlaceCallInstruction was accepted. /// - [JsonProperty("success", Order = 6)] + [JsonPropertyName("success")] public bool Success { get; set; } /// /// True iff the PlaceCallInstruction was accepted. /// - [JsonProperty("error", Order = 6, DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("error")] public string Error { get; set; } } } diff --git a/CM.Voice.VoiceApi.Sdk/Models/Events/BaseEvent.cs b/CM.Voice.VoiceApi.Sdk/Models/Events/BaseEvent.cs index 18955ae..4feca98 100644 --- a/CM.Voice.VoiceApi.Sdk/Models/Events/BaseEvent.cs +++ b/CM.Voice.VoiceApi.Sdk/Models/Events/BaseEvent.cs @@ -1,5 +1,5 @@ -using Newtonsoft.Json; -using System; +using System; +using System.Text.Json.Serialization; namespace CM.Voice.VoiceApi.Sdk.Models.Events { @@ -8,19 +8,19 @@ public abstract class BaseEvent /// /// The type of event. /// - [JsonProperty("type", Order = 1, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("type")] public string Type => EventType; /// /// The ID of the call this event belongs to. /// - [JsonProperty("call-id", Order = 2)] + [JsonPropertyName("call-id")] public Guid CallId { get; set; } /// /// The ID of the instruction the event is a result of. /// - [JsonProperty("instruction-id", Order = 3, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("instruction-id")] public string InstructionId { get; set; } /// diff --git a/CM.Voice.VoiceApi.Sdk/Models/Instructions/Apps/BaseAppInstruction.cs b/CM.Voice.VoiceApi.Sdk/Models/Instructions/Apps/BaseAppInstruction.cs index c185f85..3344bea 100644 --- a/CM.Voice.VoiceApi.Sdk/Models/Instructions/Apps/BaseAppInstruction.cs +++ b/CM.Voice.VoiceApi.Sdk/Models/Instructions/Apps/BaseAppInstruction.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace CM.Voice.VoiceApi.Sdk.Models.Instructions.Apps { @@ -10,50 +10,50 @@ public abstract class BaseAppInstruction /// /// The ID of the instruction. /// - [JsonProperty("instruction-id", Order = 3)] + [JsonPropertyName("instruction-id")] public string InstructionId { get; set; } /// /// The number to dial. /// - [JsonProperty("callee", Order = 4)] + [JsonPropertyName("callee")] public string Callee { get; set; } /// /// The numbers to dial. /// - [JsonProperty("callees", Order = 4)] + [JsonPropertyName("callees")] public string[] Callees { get; set; } /// /// The caller id to show on the end user's phone. /// - [JsonProperty("caller", Order = 5)] + [JsonPropertyName("caller")] public string Caller { get; set; } /// /// The caller id is hidden iff anonymous = true. /// - [JsonProperty("anonymous", Order = 6)] + [JsonPropertyName("anonymous")] public bool Anonymous { get; set; } /// /// Iff true, the request is not rejected if (any of) the callees are invalid. /// Please note that the invalid callees are not dialed, but the valid ones are. /// - [JsonProperty("disable-callees-validation", Order = 7)] + [JsonPropertyName("disable-callees-validation")] public bool DisableCalleesValidation { get; set; } /// /// Information on the voice to use if (any of) the prompt(s) is of type tts. /// - [JsonProperty("voice", Order = 99, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("voice")] public Voice Voice { get; set; } = new Voice(); /// /// The url to send the POST command to for further VoiceAPI flow. /// - [JsonProperty("callback-url", Order = 100, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("callback-url")] public string CallbackUrl { get; set; } } } \ No newline at end of file diff --git a/CM.Voice.VoiceApi.Sdk/Models/Instructions/Apps/NotificationInstruction.cs b/CM.Voice.VoiceApi.Sdk/Models/Instructions/Apps/NotificationInstruction.cs index 187cf14..4200f62 100644 --- a/CM.Voice.VoiceApi.Sdk/Models/Instructions/Apps/NotificationInstruction.cs +++ b/CM.Voice.VoiceApi.Sdk/Models/Instructions/Apps/NotificationInstruction.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace CM.Voice.VoiceApi.Sdk.Models.Instructions.Apps { @@ -10,43 +10,43 @@ public class NotificationInstruction : BaseAppInstruction /// /// The prompt, which is either the path and name of the file to play, or the string that needs to be tts-ed. /// - [JsonProperty("prompt", Order = 7, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("prompt")] public string Prompt { get; set; } /// /// The type of the prompt, either file or tts. /// - [JsonProperty("prompt-type", Order = 8, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("prompt-type")] public PromptType? PromptType { get; set; } = Models.PromptType.TTS; /// /// Determines the Voicemail detection flow. /// - [JsonProperty("voicemail-response", Order = 9)] + [JsonPropertyName("voicemail-response")] public VoicemailResponse VoicemailResponse { get; set; } = VoicemailResponse.Ignore; /// /// The number of times the code can be played. Min = 1, Max = 3. /// - [JsonProperty("max-replays", Order = 11, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("max-replays")] public int? MaxReplays { get; set; } /// /// The code-prompt and code will replay automatically repeat if true, it will wait for a press on the "1" otherwise. /// - [JsonProperty("auto-replay", Order = 12, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("auto-replay")] public bool? AutoReplay { get; set; } /// /// The prompt, which is either the path and name of the file to play, or the string that needs to be tts-ed. /// - [JsonProperty("replay-prompt", Order = 13, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("replay-prompt")] public string ReplayPrompt { get; set; } /// /// The type of the prompt, either file or tts. /// - [JsonProperty("replay-prompt-type", Order = 14, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("replay-prompt-type")] public PromptType? ReplayPromptType { get; set; } } } \ No newline at end of file diff --git a/CM.Voice.VoiceApi.Sdk/Models/Instructions/Apps/OtpInstruction.cs b/CM.Voice.VoiceApi.Sdk/Models/Instructions/Apps/OtpInstruction.cs index 056c5a3..e15ae1e 100644 --- a/CM.Voice.VoiceApi.Sdk/Models/Instructions/Apps/OtpInstruction.cs +++ b/CM.Voice.VoiceApi.Sdk/Models/Instructions/Apps/OtpInstruction.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace CM.Voice.VoiceApi.Sdk.Models.Instructions.Apps { @@ -10,79 +10,79 @@ public class OtpInstruction : BaseAppInstruction /// /// The prompt, which is either the path and name of the file to play, or the string that needs to be tts-ed. /// - [JsonProperty("intro-prompt", Order = 7, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("intro-prompt")] public string IntroPrompt { get; set; } /// /// The type of the prompt, either file or tts. /// - [JsonProperty("intro-prompt-type", Order = 8, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("intro-prompt-type")] public PromptType? IntroPromptType { get; set; } = PromptType.TTS; /// /// The prompt, which is either the path and name of the file to play, or the string that needs to be tts-ed. /// - [JsonProperty("code-prompt", Order = 9, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("code-prompt")] public string CodePrompt { get; set; } /// /// The type of the prompt, either file or tts. /// - [JsonProperty("code-prompt-type", Order = 10, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("code-prompt-type")] public PromptType? CodePromptType { get; set; } = PromptType.TTS; /// /// The OTP code. /// - [JsonProperty("code", Order = 11, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("code")] public string Code { get; set; } /// /// The type of the prompt, either file or tts. /// - [JsonProperty("code-type", Order = 12, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("code-type")] public CodeType? CodeType { get; set; } = Models.CodeType.TTS; /// /// The prompt, which is either the path and name of the file to play, or the string that needs to be tts-ed. /// - [JsonProperty("replay-prompt", Order = 13, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("replay-prompt")] public string ReplayPrompt { get; set; } /// /// The type of the prompt, either file or tts. /// - [JsonProperty("replay-prompt-type", Order = 14, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("replay-prompt-type")] public PromptType? ReplayPromptType { get; set; } = PromptType.TTS; /// /// The prompt, which is either the path and name of the file to play, or the string that needs to be tts-ed. /// - [JsonProperty("outro-prompt", Order = 15, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("outro-prompt")] public string OutroPrompt { get; set; } /// /// The type of the prompt, either file or tts. /// - [JsonProperty("outro-prompt-type", Order = 16, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("outro-prompt-type")] public PromptType? OutroPromptType { get; set; } = PromptType.TTS; /// /// The number of times the code can be played. Min = 1, Max = 3. /// - [JsonProperty("max-replays", Order = 17, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("max-replays")] public int? MaxReplays { get; set; } /// /// The code-prompt and code will replay automatically repeat if true, it will wait for a press on the "1" otherwise. /// - [JsonProperty("auto-replay", Order = 18, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("auto-replay")] public bool? AutoReplay { get; set; } /// /// Determines the Voicemail detection flow. /// - [JsonProperty("voicemail-response", Order = 19)] + [JsonPropertyName("voicemail-response")] public VoicemailResponse VoicemailResponse { get; set; } = VoicemailResponse.Ignore; } } \ No newline at end of file diff --git a/CM.Voice.VoiceApi.Sdk/Models/Instructions/Apps/RequestDtmfInstruction.cs b/CM.Voice.VoiceApi.Sdk/Models/Instructions/Apps/RequestDtmfInstruction.cs index c114ee2..b9201ce 100644 --- a/CM.Voice.VoiceApi.Sdk/Models/Instructions/Apps/RequestDtmfInstruction.cs +++ b/CM.Voice.VoiceApi.Sdk/Models/Instructions/Apps/RequestDtmfInstruction.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace CM.Voice.VoiceApi.Sdk.Models.Instructions.Apps { @@ -11,73 +11,73 @@ public class RequestDtmfInstruction : BaseAppInstruction /// /// The prompt, which is either the path and name of the file to play, or the string that needs to be tts-ed. /// - [JsonProperty("prompt", Order = 7, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("prompt")] public string Prompt { get; set; } /// /// The type of the prompt, either file or tts. /// - [JsonProperty("prompt-type", Order = 8, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("prompt-type")] public PromptType? PromptType { get; set; } = Models.PromptType.TTS; /// /// The prompt, which is either the path and name of the file to play, or the string that needs to be tts-ed. /// - [JsonProperty("valid-prompt", Order = 9, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("valid-prompt")] public string ValidPrompt { get; set; } /// /// The type of the prompt, either file or tts. /// - [JsonProperty("valid-prompt-type", Order = 10, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("valid-prompt-type")] public PromptType? ValidPromptType { get; set; } = Models.PromptType.TTS; /// /// The prompt, which is either the path and name of the file to play, or the string that needs to be tts-ed. /// - [JsonProperty("invalid-prompt", Order = 11, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("invalid-prompt")] public string InvalidPrompt { get; set; } /// /// The type of the prompt, either file or tts. /// - [JsonProperty("invalid-prompt-type", Order = 12, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("invalid-prompt-type")] public PromptType? InvalidPromptType { get; set; } = Models.PromptType.TTS; /// /// The minimum number of digits for the dtmf input /// - [JsonProperty("min-digits", Order = 13, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("min-digits")] public int? MinDigits { get; set; } /// /// The maximum number of digits for the dtmf input /// - [JsonProperty("max-digits", Order = 14, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("max-digits")] public int? MaxDigits { get; set; } /// /// The maximum number of attempts to input valid dtmf. /// - [JsonProperty("max-attempts", Order = 15, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("max-attempts")] public int? MaxAttempts { get; set; } /// /// The max timeout for pressing a button. /// - [JsonProperty("timeout", Order = 16, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("timeout")] public int? TimeOut { get; set; } /// /// The keys that will end dtmf input. /// - [JsonProperty("terminators", Order = 17, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("terminators")] public string Terminators { get; set; } /// /// The match to use for validating the input. /// - [JsonProperty("regex", Order = 18, NullValueHandling = NullValueHandling.Ignore)] + [JsonPropertyName("regex")] public string DigitsRegex { get; set; } } } \ No newline at end of file diff --git a/CM.Voice.VoiceApi.Sdk/Models/Voice.cs b/CM.Voice.VoiceApi.Sdk/Models/Voice.cs index e605d22..7fcb791 100644 --- a/CM.Voice.VoiceApi.Sdk/Models/Voice.cs +++ b/CM.Voice.VoiceApi.Sdk/Models/Voice.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace CM.Voice.VoiceApi.Sdk.Models { @@ -10,26 +10,26 @@ public class Voice /// /// The language (5 character locale) of the voice to use. Examples: en-US, en-GB, nl-NL. Defaults to en-GB /// - [JsonProperty("language", Order = 1)] + [JsonPropertyName("language")] public string Language { get; set; } = "en-GB"; /// /// The gender of the voice, either female or male. Defaults to Female. /// - [JsonProperty("gender", Order = 2)] + [JsonPropertyName("gender")] public Gender Gender { get; set; } = Gender.Female; /// /// Usually one, but if the selected language and gender support multiple voices, you can use this to make a selection between the different ones. Defaults to 1. /// - [JsonProperty("number", Order = 3)] + [JsonPropertyName("number")] public int Number { get; set; } = 1; /// /// Volume of the speaking voice. Defaults to 0. /// /// Allowed values are -4, -3, -2, -1, 0, 1, 2, 3 or 4. - [JsonProperty("volume", Order = 4)] + [JsonPropertyName("volume")] public sbyte Volume { get; set; } } } \ No newline at end of file diff --git a/CM.Voice.VoiceApi.Sdk/Models/VoiceApiResult.cs b/CM.Voice.VoiceApi.Sdk/Models/VoiceApiResult.cs index 9e1e237..fa2f5c0 100644 --- a/CM.Voice.VoiceApi.Sdk/Models/VoiceApiResult.cs +++ b/CM.Voice.VoiceApi.Sdk/Models/VoiceApiResult.cs @@ -1,5 +1,5 @@ using CM.Voice.VoiceApi.Sdk.Models.Events; -using Newtonsoft.Json; +using System.Text.Json; using System.Net; namespace CM.Voice.VoiceApi.Sdk.Models @@ -13,6 +13,6 @@ public class VoiceApiResult where TEvent : BaseEvent public string Content { get; set; } public TEvent DeserializeEvent() - => JsonConvert.DeserializeObject(Content); + => JsonSerializer.Deserialize(Content); } } \ No newline at end of file diff --git a/CM.Voice.VoiceApi.Sdk/VoiceApiClient.cs b/CM.Voice.VoiceApi.Sdk/VoiceApiClient.cs index 2d3ca4a..6d8357f 100644 --- a/CM.Voice.VoiceApi.Sdk/VoiceApiClient.cs +++ b/CM.Voice.VoiceApi.Sdk/VoiceApiClient.cs @@ -1,7 +1,7 @@ using CM.Voice.VoiceApi.Sdk.Models; using CM.Voice.VoiceApi.Sdk.Models.Events.Apps; using CM.Voice.VoiceApi.Sdk.Models.Instructions.Apps; -using Newtonsoft.Json; +using System.Text.Json; using System; using System.Net.Http; using System.Text; @@ -42,8 +42,7 @@ public async Task> SendAsync(BaseAppInstruction using (var request = new HttpRequestMessage(HttpMethod.Post, _url + urlSuffix)) { request.Headers.Add(ApiKeyHeader, _apiKey.ToString()); - request.Content = new StringContent(JsonConvert.SerializeObject(instruction), Encoding.UTF8, "application/json"); - + request.Content = new StringContent(JsonSerializer.Serialize(Convert.ChangeType(instruction, instruction.GetType())), Encoding.UTF8, "application/json"); using (var result = await _httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false)) { cancellationToken.ThrowIfCancellationRequested(); diff --git a/Tests/ClientTests.cs b/Tests/ClientTests.cs index 4af840d..ab01a71 100644 --- a/Tests/ClientTests.cs +++ b/Tests/ClientTests.cs @@ -2,7 +2,7 @@ using CM.Voice.VoiceApi.Sdk.Models; using CM.Voice.VoiceApi.Sdk.Models.Events.Apps; using CM.Voice.VoiceApi.Sdk.Models.Instructions.Apps; -using Newtonsoft.Json; +using System.Text.Json; using System; using System.Collections.Generic; using System.Linq; @@ -64,7 +64,8 @@ public async Task TestNotification() var (httpRequestMessage, content) = handler.RequestMessages.First(); Assert.Equal(Url + "/Notification", httpRequestMessage.RequestUri.AbsoluteUri); Assert.Equal(HttpMethod.Post, httpRequestMessage.Method); - var json = JsonConvert.SerializeObject(instruction); + //var json = JsonConvert.SerializeObject(instruction); + var json = JsonSerializer.Serialize(instruction); Assert.Equal(json, content); } @@ -103,7 +104,8 @@ public async Task TestOtp() var (httpRequestMessage, content) = handler.RequestMessages.First(); Assert.Equal(Url + "/OTP", httpRequestMessage.RequestUri.AbsoluteUri); Assert.Equal(HttpMethod.Post, httpRequestMessage.Method); - var json = JsonConvert.SerializeObject(instruction); + //var json = JsonConvert.SerializeObject(instruction); + var json = JsonSerializer.Serialize(instruction); Assert.Equal(json, content); } @@ -149,7 +151,8 @@ public async Task TestDtmf() var (httpRequestMessage, content) = handler.RequestMessages.First(); Assert.Equal(Url + "/DTMF", httpRequestMessage.RequestUri.AbsoluteUri); Assert.Equal(HttpMethod.Post, httpRequestMessage.Method); - var json = JsonConvert.SerializeObject(instruction); + //var json = JsonConvert.SerializeObject(instruction); + var json = JsonSerializer.Serialize(instruction); Assert.Equal(json, content); } @@ -179,7 +182,8 @@ public async Task TestCallQueuedEvent() }; var responseMessage = new HttpResponseMessage(HttpStatusCode.OK); - var evtJson = JsonConvert.SerializeObject(evt); + //var evtJson = JsonConvert.SerializeObject(evt); + var evtJson = JsonSerializer.Serialize(evt); responseMessage.Content = new StringContent(evtJson); var handler = new MockHttpMessageHandler { @@ -228,7 +232,8 @@ public async Task TestObsoleteNotification() var (httpRequestMessage, content) = handler.RequestMessages.First(); Assert.Equal(Url + "/Notification", httpRequestMessage.RequestUri.AbsoluteUri); Assert.Equal(HttpMethod.Post, httpRequestMessage.Method); - var json = JsonConvert.SerializeObject(instruction); + //var json = JsonConvert.SerializeObject(instruction); + var json = JsonSerializer.Serialize(instruction); Assert.Equal(json, content); } @@ -267,7 +272,8 @@ public async Task TestObsoleteOtp() var (httpRequestMessage, content) = handler.RequestMessages.First(); Assert.Equal(Url + "/OTP", httpRequestMessage.RequestUri.AbsoluteUri); Assert.Equal(HttpMethod.Post, httpRequestMessage.Method); - var json = JsonConvert.SerializeObject(instruction); + //var json = JsonConvert.SerializeObject(instruction); + var json = JsonSerializer.Serialize(instruction); Assert.Equal(json, content); } @@ -313,7 +319,8 @@ public async Task TestObsoleteDtmf() var (httpRequestMessage, content) = handler.RequestMessages.First(); Assert.Equal(Url + "/DTMF", httpRequestMessage.RequestUri.AbsoluteUri); Assert.Equal(HttpMethod.Post, httpRequestMessage.Method); - var json = JsonConvert.SerializeObject(instruction); + //var json = JsonConvert.SerializeObject(instruction); + var json = JsonSerializer.Serialize(instruction); Assert.Equal(json, content); } @@ -344,7 +351,8 @@ public async Task TestObsoleteCallQueuedEvent() }; var responseMessage = new HttpResponseMessage(HttpStatusCode.OK); - var evtJson = JsonConvert.SerializeObject(evt); + //var evtJson = JsonConvert.SerializeObject(evt); + var evtJson = JsonSerializer.Serialize(evt); responseMessage.Content = new StringContent(evtJson); var handler = new MockHttpMessageHandler { diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 1d98487..ca97e14 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp2.0 + net5.0 false