Add a System.Text.Json based TempDataSerializer (#8874)
* Add a System.Text.Json based TempDataSerializer * Update DefaultTempDataSerializer * Add common tests for DefaultTempDataSerializer & BsonTempDataSerializer * Remove uses of NewtonsoftJson in tests solely required for temp-data support Fixes https://github.com/aspnet/AspNetCore/issues/7255
This commit is contained in:
parent
8499a27c7f
commit
1b868323e8
|
|
@ -149,7 +149,7 @@ namespace Microsoft.AspNetCore.Mvc.NewtonsoftJson
|
|||
}
|
||||
else
|
||||
{
|
||||
return new byte[0];
|
||||
return Array.Empty<byte>();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -165,6 +165,8 @@ namespace Microsoft.AspNetCore.Mvc.NewtonsoftJson
|
|||
}
|
||||
}
|
||||
|
||||
public override bool CanSerializeType(Type type) => CanSerializeType(type, out _);
|
||||
|
||||
private static bool CanSerializeType(Type typeToSerialize, out string errorMessage)
|
||||
{
|
||||
typeToSerialize = typeToSerialize ?? throw new ArgumentNullException(nameof(typeToSerialize));
|
||||
|
|
@ -208,6 +210,8 @@ namespace Microsoft.AspNetCore.Mvc.NewtonsoftJson
|
|||
}
|
||||
|
||||
actualType = actualType ?? typeToSerialize;
|
||||
actualType = Nullable.GetUnderlyingType(actualType) ?? actualType;
|
||||
|
||||
if (!IsSimpleType(actualType))
|
||||
{
|
||||
errorMessage = Resources.FormatTempData_CannotSerializeType(
|
||||
|
|
|
|||
|
|
@ -3,12 +3,15 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures.Infrastructure;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.NewtonsoftJson
|
||||
{
|
||||
public class BsonTempDataSerializerTest
|
||||
public class BsonTempDataSerializerTest : TempDataSerializerTestBase
|
||||
{
|
||||
protected override TempDataSerializer GetTempDataSerializer() => new BsonTempDataSerializer();
|
||||
|
||||
public static TheoryData<object, Type> InvalidTypes
|
||||
{
|
||||
get
|
||||
|
|
@ -93,6 +96,112 @@ namespace Microsoft.AspNetCore.Mvc.NewtonsoftJson
|
|||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RoundTripTest_ArrayOfIntegers()
|
||||
{
|
||||
// Arrange
|
||||
var key = "test-key";
|
||||
var value = new[] { 1, -2, 3 };
|
||||
var testProvider = GetTempDataSerializer();
|
||||
var input = new Dictionary<string, object>
|
||||
{
|
||||
{ key, value },
|
||||
};
|
||||
|
||||
// Act
|
||||
var bytes = testProvider.Serialize(input);
|
||||
var values = testProvider.Deserialize(bytes);
|
||||
|
||||
// Assert
|
||||
var roundTripValue = Assert.IsType<int[]>(values[key]);
|
||||
Assert.Equal(value, roundTripValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RoundTripTest_DateTime()
|
||||
{
|
||||
// Arrange
|
||||
var key = "test-key";
|
||||
var value = new DateTime(2007, 1, 1);
|
||||
var testProvider = GetTempDataSerializer();
|
||||
var input = new Dictionary<string, object>
|
||||
{
|
||||
{ key, value },
|
||||
};
|
||||
|
||||
// Act
|
||||
var bytes = testProvider.Serialize(input);
|
||||
var values = testProvider.Deserialize(bytes);
|
||||
|
||||
// Assert
|
||||
var roundTripValue = Assert.IsType<DateTime>(values[key]);
|
||||
Assert.Equal(value, roundTripValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RoundTripTest_Guid()
|
||||
{
|
||||
// Arrange
|
||||
var key = "test-key";
|
||||
var value = Guid.NewGuid();
|
||||
var testProvider = GetTempDataSerializer();
|
||||
var input = new Dictionary<string, object>
|
||||
{
|
||||
{ key, value },
|
||||
};
|
||||
|
||||
// Act
|
||||
var bytes = testProvider.Serialize(input);
|
||||
var values = testProvider.Deserialize(bytes);
|
||||
|
||||
// Assert
|
||||
var roundTripValue = Assert.IsType<Guid>(values[key]);
|
||||
Assert.Equal(value, roundTripValue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(2147483648)]
|
||||
[InlineData(-2147483649)]
|
||||
public void RoundTripTest_LongValue(long value)
|
||||
{
|
||||
// Arrange
|
||||
var key = "test-key";
|
||||
var testProvider = GetTempDataSerializer();
|
||||
var input = new Dictionary<string, object>
|
||||
{
|
||||
{ key, value },
|
||||
};
|
||||
|
||||
// Act
|
||||
var bytes = testProvider.Serialize(input);
|
||||
var values = testProvider.Deserialize(bytes);
|
||||
|
||||
// Assert
|
||||
var roundTripValue = Assert.IsType<long>(values[key]);
|
||||
Assert.Equal(value, roundTripValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RoundTripTest_Double()
|
||||
{
|
||||
// Arrange
|
||||
var key = "test-key";
|
||||
var value = 10d;
|
||||
var testProvider = GetTempDataSerializer();
|
||||
var input = new Dictionary<string, object>
|
||||
{
|
||||
{ key, value },
|
||||
};
|
||||
|
||||
// Act
|
||||
var bytes = testProvider.Serialize(input);
|
||||
var values = testProvider.Deserialize(bytes);
|
||||
|
||||
// Assert
|
||||
var roundTripValue = (double)values[key];
|
||||
Assert.Equal(value, roundTripValue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(ValidTypes))]
|
||||
public void EnsureObjectCanBeSerialized_DoesNotThrow_OnValidType(object value)
|
||||
|
|
@ -104,40 +213,6 @@ namespace Microsoft.AspNetCore.Mvc.NewtonsoftJson
|
|||
testProvider.EnsureObjectCanBeSerialized(value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DeserializeTempData_ReturnsEmptyDictionary_DataIsEmpty()
|
||||
{
|
||||
// Arrange
|
||||
var serializer = new BsonTempDataSerializer();
|
||||
|
||||
// Act
|
||||
var tempDataDictionary = serializer.Deserialize(new byte[0]);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(tempDataDictionary);
|
||||
Assert.Empty(tempDataDictionary);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SerializeAndDeserialize_NullValue_RoundTripsSuccessfully()
|
||||
{
|
||||
// Arrange
|
||||
var key = "NullKey";
|
||||
var testProvider = new BsonTempDataSerializer();
|
||||
var input = new Dictionary<string, object>
|
||||
{
|
||||
{ key, null }
|
||||
};
|
||||
|
||||
// Act
|
||||
var bytes = testProvider.Serialize(input);
|
||||
var values = testProvider.Deserialize(bytes);
|
||||
|
||||
// Assert
|
||||
Assert.True(values.ContainsKey(key));
|
||||
Assert.Null(values[key]);
|
||||
}
|
||||
|
||||
private class TestItem
|
||||
{
|
||||
public int DummyInt { get; set; }
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
<ItemGroup>
|
||||
<Compile Include="..\..\Mvc.Core\test\Formatters\JsonInputFormatterTestBase.cs" />
|
||||
<Compile Include="..\..\Mvc.Core\test\Formatters\JsonOutputFormatterTestBase.cs" />
|
||||
<Compile Include="..\..\Mvc.ViewFeatures\test\Infrastructure\TempDataSerializerTestBase.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ using System;
|
|||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures.Infrastructure;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ApplicationModels
|
||||
|
|
@ -44,6 +44,23 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
|
|||
Assert.Equal(expected, ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OnProvidersExecuting_ThrowsIfThePropertyTypeIsUnsupported()
|
||||
{
|
||||
// Arrange
|
||||
var type = typeof(TestPageModel_InvalidProperties);
|
||||
var expected = $"TempData serializer '{typeof(DefaultTempDataSerializer)}' cannot serialize property '{type}.ModelState' of type '{typeof(ModelStateDictionary)}'." +
|
||||
Environment.NewLine +
|
||||
$"TempData serializer '{typeof(DefaultTempDataSerializer)}' cannot serialize property '{type}.TimeZone' of type '{typeof(TimeZoneInfo)}'.";
|
||||
|
||||
var provider = CreateProvider();
|
||||
var context = CreateProviderContext(type);
|
||||
|
||||
// Act & Assert
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => provider.OnProvidersExecuting(context));
|
||||
Assert.Equal(expected, ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AddsTempDataPropertyFilter_ForTempDataAttributeProperties()
|
||||
{
|
||||
|
|
@ -114,18 +131,9 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
|
|||
return context;
|
||||
}
|
||||
|
||||
private static CompiledPageActionDescriptor CreateDescriptor(Type type)
|
||||
{
|
||||
return new CompiledPageActionDescriptor(new PageActionDescriptor())
|
||||
{
|
||||
PageTypeInfo = typeof(TestPage).GetTypeInfo(),
|
||||
HandlerTypeInfo = type.GetTypeInfo(),
|
||||
};
|
||||
}
|
||||
|
||||
private static TempDataFilterPageApplicationModelProvider CreateProvider()
|
||||
{
|
||||
var tempDataSerializer = Mock.Of<TempDataSerializer>(s => s.CanSerializeType(It.IsAny<Type>()) == true);
|
||||
var tempDataSerializer = new DefaultTempDataSerializer();
|
||||
return new TempDataFilterPageApplicationModelProvider(tempDataSerializer);
|
||||
}
|
||||
|
||||
|
|
@ -160,5 +168,17 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
|
|||
[TempData]
|
||||
public string Test { get; private set; }
|
||||
}
|
||||
|
||||
public class TestPageModel_InvalidProperties
|
||||
{
|
||||
[TempData]
|
||||
public ModelStateDictionary ModelState { get; set; }
|
||||
|
||||
[TempData]
|
||||
public int SomeProperty { get; set; }
|
||||
|
||||
[TempData]
|
||||
public TimeZoneInfo TimeZone { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures.Infrastructure;
|
||||
|
|
@ -86,6 +87,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Filters
|
|||
Type type)
|
||||
{
|
||||
List<LifecycleProperty> results = null;
|
||||
var errorMessages = new List<string>();
|
||||
|
||||
var propertyHelpers = PropertyHelper.GetVisibleProperties(type: type);
|
||||
for (var i = 0; i < propertyHelpers.Length; i++)
|
||||
|
|
@ -93,9 +95,8 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Filters
|
|||
var propertyHelper = propertyHelpers[i];
|
||||
var property = propertyHelper.Property;
|
||||
var tempDataAttribute = property.GetCustomAttribute<TempDataAttribute>();
|
||||
if (tempDataAttribute != null)
|
||||
if (tempDataAttribute != null && ValidateProperty(tempDataSerializer, errorMessages, propertyHelper.Property))
|
||||
{
|
||||
ValidateProperty(tempDataSerializer, propertyHelper.Property);
|
||||
if (results == null)
|
||||
{
|
||||
results = new List<LifecycleProperty>();
|
||||
|
|
@ -111,28 +112,41 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Filters
|
|||
}
|
||||
}
|
||||
|
||||
if (errorMessages.Count > 0)
|
||||
{
|
||||
throw new InvalidOperationException(string.Join(Environment.NewLine, errorMessages));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private static void ValidateProperty(TempDataSerializer tempDataSerializer, PropertyInfo property)
|
||||
private static bool ValidateProperty(TempDataSerializer tempDataSerializer, List<string> errorMessages, PropertyInfo property)
|
||||
{
|
||||
if (!(property.SetMethod != null &&
|
||||
property.SetMethod.IsPublic &&
|
||||
property.GetMethod != null &&
|
||||
property.GetMethod.IsPublic))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
errorMessages.Add(
|
||||
Resources.FormatTempDataProperties_PublicGetterSetter(property.DeclaringType.FullName, property.Name, nameof(TempDataAttribute)));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!tempDataSerializer.CanSerializeType(property.PropertyType))
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatTempDataProperties_InvalidType(
|
||||
var errorMessage = Resources.FormatTempDataProperties_InvalidType(
|
||||
tempDataSerializer.GetType().FullName,
|
||||
TypeNameHelper.GetTypeDisplayName(property.DeclaringType),
|
||||
property.Name,
|
||||
TypeNameHelper.GetTypeDisplayName(property.PropertyType)));
|
||||
TypeNameHelper.GetTypeDisplayName(property.PropertyType));
|
||||
|
||||
errorMessages.Add(errorMessage);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,180 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Infrastructure
|
||||
{
|
||||
// Note: this is currently an internal class that will be replaced with a shared version.
|
||||
internal sealed class ArrayBufferWriter<T> : IBufferWriter<T>, IDisposable
|
||||
{
|
||||
private T[] _rentedBuffer;
|
||||
private int _index;
|
||||
|
||||
private const int MinimumBufferSize = 256;
|
||||
|
||||
public ArrayBufferWriter()
|
||||
{
|
||||
_rentedBuffer = ArrayPool<T>.Shared.Rent(MinimumBufferSize);
|
||||
_index = 0;
|
||||
}
|
||||
|
||||
public ArrayBufferWriter(int initialCapacity)
|
||||
{
|
||||
if (initialCapacity <= 0)
|
||||
throw new ArgumentException(nameof(initialCapacity));
|
||||
|
||||
_rentedBuffer = ArrayPool<T>.Shared.Rent(initialCapacity);
|
||||
_index = 0;
|
||||
}
|
||||
|
||||
public ReadOnlyMemory<T> WrittenMemory
|
||||
{
|
||||
get
|
||||
{
|
||||
CheckIfDisposed();
|
||||
|
||||
return _rentedBuffer.AsMemory(0, _index);
|
||||
}
|
||||
}
|
||||
|
||||
public int WrittenCount
|
||||
{
|
||||
get
|
||||
{
|
||||
CheckIfDisposed();
|
||||
|
||||
return _index;
|
||||
}
|
||||
}
|
||||
|
||||
public int Capacity
|
||||
{
|
||||
get
|
||||
{
|
||||
CheckIfDisposed();
|
||||
|
||||
return _rentedBuffer.Length;
|
||||
}
|
||||
}
|
||||
|
||||
public int FreeCapacity
|
||||
{
|
||||
get
|
||||
{
|
||||
CheckIfDisposed();
|
||||
|
||||
return _rentedBuffer.Length - _index;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
CheckIfDisposed();
|
||||
|
||||
ClearHelper();
|
||||
}
|
||||
|
||||
private void ClearHelper()
|
||||
{
|
||||
Debug.Assert(_rentedBuffer != null);
|
||||
|
||||
_rentedBuffer.AsSpan(0, _index).Clear();
|
||||
_index = 0;
|
||||
}
|
||||
|
||||
// Returns the rented buffer back to the pool
|
||||
public void Dispose()
|
||||
{
|
||||
if (_rentedBuffer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ClearHelper();
|
||||
ArrayPool<T>.Shared.Return(_rentedBuffer);
|
||||
_rentedBuffer = null;
|
||||
}
|
||||
|
||||
private void CheckIfDisposed()
|
||||
{
|
||||
if (_rentedBuffer == null)
|
||||
{
|
||||
throw new ObjectDisposedException(nameof(ArrayBufferWriter<T>));
|
||||
}
|
||||
}
|
||||
|
||||
public void Advance(int count)
|
||||
{
|
||||
CheckIfDisposed();
|
||||
|
||||
if (count < 0)
|
||||
throw new ArgumentException(nameof(count));
|
||||
|
||||
if (_index > _rentedBuffer.Length - count)
|
||||
ThrowInvalidOperationException(_rentedBuffer.Length);
|
||||
|
||||
_index += count;
|
||||
}
|
||||
|
||||
public Memory<T> GetMemory(int sizeHint = 0)
|
||||
{
|
||||
CheckIfDisposed();
|
||||
|
||||
CheckAndResizeBuffer(sizeHint);
|
||||
return _rentedBuffer.AsMemory(_index);
|
||||
}
|
||||
|
||||
public Span<T> GetSpan(int sizeHint = 0)
|
||||
{
|
||||
CheckIfDisposed();
|
||||
|
||||
CheckAndResizeBuffer(sizeHint);
|
||||
return _rentedBuffer.AsSpan(_index);
|
||||
}
|
||||
|
||||
private void CheckAndResizeBuffer(int sizeHint)
|
||||
{
|
||||
Debug.Assert(_rentedBuffer != null);
|
||||
|
||||
if (sizeHint < 0)
|
||||
throw new ArgumentException(nameof(sizeHint));
|
||||
|
||||
if (sizeHint == 0)
|
||||
{
|
||||
sizeHint = MinimumBufferSize;
|
||||
}
|
||||
|
||||
int availableSpace = _rentedBuffer.Length - _index;
|
||||
|
||||
if (sizeHint > availableSpace)
|
||||
{
|
||||
int growBy = Math.Max(sizeHint, _rentedBuffer.Length);
|
||||
|
||||
int newSize = checked(_rentedBuffer.Length + growBy);
|
||||
|
||||
T[] oldBuffer = _rentedBuffer;
|
||||
|
||||
_rentedBuffer = ArrayPool<T>.Shared.Rent(newSize);
|
||||
|
||||
Debug.Assert(oldBuffer.Length >= _index);
|
||||
Debug.Assert(_rentedBuffer.Length >= _index);
|
||||
|
||||
Span<T> previousBuffer = oldBuffer.AsSpan(0, _index);
|
||||
previousBuffer.CopyTo(_rentedBuffer);
|
||||
previousBuffer.Clear();
|
||||
ArrayPool<T>.Shared.Return(oldBuffer);
|
||||
}
|
||||
|
||||
Debug.Assert(_rentedBuffer.Length - _index > 0);
|
||||
Debug.Assert(_rentedBuffer.Length - _index >= sizeHint);
|
||||
}
|
||||
|
||||
private static void ThrowInvalidOperationException(int capacity)
|
||||
{
|
||||
throw new InvalidOperationException($"Cannot advance past the end of the buffer, which has a size of {capacity}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,30 +3,157 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Globalization;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Infrastructure
|
||||
{
|
||||
internal class DefaultTempDataSerializer : TempDataSerializer
|
||||
{
|
||||
public override IDictionary<string, object> Deserialize(byte[] unprotectedData)
|
||||
public override IDictionary<string, object> Deserialize(byte[] value)
|
||||
{
|
||||
throw new InvalidOperationException(Core.Resources.FormatReferenceToNewtonsoftJsonRequired(
|
||||
Resources.DeserializingTempData,
|
||||
"Microsoft.AspNetCore.Mvc.NewtonsoftJson",
|
||||
nameof(IMvcBuilder),
|
||||
"AddNewtonsoftJson",
|
||||
"ConfigureServices(...)"));
|
||||
if (value == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
|
||||
if (value.Length == 0)
|
||||
{
|
||||
return new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
using var jsonDocument = JsonDocument.Parse(value);
|
||||
var rootElement = jsonDocument.RootElement;
|
||||
return DeserializeDictionary(rootElement);
|
||||
}
|
||||
|
||||
private IDictionary<string, object> DeserializeDictionary(JsonElement rootElement)
|
||||
{
|
||||
var deserialized = new Dictionary<string, object>(StringComparer.Ordinal);
|
||||
|
||||
foreach (var item in rootElement.EnumerateObject())
|
||||
{
|
||||
object deserializedValue;
|
||||
switch (item.Value.Type)
|
||||
{
|
||||
case JsonValueType.False:
|
||||
case JsonValueType.True:
|
||||
deserializedValue = item.Value.GetBoolean();
|
||||
break;
|
||||
|
||||
case JsonValueType.Number:
|
||||
deserializedValue = item.Value.GetInt32();
|
||||
break;
|
||||
|
||||
case JsonValueType.String:
|
||||
var stringValue = item.Value.GetString();
|
||||
// BsonTempDataSerializer will parse certain types of string values. We'll attempt to imitiate it.
|
||||
if (DateTime.TryParseExact(stringValue, "r", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var dateTime))
|
||||
{
|
||||
deserializedValue = dateTime;
|
||||
}
|
||||
else if (Guid.TryParseExact(stringValue, "B", out var guid))
|
||||
{
|
||||
deserializedValue = guid;
|
||||
}
|
||||
else
|
||||
{
|
||||
deserializedValue = stringValue;
|
||||
}
|
||||
break;
|
||||
|
||||
case JsonValueType.Null:
|
||||
deserializedValue = null;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException(Resources.FormatTempData_CannotDeserializeType(item.Value.Type));
|
||||
}
|
||||
|
||||
deserialized[item.Name] = deserializedValue;
|
||||
}
|
||||
|
||||
return deserialized;
|
||||
}
|
||||
|
||||
public override byte[] Serialize(IDictionary<string, object> values)
|
||||
{
|
||||
throw new InvalidOperationException(Core.Resources.FormatReferenceToNewtonsoftJsonRequired(
|
||||
Resources.SerializingTempData,
|
||||
"Microsoft.AspNetCore.Mvc.NewtonsoftJson",
|
||||
nameof(IMvcBuilder),
|
||||
"AddNewtonsoftJson",
|
||||
"ConfigureServices(...)"));
|
||||
if (values == null || values.Count == 0)
|
||||
{
|
||||
return Array.Empty<byte>();
|
||||
}
|
||||
|
||||
using (var bufferWriter = new ArrayBufferWriter<byte>())
|
||||
{
|
||||
var writer = new Utf8JsonWriter(bufferWriter);
|
||||
writer.WriteStartObject();
|
||||
foreach (var (key, value) in values)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
writer.WriteNull(key);
|
||||
continue;
|
||||
}
|
||||
|
||||
// We want to allow only simple types to be serialized.
|
||||
if (!CanSerializeType(value.GetType()))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
Resources.FormatTempData_CannotSerializeType(
|
||||
typeof(DefaultTempDataSerializer).FullName,
|
||||
value.GetType()));
|
||||
}
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case Enum _:
|
||||
writer.WriteNumber(key, (int)value);
|
||||
break;
|
||||
|
||||
case string stringValue:
|
||||
writer.WriteString(key, stringValue);
|
||||
break;
|
||||
|
||||
case int intValue:
|
||||
writer.WriteNumber(key, intValue);
|
||||
break;
|
||||
|
||||
case bool boolValue:
|
||||
writer.WriteBoolean(key, boolValue);
|
||||
break;
|
||||
|
||||
case DateTime dateTime:
|
||||
writer.WriteString(key, dateTime.ToString("r", CultureInfo.InvariantCulture));
|
||||
break;
|
||||
|
||||
case Guid guid:
|
||||
writer.WriteString(key, guid.ToString("B", CultureInfo.InvariantCulture));
|
||||
break;
|
||||
}
|
||||
}
|
||||
writer.WriteEndObject();
|
||||
writer.Flush();
|
||||
|
||||
return bufferWriter.WrittenMemory.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanSerializeType(Type type)
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
}
|
||||
|
||||
type = Nullable.GetUnderlyingType(type) ?? type;
|
||||
|
||||
return
|
||||
type.IsEnum ||
|
||||
type == typeof(int) ||
|
||||
type == typeof(string) ||
|
||||
type == typeof(bool) ||
|
||||
type == typeof(DateTime) ||
|
||||
type == typeof(Guid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -808,6 +808,34 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
|||
internal static string FormatSerializingTempData()
|
||||
=> GetString("SerializingTempData");
|
||||
|
||||
/// <summary>
|
||||
/// The '{0}' cannot serialize an object of type '{1}'.
|
||||
/// </summary>
|
||||
internal static string TempData_CannotSerializeType
|
||||
{
|
||||
get => GetString("TempData_CannotSerializeType");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The '{0}' cannot serialize an object of type '{1}'.
|
||||
/// </summary>
|
||||
internal static string FormatTempData_CannotSerializeType(object p0, object p1)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("TempData_CannotSerializeType"), p0, p1);
|
||||
|
||||
/// <summary>
|
||||
/// Unsupported data type '{0}'.
|
||||
/// </summary>
|
||||
internal static string TempData_CannotDeserializeType
|
||||
{
|
||||
get => GetString("TempData_CannotDeserializeType");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unsupported data type '{0}'.
|
||||
/// </summary>
|
||||
internal static string FormatTempData_CannotDeserializeType(object p0)
|
||||
=> string.Format(CultureInfo.CurrentCulture, GetString("TempData_CannotDeserializeType"), p0);
|
||||
|
||||
private static string GetString(string name, params string[] formatterNames)
|
||||
{
|
||||
var value = _resourceManager.GetString(name);
|
||||
|
|
|
|||
|
|
@ -289,4 +289,10 @@
|
|||
<data name="SerializingTempData" xml:space="preserve">
|
||||
<value>Serializing TempDataDictionary</value>
|
||||
</data>
|
||||
<data name="TempData_CannotSerializeType" xml:space="preserve">
|
||||
<value>The '{0}' cannot serialize an object of type '{1}'.</value>
|
||||
</data>
|
||||
<data name="TempData_CannotDeserializeType" xml:space="preserve">
|
||||
<value>Unsupported data type '{0}'.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -8,7 +8,6 @@ using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
|||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures.Infrastructure;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Filters
|
||||
|
|
@ -48,20 +47,20 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Filters
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void AddsTempDataPropertyFilter_ForTempDataAttributeProperties()
|
||||
public void OnProvidersExecuting_ThrowsIfThePropertyTypeIsUnsupported()
|
||||
{
|
||||
// Arrange
|
||||
var type = typeof(TestController_NullableNonPrimitiveTempDataProperty);
|
||||
var type = typeof(TestController_InvalidProperties);
|
||||
var expected = $"TempData serializer '{typeof(DefaultTempDataSerializer)}' cannot serialize property '{type}.ModelState' of type '{typeof(ModelStateDictionary)}'." +
|
||||
Environment.NewLine +
|
||||
$"TempData serializer '{typeof(DefaultTempDataSerializer)}' cannot serialize property '{type}.TimeZone' of type '{typeof(TimeZoneInfo)}'.";
|
||||
var provider = CreateProvider();
|
||||
|
||||
var context = GetContext(type);
|
||||
|
||||
// Act
|
||||
provider.OnProvidersExecuting(context);
|
||||
|
||||
// Assert
|
||||
var controller = Assert.Single(context.Result.Controllers);
|
||||
Assert.IsType<ControllerSaveTempDataPropertyFilterFactory>(Assert.Single(controller.Filters));
|
||||
// Act & Assert
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => provider.OnProvidersExecuting(context));
|
||||
Assert.Equal(expected, ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -109,7 +108,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Filters
|
|||
|
||||
private static TempDataApplicationModelProvider CreateProvider()
|
||||
{
|
||||
var tempDataSerializer = Mock.Of<TempDataSerializer>(s => s.CanSerializeType(It.IsAny<Type>()) == true);
|
||||
var tempDataSerializer = new DefaultTempDataSerializer();
|
||||
return new TempDataApplicationModelProvider(tempDataSerializer);
|
||||
}
|
||||
|
||||
|
|
@ -129,12 +128,6 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Filters
|
|||
public DateTime? DateTime { get; set; }
|
||||
}
|
||||
|
||||
public class TestController_NullableNonPrimitiveTempDataProperty
|
||||
{
|
||||
[TempData]
|
||||
public DateTime? DateTime { get; set; }
|
||||
}
|
||||
|
||||
public class TestController_OneTempDataProperty
|
||||
{
|
||||
public string Test { get; set; }
|
||||
|
|
@ -148,5 +141,17 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Filters
|
|||
[TempData]
|
||||
public string Test { get; private set; }
|
||||
}
|
||||
|
||||
public class TestController_InvalidProperties
|
||||
{
|
||||
[TempData]
|
||||
public ModelStateDictionary ModelState { get; set; }
|
||||
|
||||
[TempData]
|
||||
public int SomeProperty { get; set; }
|
||||
|
||||
[TempData]
|
||||
public TimeZoneInfo TimeZone { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Infrastructure
|
||||
{
|
||||
public class DefaultTempDataSerializerTest : TempDataSerializerTestBase
|
||||
{
|
||||
protected override TempDataSerializer GetTempDataSerializer() => new DefaultTempDataSerializer();
|
||||
|
||||
[Fact]
|
||||
public void RoundTripTest_StringThatLooksLikeCompliantDateTime()
|
||||
{
|
||||
// This is an unintentional side-effect of trying to support a compat with JSON.NET.
|
||||
// Any string that looks like a compliant DateTime object will be parsed as a DateTime.
|
||||
// This test documents this behavior.
|
||||
// Arrange
|
||||
var key = "test-key";
|
||||
var testProvider = GetTempDataSerializer();
|
||||
var value = new DateTime(2009, 1, 1, 12, 37, 43);
|
||||
var input = new Dictionary<string, object>
|
||||
{
|
||||
{ key, value.ToString("r") }
|
||||
};
|
||||
|
||||
// Act
|
||||
var bytes = testProvider.Serialize(input);
|
||||
var values = testProvider.Deserialize(bytes);
|
||||
|
||||
// Assert
|
||||
var roundTripValue = Assert.IsType<DateTime>(values[key]);
|
||||
Assert.Equal(value, roundTripValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RoundTripTest_StringThatIsNotCompliantDateTime()
|
||||
{
|
||||
// This is an unintentional side-effect of trying to support a compat with JSON.NET.
|
||||
// Any string that looks like a compliant DateTime object will be parsed as a DateTime.
|
||||
// This test documents this behavior.
|
||||
// Arrange
|
||||
var key = "test-key";
|
||||
var testProvider = GetTempDataSerializer();
|
||||
var value = new DateTime(2009, 1, 1, 12, 37, 43);
|
||||
var input = new Dictionary<string, object>
|
||||
{
|
||||
{ key, value.ToString() }
|
||||
};
|
||||
|
||||
// Act
|
||||
var bytes = testProvider.Serialize(input);
|
||||
var values = testProvider.Deserialize(bytes);
|
||||
|
||||
// Assert
|
||||
var roundTripValue = Assert.IsType<string>(values[key]);
|
||||
Assert.Equal(value.ToString(), roundTripValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RoundTripTest_StringThatIsNotCompliantGuid()
|
||||
{
|
||||
// This is an unintentional side-effect of trying to support a compat with JSON.NET.
|
||||
// Any string that looks like a compliant DateTime object will be parsed as a DateTime.
|
||||
// This test documents this behavior.
|
||||
// Arrange
|
||||
var key = "test-key";
|
||||
var testProvider = GetTempDataSerializer();
|
||||
var value = Guid.NewGuid();
|
||||
var input = new Dictionary<string, object>
|
||||
{
|
||||
{ key, value.ToString() }
|
||||
};
|
||||
|
||||
// Act
|
||||
var bytes = testProvider.Serialize(input);
|
||||
var values = testProvider.Deserialize(bytes);
|
||||
|
||||
// Assert
|
||||
var roundTripValue = Assert.IsType<string>(values[key]);
|
||||
Assert.Equal(value.ToString(), roundTripValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Infrastructure
|
||||
{
|
||||
public abstract class TempDataSerializerTestBase
|
||||
{
|
||||
[Fact]
|
||||
public void DeserializeTempData_ReturnsEmptyDictionary_DataIsEmpty()
|
||||
{
|
||||
// Arrange
|
||||
var serializer = GetTempDataSerializer();
|
||||
|
||||
// Act
|
||||
var tempDataDictionary = serializer.Deserialize(new byte[0]);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(tempDataDictionary);
|
||||
Assert.Empty(tempDataDictionary);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RoundTripTest_NullValue()
|
||||
{
|
||||
// Arrange
|
||||
var key = "NullKey";
|
||||
var testProvider = GetTempDataSerializer();
|
||||
var input = new Dictionary<string, object>
|
||||
{
|
||||
{ key, null }
|
||||
};
|
||||
|
||||
// Act
|
||||
var bytes = testProvider.Serialize(input);
|
||||
var values = testProvider.Deserialize(bytes);
|
||||
|
||||
// Assert
|
||||
Assert.True(values.ContainsKey(key));
|
||||
Assert.Null(values[key]);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(-10)]
|
||||
[InlineData(3340)]
|
||||
[InlineData(int.MaxValue)]
|
||||
[InlineData(int.MinValue)]
|
||||
public void RoundTripTest_IntValue(int value)
|
||||
{
|
||||
// Arrange
|
||||
var key = "test-key";
|
||||
var testProvider = GetTempDataSerializer();
|
||||
var input = new Dictionary<string, object>
|
||||
{
|
||||
{ key, value },
|
||||
};
|
||||
|
||||
// Act
|
||||
var bytes = testProvider.Serialize(input);
|
||||
var values = testProvider.Deserialize(bytes);
|
||||
|
||||
// Assert
|
||||
var roundTripValue = Assert.IsType<int>(values[key]);
|
||||
Assert.Equal(value, roundTripValue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null)]
|
||||
[InlineData(10)]
|
||||
public void RoundTripTest_NullableInt(int? value)
|
||||
{
|
||||
// Arrange
|
||||
var key = "test-key";
|
||||
var testProvider = GetTempDataSerializer();
|
||||
var input = new Dictionary<string, object>
|
||||
{
|
||||
{ key, value },
|
||||
};
|
||||
|
||||
// Act
|
||||
var bytes = testProvider.Serialize(input);
|
||||
var values = testProvider.Deserialize(bytes);
|
||||
|
||||
// Assert
|
||||
var roundTripValue = (int?)values[key];
|
||||
Assert.Equal(value, roundTripValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RoundTripTest_StringValue()
|
||||
{
|
||||
// Arrange
|
||||
var key = "test-key";
|
||||
var value = "test-value";
|
||||
var testProvider = GetTempDataSerializer();
|
||||
var input = new Dictionary<string, object>
|
||||
{
|
||||
{ key, value },
|
||||
};
|
||||
|
||||
// Act
|
||||
var bytes = testProvider.Serialize(input);
|
||||
var values = testProvider.Deserialize(bytes);
|
||||
|
||||
// Assert
|
||||
var roundTripValue = Assert.IsType<string>(values[key]);
|
||||
Assert.Equal(value, roundTripValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RoundTripTest_Enum()
|
||||
{
|
||||
// Arrange
|
||||
var key = "test-key";
|
||||
var value = DayOfWeek.Friday;
|
||||
var testProvider = GetTempDataSerializer();
|
||||
var input = new Dictionary<string, object>
|
||||
{
|
||||
{ key, value },
|
||||
};
|
||||
|
||||
// Act
|
||||
var bytes = testProvider.Serialize(input);
|
||||
var values = testProvider.Deserialize(bytes);
|
||||
|
||||
// Assert
|
||||
var roundTripValue = (DayOfWeek)values[key];
|
||||
Assert.Equal(value, roundTripValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RoundTripTest_DateTimeValue()
|
||||
{
|
||||
// Arrange
|
||||
var key = "test-key";
|
||||
var value = new DateTime(2009, 1, 1, 12, 37, 43);
|
||||
var testProvider = GetTempDataSerializer();
|
||||
var input = new Dictionary<string, object>
|
||||
{
|
||||
{ key, value },
|
||||
};
|
||||
|
||||
// Act
|
||||
var bytes = testProvider.Serialize(input);
|
||||
var values = testProvider.Deserialize(bytes);
|
||||
|
||||
// Assert
|
||||
var roundTripValue = Assert.IsType<DateTime>(values[key]);
|
||||
Assert.Equal(value, roundTripValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RoundTripTest_GuidValue()
|
||||
{
|
||||
// Arrange
|
||||
var key = "test-key";
|
||||
var testProvider = GetTempDataSerializer();
|
||||
var value = Guid.NewGuid();
|
||||
var input = new Dictionary<string, object>
|
||||
{
|
||||
{ key, value }
|
||||
};
|
||||
|
||||
// Act
|
||||
var bytes = testProvider.Serialize(input);
|
||||
var values = testProvider.Deserialize(bytes);
|
||||
|
||||
// Assert
|
||||
var roundTripValue = Assert.IsType<Guid>(values[key]);
|
||||
Assert.Equal(value, roundTripValue);
|
||||
}
|
||||
|
||||
protected abstract TempDataSerializer GetTempDataSerializer();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -507,7 +507,7 @@ Products: Book1, Book2 (1)";
|
|||
|
||||
// Act - 3
|
||||
// Trigger an expiration of the nested content.
|
||||
var content = @"[{ productName: ""Music Systems"" },{ productName: ""Televisions"" }]";
|
||||
var content = @"[{ ""ProductName"": ""Music Systems"" },{ ""ProductName"": ""Televisions"" }]";
|
||||
var requestMessage = new HttpRequestMessage(HttpMethod.Post, "/categories/Electronics");
|
||||
requestMessage.Content = new StringContent(content, Encoding.UTF8, "application/json");
|
||||
(await Client.SendAsync(requestMessage)).EnsureSuccessStatusCode();
|
||||
|
|
|
|||
|
|
@ -784,7 +784,7 @@ Hello from /Pages/WithViewStart/Index.cshtml!";
|
|||
Assert.Equal(expected, content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Fact(Skip = "https://github.com/dotnet/corefx/issues/36024")]
|
||||
public async Task PolymorphicPropertiesOnPageModelsAreValidated()
|
||||
{
|
||||
// Arrange
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
|
|
@ -8,7 +8,6 @@
|
|||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Mvc" />
|
||||
<Reference Include="Microsoft.AspNetCore.Mvc.Formatters.Xml" />
|
||||
<Reference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" />
|
||||
|
||||
<Reference Include="Microsoft.AspNetCore.Cors" />
|
||||
<Reference Include="Microsoft.AspNetCore.Server.IISIntegration" />
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ namespace CorsWebSite
|
|||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddControllers(ConfigureMvcOptions)
|
||||
.AddNewtonsoftJson()
|
||||
.SetCompatibilityVersion(CompatibilityVersion.Latest);
|
||||
services.Configure<CorsOptions>(options =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Mvc" />
|
||||
<Reference Include="Microsoft.AspNetCore.Mvc.Formatters.Xml" />
|
||||
<Reference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" />
|
||||
|
||||
<Reference Include="Microsoft.AspNetCore.Localization.Routing" />
|
||||
<Reference Include="Microsoft.AspNetCore.Server.IISIntegration" />
|
||||
|
|
|
|||
|
|
@ -1,11 +1,8 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
|
|
@ -24,9 +21,7 @@ namespace GenericHostWebSite
|
|||
// Remove when all URL generation tests are passing - https://github.com/aspnet/Routing/issues/590
|
||||
options.EnableEndpointRouting = false;
|
||||
})
|
||||
.SetCompatibilityVersion(CompatibilityVersion.Latest)
|
||||
.AddNewtonsoftJson()
|
||||
.AddXmlDataContractSerializerFormatters();
|
||||
.SetCompatibilityVersion(CompatibilityVersion.Latest);
|
||||
|
||||
services.AddLogging();
|
||||
services.AddHttpContextAccessor();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Mvc" />
|
||||
<Reference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" />
|
||||
<Reference Include="Microsoft.AspNetCore.Server.IISIntegration" />
|
||||
<Reference Include="Microsoft.AspNetCore.Server.Kestrel" />
|
||||
<Reference Include="Microsoft.AspNetCore.StaticFiles" />
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ namespace HtmlGenerationWebSite
|
|||
// null which is interpreted as true unless element includes an action attribute.
|
||||
services.AddMvc(ConfigureMvcOptions)
|
||||
.InitializeTagHelper<FormTagHelper>((helper, _) => helper.Antiforgery = false)
|
||||
.AddNewtonsoftJson()
|
||||
.SetCompatibilityVersion(CompatibilityVersion.Latest);
|
||||
|
||||
services.AddSingleton(typeof(ISignalTokenProviderService<>), typeof(SignalTokenProviderService<>));
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ namespace RazorPagesWebSite
|
|||
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options => options.LoginPath = "/Login");
|
||||
services.AddMvc(options => options.EnableEndpointRouting = false)
|
||||
.AddMvcLocalization()
|
||||
.AddNewtonsoftJson()
|
||||
.AddRazorPagesOptions(options =>
|
||||
{
|
||||
options.Conventions.AuthorizePage("/HelloWorldWithAuth");
|
||||
|
|
|
|||
Loading…
Reference in New Issue