Merge branch 'master' into merge/release/3.0-preview6-to-master

This commit is contained in:
Doug Bunting 2019-06-04 20:44:48 -07:00 committed by GitHub
commit 379f28edc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 704 additions and 264 deletions

View File

@ -56,5 +56,10 @@ Later on, this will be checked using this condition:
Microsoft.AspNetCore.AzureAppServices.SiteExtension;
</PackagesInPatch>
</PropertyGroup>
<PropertyGroup Condition=" '$(VersionPrefix)' == '2.2.6' ">
<PackagesInPatch>
Microsoft.AspNetCore.Mvc.Api.Analyzers;
</PackagesInPatch>
</PropertyGroup>
</Project>

View File

@ -9,53 +9,53 @@
-->
<Dependencies>
<ProductDependencies>
<Dependency Name="Microsoft.AspNetCore.Blazor.Mono" Version="0.10.0-preview6.19303.4">
<Dependency Name="Microsoft.AspNetCore.Blazor.Mono" Version="0.10.0-preview7.19303.2">
<Uri>https://github.com/aspnet/Blazor</Uri>
<Sha>be5e4eea2dc7da9852a560703bce381295718905</Sha>
<Sha>9bc8036bf68fd159fffa56f93f8b2471bf96efd4</Sha>
</Dependency>
<Dependency Name="Microsoft.AspNetCore.Razor.Language" Version="3.0.0-preview6.19304.1">
<Dependency Name="Microsoft.AspNetCore.Razor.Language" Version="3.0.0-preview7.19303.10">
<Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
<Sha>16628fa0fbf8f9948840a549fec0b898cb469f4b</Sha>
<Sha>6fcd12e60b3d828988cabdebb55d30397c21d0db</Sha>
</Dependency>
<Dependency Name="Microsoft.AspNetCore.Mvc.Razor.Extensions" Version="3.0.0-preview6.19304.1">
<Dependency Name="Microsoft.AspNetCore.Mvc.Razor.Extensions" Version="3.0.0-preview7.19303.10">
<Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
<Sha>16628fa0fbf8f9948840a549fec0b898cb469f4b</Sha>
<Sha>6fcd12e60b3d828988cabdebb55d30397c21d0db</Sha>
</Dependency>
<Dependency Name="Microsoft.CodeAnalysis.Razor" Version="3.0.0-preview6.19304.1">
<Dependency Name="Microsoft.CodeAnalysis.Razor" Version="3.0.0-preview7.19303.10">
<Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
<Sha>16628fa0fbf8f9948840a549fec0b898cb469f4b</Sha>
<Sha>6fcd12e60b3d828988cabdebb55d30397c21d0db</Sha>
</Dependency>
<Dependency Name="Microsoft.NET.Sdk.Razor" Version="3.0.0-preview6.19304.1">
<Dependency Name="Microsoft.NET.Sdk.Razor" Version="3.0.0-preview7.19303.10">
<Uri>https://github.com/aspnet/AspNetCore-Tooling</Uri>
<Sha>16628fa0fbf8f9948840a549fec0b898cb469f4b</Sha>
<Sha>6fcd12e60b3d828988cabdebb55d30397c21d0db</Sha>
</Dependency>
<Dependency Name="dotnet-ef" Version="3.0.0-preview6.19304.2">
<Dependency Name="dotnet-ef" Version="3.0.0-preview7.19303.12">
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
<Sha>2a3b2d25434148421c39134f5e80c5427f20a5a5</Sha>
<Sha>b9c9b57de1ba41f75427db0a51b2e897d0354656</Sha>
</Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="3.0.0-preview6.19304.2">
<Dependency Name="Microsoft.EntityFrameworkCore.InMemory" Version="3.0.0-preview7.19303.12">
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
<Sha>2a3b2d25434148421c39134f5e80c5427f20a5a5</Sha>
<Sha>b9c9b57de1ba41f75427db0a51b2e897d0354656</Sha>
</Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="3.0.0-preview6.19304.2">
<Dependency Name="Microsoft.EntityFrameworkCore.Relational" Version="3.0.0-preview7.19303.12">
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
<Sha>2a3b2d25434148421c39134f5e80c5427f20a5a5</Sha>
<Sha>b9c9b57de1ba41f75427db0a51b2e897d0354656</Sha>
</Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="3.0.0-preview6.19304.2">
<Dependency Name="Microsoft.EntityFrameworkCore.Sqlite" Version="3.0.0-preview7.19303.12">
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
<Sha>2a3b2d25434148421c39134f5e80c5427f20a5a5</Sha>
<Sha>b9c9b57de1ba41f75427db0a51b2e897d0354656</Sha>
</Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0-preview6.19304.2">
<Dependency Name="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0-preview7.19303.12">
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
<Sha>2a3b2d25434148421c39134f5e80c5427f20a5a5</Sha>
<Sha>b9c9b57de1ba41f75427db0a51b2e897d0354656</Sha>
</Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0-preview6.19304.2">
<Dependency Name="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0-preview7.19303.12">
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
<Sha>2a3b2d25434148421c39134f5e80c5427f20a5a5</Sha>
<Sha>b9c9b57de1ba41f75427db0a51b2e897d0354656</Sha>
</Dependency>
<Dependency Name="Microsoft.EntityFrameworkCore" Version="3.0.0-preview6.19304.2">
<Dependency Name="Microsoft.EntityFrameworkCore" Version="3.0.0-preview7.19303.12">
<Uri>https://github.com/aspnet/EntityFrameworkCore</Uri>
<Sha>2a3b2d25434148421c39134f5e80c5427f20a5a5</Sha>
<Sha>b9c9b57de1ba41f75427db0a51b2e897d0354656</Sha>
</Dependency>
<Dependency Name="Microsoft.AspNetCore.Analyzer.Testing" Version="3.0.0-preview6.19304.2" CoherentParentDependency="Microsoft.EntityFrameworkCore">
<Uri>https://github.com/aspnet/Extensions</Uri>

View File

@ -49,7 +49,7 @@
<!-- Only listed explicitly to workaround https://github.com/dotnet/cli/issues/10528 -->
<MicrosoftNETCorePlatformsPackageVersion>3.0.0-preview6.19303.8</MicrosoftNETCorePlatformsPackageVersion>
<!-- Packages from aspnet/Blazor -->
<MicrosoftAspNetCoreBlazorMonoPackageVersion>0.10.0-preview6.19303.4</MicrosoftAspNetCoreBlazorMonoPackageVersion>
<MicrosoftAspNetCoreBlazorMonoPackageVersion>0.10.0-preview7.19303.2</MicrosoftAspNetCoreBlazorMonoPackageVersion>
<!-- Packages from aspnet/Extensions -->
<InternalAspNetCoreAnalyzersPackageVersion>3.0.0-preview6.19304.2</InternalAspNetCoreAnalyzersPackageVersion>
<MicrosoftAspNetCoreAnalyzerTestingPackageVersion>3.0.0-preview6.19304.2</MicrosoftAspNetCoreAnalyzerTestingPackageVersion>
@ -113,18 +113,18 @@
<MicrosoftJSInteropPackageVersion>3.0.0-preview6.19304.2</MicrosoftJSInteropPackageVersion>
<MonoWebAssemblyInteropPackageVersion>3.0.0-preview6.19304.2</MonoWebAssemblyInteropPackageVersion>
<!-- Packages from aspnet/EntityFrameworkCore -->
<dotnetefPackageVersion>3.0.0-preview6.19304.2</dotnetefPackageVersion>
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>3.0.0-preview6.19304.2</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>3.0.0-preview6.19304.2</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
<MicrosoftEntityFrameworkCoreSqlitePackageVersion>3.0.0-preview6.19304.2</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>3.0.0-preview6.19304.2</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
<MicrosoftEntityFrameworkCoreToolsPackageVersion>3.0.0-preview6.19304.2</MicrosoftEntityFrameworkCoreToolsPackageVersion>
<MicrosoftEntityFrameworkCorePackageVersion>3.0.0-preview6.19304.2</MicrosoftEntityFrameworkCorePackageVersion>
<dotnetefPackageVersion>3.0.0-preview7.19303.12</dotnetefPackageVersion>
<MicrosoftEntityFrameworkCoreInMemoryPackageVersion>3.0.0-preview7.19303.12</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>
<MicrosoftEntityFrameworkCoreRelationalPackageVersion>3.0.0-preview7.19303.12</MicrosoftEntityFrameworkCoreRelationalPackageVersion>
<MicrosoftEntityFrameworkCoreSqlitePackageVersion>3.0.0-preview7.19303.12</MicrosoftEntityFrameworkCoreSqlitePackageVersion>
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>3.0.0-preview7.19303.12</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
<MicrosoftEntityFrameworkCoreToolsPackageVersion>3.0.0-preview7.19303.12</MicrosoftEntityFrameworkCoreToolsPackageVersion>
<MicrosoftEntityFrameworkCorePackageVersion>3.0.0-preview7.19303.12</MicrosoftEntityFrameworkCorePackageVersion>
<!-- Packages from aspnet/AspNetCore-Tooling -->
<MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>3.0.0-preview6.19304.1</MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>
<MicrosoftAspNetCoreRazorLanguagePackageVersion>3.0.0-preview6.19304.1</MicrosoftAspNetCoreRazorLanguagePackageVersion>
<MicrosoftCodeAnalysisRazorPackageVersion>3.0.0-preview6.19304.1</MicrosoftCodeAnalysisRazorPackageVersion>
<MicrosoftNETSdkRazorPackageVersion>3.0.0-preview6.19304.1</MicrosoftNETSdkRazorPackageVersion>
<MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>3.0.0-preview7.19303.10</MicrosoftAspNetCoreMvcRazorExtensionsPackageVersion>
<MicrosoftAspNetCoreRazorLanguagePackageVersion>3.0.0-preview7.19303.10</MicrosoftAspNetCoreRazorLanguagePackageVersion>
<MicrosoftCodeAnalysisRazorPackageVersion>3.0.0-preview7.19303.10</MicrosoftCodeAnalysisRazorPackageVersion>
<MicrosoftNETSdkRazorPackageVersion>3.0.0-preview7.19303.10</MicrosoftNETSdkRazorPackageVersion>
</PropertyGroup>
<!--

View File

@ -13,5 +13,9 @@
<assembly fullname="System">
<!-- Without this, [Required(typeof(bool), "true", "true", ErrorMessage = "...")] fails -->
<type fullname="System.ComponentModel.BooleanConverter" />
<!-- TypeConverters are only used through reflection. These are two built-in TypeConverters that are useful. -->
<type fullname="System.ComponentModel.GuidConverter" />
<type fullname="System.ComponentModel.TimeSpanConverter" />
</assembly>
</linker>

View File

@ -155,6 +155,7 @@ namespace Microsoft.AspNetCore.Components
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<int> setter, int existingValue) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<long> setter, long existingValue) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<bool?> setter, bool? existingValue) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<System.DateTime?> setter, System.DateTime? existingValue) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<decimal?> setter, decimal? existingValue) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<double?> setter, double? existingValue) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<int?> setter, int? existingValue) { throw null; }
@ -162,7 +163,7 @@ namespace Microsoft.AspNetCore.Components
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<float?> setter, float? existingValue) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<float> setter, float existingValue) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<string> setter, string existingValue) { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder<T>(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<T> setter, T existingValue) where T : struct, System.Enum { throw null; }
public static Microsoft.AspNetCore.Components.EventCallback<Microsoft.AspNetCore.Components.UIChangeEventArgs> CreateBinder<T>(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action<T> setter, T existingValue) { throw null; }
}
public static partial class EventCallbackFactoryUIEventArgsExtensions
{

View File

@ -2,13 +2,27 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Concurrent;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
namespace Microsoft.AspNetCore.Components
{
/// <summary>
/// Contains extension methods for two-way binding using <see cref="EventCallback"/>. For internal use only.
/// </summary>
//
// NOTE: for number parsing, the HTML5 spec dictates that <input type="number"> the DOM will represent
// number values as floating point numbers using `.` as the period separator. This is NOT culture senstive.
// Put another way, the user might see `,` as their decimal separator, but the value available in events
// to JS code is always simpilar to what .NET parses with InvariantCulture.
//
// See: https://www.w3.org/TR/html5/sec-forms.html#number-state-typenumber
// See: https://www.w3.org/TR/html5/infrastructure.html#valid-floating-point-number
//
// For now we're not necessarily handling this correctly since we parse the same way for number and text.
public static class EventCallbackFactoryBinderExtensions
{
private delegate bool BindConverter<T>(object obj, out T value);
@ -53,7 +67,7 @@ namespace Microsoft.AspNetCore.Components
return false;
}
if (!int.TryParse(text, out var converted))
if (!int.TryParse(text, NumberStyles.Integer, CultureInfo.CurrentCulture, out var converted))
{
value = default;
return false;
@ -72,7 +86,7 @@ namespace Microsoft.AspNetCore.Components
return true;
}
if (!int.TryParse(text, out var converted))
if (!int.TryParse(text, NumberStyles.Integer, CultureInfo.CurrentCulture, out var converted))
{
value = default;
return false;
@ -94,7 +108,7 @@ namespace Microsoft.AspNetCore.Components
return false;
}
if (!long.TryParse(text, out var converted))
if (!long.TryParse(text, NumberStyles.Integer, CultureInfo.CurrentCulture, out var converted))
{
value = default;
return false;
@ -113,7 +127,7 @@ namespace Microsoft.AspNetCore.Components
return true;
}
if (!long.TryParse(text, out var converted))
if (!long.TryParse(text, NumberStyles.Integer, CultureInfo.CurrentCulture, out var converted))
{
value = default;
return false;
@ -135,7 +149,7 @@ namespace Microsoft.AspNetCore.Components
return false;
}
if (!float.TryParse(text, out var converted))
if (!float.TryParse(text, NumberStyles.Number, CultureInfo.CurrentCulture, out var converted))
{
value = default;
return false;
@ -154,7 +168,7 @@ namespace Microsoft.AspNetCore.Components
return true;
}
if (!float.TryParse(text, out var converted))
if (!float.TryParse(text, NumberStyles.Number, CultureInfo.CurrentCulture, out var converted))
{
value = default;
return false;
@ -176,7 +190,7 @@ namespace Microsoft.AspNetCore.Components
return false;
}
if (!double.TryParse(text, out var converted))
if (!double.TryParse(text, NumberStyles.Number, CultureInfo.CurrentCulture, out var converted))
{
value = default;
return false;
@ -195,7 +209,7 @@ namespace Microsoft.AspNetCore.Components
return true;
}
if (!double.TryParse(text, out var converted))
if (!double.TryParse(text, NumberStyles.Number, CultureInfo.CurrentCulture, out var converted))
{
value = default;
return false;
@ -217,7 +231,7 @@ namespace Microsoft.AspNetCore.Components
return false;
}
if (!decimal.TryParse(text, out var converted))
if (!decimal.TryParse(text, NumberStyles.Number, CultureInfo.CurrentCulture, out var converted))
{
value = default;
return false;
@ -236,7 +250,7 @@ namespace Microsoft.AspNetCore.Components
return true;
}
if (!decimal.TryParse(text, out var converted))
if (!decimal.TryParse(text, NumberStyles.Number, CultureInfo.CurrentCulture, out var converted))
{
value = default;
return false;
@ -246,28 +260,83 @@ namespace Microsoft.AspNetCore.Components
return true;
}
private static class EnumConverter<T> where T : struct, Enum
private static BindConverter<DateTime> ConvertToDateTime = ConvertToDateTimeCore;
private static BindConverter<DateTime?> ConvertToNullableDateTime = ConvertToNullableDateTimeCore;
private static bool ConvertToDateTimeCore(object obj, out DateTime value)
{
public static readonly BindConverter<T> Convert = ConvertCore;
public static bool ConvertCore(object obj, out T value)
var text = (string)obj;
if (string.IsNullOrEmpty(text))
{
var text = (string)obj;
if (string.IsNullOrEmpty(text))
{
value = default;
return true;
}
value = default;
return false;
}
if (!Enum.TryParse<T>(text, out var converted))
{
value = default;
return false;
}
if (!DateTime.TryParse(text, CultureInfo.CurrentCulture, DateTimeStyles.None, out var converted))
{
value = default;
return false;
}
value = converted;
value = converted;
return true;
}
private static bool ConvertToNullableDateTimeCore(object obj, out DateTime? value)
{
var text = (string)obj;
if (string.IsNullOrEmpty(text))
{
value = default;
return true;
}
if (!DateTime.TryParse(text, CultureInfo.CurrentCulture, DateTimeStyles.None, out var converted))
{
value = default;
return false;
}
value = converted;
return true;
}
private static bool ConvertToEnum<T>(object obj, out T value) where T : struct, Enum
{
var text = (string)obj;
if (string.IsNullOrEmpty(text))
{
value = default;
return true;
}
if (!Enum.TryParse<T>(text, out var converted))
{
value = default;
return false;
}
value = converted;
return true;
}
private static bool ConvertToNullableEnum<T>(object obj, out Nullable<T> value) where T : struct, Enum
{
var text = (string)obj;
if (string.IsNullOrEmpty(text))
{
value = default;
return true;
}
if (!Enum.TryParse<T>(text, out var converted))
{
value = default;
return false;
}
value = converted;
return true;
}
/// <summary>
@ -284,7 +353,6 @@ namespace Microsoft.AspNetCore.Components
Action<string> setter,
string existingValue)
{
;
return CreateBinderCore<string>(factory, receiver, setter, ConvertToString);
}
@ -489,15 +557,6 @@ namespace Microsoft.AspNetCore.Components
Action<decimal?> setter,
decimal? existingValue)
{
Func<object, decimal?> converter = (obj) =>
{
if (decimal.TryParse((string)obj, out var value))
{
return value;
}
return null;
};
return CreateBinderCore<decimal?>(factory, receiver, setter, ConvertToNullableDecimal);
}
@ -515,28 +574,24 @@ namespace Microsoft.AspNetCore.Components
Action<DateTime> setter,
DateTime existingValue)
{
// Avoiding CreateBinderCore so we can avoid an extra allocating lambda
// when a format is used.
Action<UIChangeEventArgs> callback = (e) =>
{
DateTime value = default;
var converted = false;
try
{
value = ConvertDateTime(e.Value, format: null);
converted = true;
}
catch
{
}
return CreateBinderCore<DateTime>(factory, receiver, setter, ConvertToDateTime);
}
// See comments in CreateBinderCore
if (converted)
{
setter(value);
}
};
return factory.Create<UIChangeEventArgs>(receiver, callback);
/// <summary>
/// For internal use only.
/// </summary>
/// <param name="factory"></param>
/// <param name="receiver"></param>
/// <param name="setter"></param>
/// <param name="existingValue"></param>
/// <returns></returns>
public static EventCallback<UIChangeEventArgs> CreateBinder(
this EventCallbackFactory factory,
object receiver,
Action<DateTime?> setter,
DateTime? existingValue)
{
return CreateBinderCore<DateTime?>(factory, receiver, setter, ConvertToNullableDateTime);
}
/// <summary>
@ -577,6 +632,23 @@ namespace Microsoft.AspNetCore.Components
}
};
return factory.Create<UIChangeEventArgs>(receiver, callback);
static DateTime ConvertDateTime(object obj, string format)
{
var text = (string)obj;
if (string.IsNullOrEmpty(text))
{
return default;
}
else if (format != null && DateTime.TryParseExact(text, format, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var value))
{
return value;
}
else
{
return DateTime.Parse(text);
}
}
}
/// <summary>
@ -592,26 +664,9 @@ namespace Microsoft.AspNetCore.Components
this EventCallbackFactory factory,
object receiver,
Action<T> setter,
T existingValue) where T : struct, Enum
T existingValue)
{
return CreateBinderCore<T>(factory, receiver, setter, EnumConverter<T>.Convert);
}
private static DateTime ConvertDateTime(object obj, string format)
{
var text = (string)obj;
if (string.IsNullOrEmpty(text))
{
return default;
}
else if (format != null && DateTime.TryParseExact(text, format, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var value))
{
return value;
}
else
{
return DateTime.Parse(text);
}
return CreateBinderCore<T>(factory, receiver, setter, BinderConverterCache.Get<T>());
}
private static EventCallback<UIChangeEventArgs> CreateBinderCore<T>(
@ -642,5 +697,139 @@ namespace Microsoft.AspNetCore.Components
};
return factory.Create<UIChangeEventArgs>(receiver, callback);
}
// We can't rely on generics + static to cache here unfortunately. That would require us to overload
// CreateBinder on T : struct AND T : class, which is not allowed.
private static class BinderConverterCache
{
private readonly static ConcurrentDictionary<Type, Delegate> _cache = new ConcurrentDictionary<Type, Delegate>();
private static MethodInfo _convertToEnum;
private static MethodInfo _convertToNullableEnum;
public static BindConverter<T> Get<T>()
{
if (!_cache.TryGetValue(typeof(T), out var converter))
{
// We need to replicate all of the primitive cases that we handle here so that they will behave the same way.
// The result will be cached.
if (typeof(T) == typeof(string))
{
converter = ConvertToString;
}
else if (typeof(T) == typeof(bool))
{
converter = ConvertToBool;
}
else if (typeof(T) == typeof(bool?))
{
converter = ConvertToNullableBool;
}
else if (typeof(T) == typeof(int))
{
converter = ConvertToInt;
}
else if (typeof(T) == typeof(int?))
{
converter = ConvertToNullableInt;
}
else if (typeof(T) == typeof(long))
{
converter = ConvertToLong;
}
else if (typeof(T) == typeof(long?))
{
converter = ConvertToNullableLong;
}
else if (typeof(T) == typeof(float))
{
converter = ConvertToFloat;
}
else if (typeof(T) == typeof(float?))
{
converter = ConvertToNullableFloat;
}
else if (typeof(T) == typeof(double))
{
converter = ConvertToDouble;
}
else if (typeof(T) == typeof(double?))
{
converter = ConvertToNullableDouble;
}
else if (typeof(T) == typeof(decimal))
{
converter = ConvertToDecimal;
}
else if (typeof(T) == typeof(decimal?))
{
converter = ConvertToNullableDecimal;
}
else if (typeof(T) == typeof(DateTime))
{
converter = ConvertToDateTime;
}
else if (typeof(T) == typeof(DateTime?))
{
converter = ConvertToNullableDateTime;
}
else if (typeof(T).IsEnum)
{
// We have to deal invoke this dynamically to work around the type constraint on Enum.TryParse.
var method = _convertToEnum ??= typeof(EventCallbackFactoryBinderExtensions).GetMethod(nameof(ConvertToEnum), BindingFlags.NonPublic | BindingFlags.Static);
converter = method.MakeGenericMethod(typeof(T)).CreateDelegate(typeof(BindConverter<T>), target: null);
}
else if (Nullable.GetUnderlyingType(typeof(T)) is Type innerType && innerType.IsEnum)
{
// We have to deal invoke this dynamically to work around the type constraint on Enum.TryParse.
var method = _convertToNullableEnum ??= typeof(EventCallbackFactoryBinderExtensions).GetMethod(nameof(ConvertToNullableEnum), BindingFlags.NonPublic | BindingFlags.Static);
converter = method.MakeGenericMethod(innerType).CreateDelegate(typeof(BindConverter<T>), target: null);
}
else
{
converter = MakeTypeConverterConverter<T>();
}
_cache.TryAdd(typeof(T), converter);
}
return (BindConverter<T>)converter;
}
private static BindConverter<T> MakeTypeConverterConverter<T>()
{
var typeConverter = TypeDescriptor.GetConverter(typeof(T));
if (typeConverter == null || !typeConverter.CanConvertFrom(typeof(string)))
{
throw new InvalidOperationException(
$"The type '{typeof(T).FullName}' does not have an associated {typeof(TypeConverter).Name} that supports " +
$"conversion from a string. " +
$"Apply '{typeof(TypeConverterAttribute).Name}' to the type to register a converter.");
}
return ConvertWithTypeConverter;
bool ConvertWithTypeConverter(object obj, out T value)
{
var text = (string)obj;
if (string.IsNullOrEmpty(text))
{
value = default;
return true;
}
// We intentionally close-over the TypeConverter to cache it. The TypeDescriptor infrastructure is slow.
var converted = typeConverter.ConvertFromString(context: null, CultureInfo.CurrentCulture, text);
if (converted == null)
{
value = default;
return false;
}
value = (T)converted;
return true;
}
}
}
}
}

View File

@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.ComponentModel;
using System.Globalization;
using System.Threading.Tasks;
using Xunit;
@ -344,6 +346,25 @@ namespace Microsoft.AspNetCore.Components
Assert.Equal(1, component.Count);
}
[Fact]
public async Task CreateBinder_NullableEnum()
{
// Arrange
var value = (AttributeTargets?)AttributeTargets.All;
var component = new EventCountingComponent();
Action<AttributeTargets?> setter = (_) => value = _;
var binder = EventCallback.Factory.CreateBinder(component, setter, value);
var expectedValue = AttributeTargets.Class;
// Act
await binder.InvokeAsync(new UIChangeEventArgs() { Value = expectedValue.ToString(), });
Assert.Equal(expectedValue, value);
Assert.Equal(1, component.Count);
}
[Fact]
public async Task CreateBinder_DateTime()
{
@ -363,6 +384,26 @@ namespace Microsoft.AspNetCore.Components
Assert.Equal(1, component.Count);
}
[Fact]
public async Task CreateBinder_NullableDateTime()
{
// Arrange
var value = (DateTime?)DateTime.Now;
var component = new EventCountingComponent();
Action<DateTime?> setter = (_) => value = _;
var binder = EventCallback.Factory.CreateBinder(component, setter, value);
var expectedValue = new DateTime(2018, 3, 4, 1, 2, 3);
// Act
await binder.InvokeAsync(new UIChangeEventArgs() { Value = expectedValue.ToString(), });
Assert.Equal(expectedValue, value);
Assert.Equal(1, component.Count);
}
// For now format is only supported by this specific method.
[Fact]
public async Task CreateBinder_DateTime_Format()
{
@ -383,6 +424,80 @@ namespace Microsoft.AspNetCore.Components
Assert.Equal(1, component.Count);
}
// This uses a type converter
[Fact]
public async Task CreateBinder_Guid()
{
// Arrange
var value = Guid.NewGuid();
var component = new EventCountingComponent();
Action<Guid> setter = (_) => value = _;
var binder = EventCallback.Factory.CreateBinder(component, setter, value);
var expectedValue = Guid.NewGuid();
// Act
await binder.InvokeAsync(new UIChangeEventArgs() { Value = expectedValue.ToString(), });
Assert.Equal(expectedValue, value);
Assert.Equal(1, component.Count);
}
// This uses a type converter
[Fact]
public async Task CreateBinder_NullableGuid()
{
// Arrange
var value = (Guid?)Guid.NewGuid();
var component = new EventCountingComponent();
Action<Guid?> setter = (_) => value = _;
var binder = EventCallback.Factory.CreateBinder(component, setter, value);
var expectedValue = Guid.NewGuid();
// Act
await binder.InvokeAsync(new UIChangeEventArgs() { Value = expectedValue.ToString(), });
Assert.Equal(expectedValue, value);
Assert.Equal(1, component.Count);
}
[Fact]
public async Task CreateBinder_CustomTypeConverter()
{
// Arrange
var value = new SecretMessage() { Message = "A message", };
var component = new EventCountingComponent();
Action<SecretMessage> setter = (_) => value = _;
var binder = EventCallback.Factory.CreateBinder(component, setter, value);
var expectedValue = new SecretMessage() { Message = "TypeConverter may be old, but it still works!", };
// Act
await binder.InvokeAsync(new UIChangeEventArgs() { Value = expectedValue.ToString(), });
Assert.Equal(expectedValue.Message, value.Message);
Assert.Equal(1, component.Count);
}
[Fact]
public void CreateBinder_GenericWithoutTypeConverter_Throws()
{
var value = new ClassWithoutTypeConverter();
var component = new EventCountingComponent();
Action<ClassWithoutTypeConverter> setter = (_) => value = _;
var ex = Assert.Throws<InvalidOperationException>(() => EventCallback.Factory.CreateBinder(component, setter, value));
Assert.Equal(
$"The type '{typeof(ClassWithoutTypeConverter).FullName}' does not have an associated TypeConverter that supports conversion from a string. " +
$"Apply 'TypeConverterAttribute' to the type to register a converter.",
ex.Message);
}
private class EventCountingComponent : IComponent, IHandleEvent
{
public int Count;
@ -403,5 +518,42 @@ namespace Microsoft.AspNetCore.Components
throw new System.NotImplementedException();
}
}
private class ClassWithoutTypeConverter
{
}
[TypeConverter(typeof(SecretMessageTypeConverter))]
private class SecretMessage
{
public string Message { get; set; }
public override string ToString()
{
return Message;
}
}
private class SecretMessageTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
{
return true;
}
return false;
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is string message)
{
return new SecretMessage() { Message = message, };
}
return null;
}
}
}
}

View File

@ -1,6 +1,7 @@
// 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 BasicTestApp;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure;
using Microsoft.AspNetCore.Components.E2ETest.Infrastructure.ServerFixtures;
@ -538,5 +539,48 @@ namespace Microsoft.AspNetCore.Components.E2ETest.Tests
Browser.Equal("0.011", () => boundValue.Text);
Assert.Equal("0.011", mirrorValue.GetAttribute("value"));
}
[Fact]
public void CanBindTextboxGenericInt()
{
var target = Browser.FindElement(By.Id("textbox-generic-int"));
var boundValue = Browser.FindElement(By.Id("textbox-generic-int-value"));
var mirrorValue = Browser.FindElement(By.Id("textbox-generic-int-mirror"));
Assert.Equal("-42", target.GetAttribute("value"));
Assert.Equal("-42", boundValue.Text);
Assert.Equal("-42", mirrorValue.GetAttribute("value"));
// Modify target; value is not updated because it's not convertable.
target.Clear();
Browser.Equal("-42", () => boundValue.Text);
Assert.Equal("-42", mirrorValue.GetAttribute("value"));
// Modify target; verify value is updated and that textboxes linked to the same data are updated
target.SendKeys("42\t");
Browser.Equal("42", () => boundValue.Text);
Assert.Equal("42", mirrorValue.GetAttribute("value"));
}
[Fact]
public void CanBindTextboxGenericGuid()
{
var target = Browser.FindElement(By.Id("textbox-generic-guid"));
var boundValue = Browser.FindElement(By.Id("textbox-generic-guid-value"));
var mirrorValue = Browser.FindElement(By.Id("textbox-generic-guid-mirror"));
Assert.Equal("00000000-0000-0000-0000-000000000000", target.GetAttribute("value"));
Assert.Equal("00000000-0000-0000-0000-000000000000", boundValue.Text);
Assert.Equal("00000000-0000-0000-0000-000000000000", mirrorValue.GetAttribute("value"));
// Modify target; value is not updated because it's not convertable.
target.Clear();
Browser.Equal("00000000-0000-0000-0000-000000000000", () => boundValue.Text);
Assert.Equal("00000000-0000-0000-0000-000000000000", mirrorValue.GetAttribute("value"));
// Modify target; verify value is updated and that textboxes linked to the same data are updated
var newValue = Guid.NewGuid().ToString();
target.SendKeys(newValue + "\t");
Browser.Equal(newValue, () => boundValue.Text);
Assert.Equal(newValue, mirrorValue.GetAttribute("value"));
}
}
}

View File

@ -90,6 +90,19 @@
<input id="textbox-nullable-decimal-invalid-mirror" @bind="textboxNullableDecimalInvalidValue" readonly />
</p>
<p>
Generic bind (int):
<BindGenericComponent Id="textbox-generic-int" @bind-Value="textboxGenericIntValue" />
<span id="textbox-generic-int-value">@textboxGenericIntValue</span>
<input id="textbox-generic-int-mirror" @bind="textboxGenericIntValue" readonly />
</p>
<p>
Generic bind (guid):
<BindGenericComponent Id="textbox-generic-guid" @bind-Value="textboxGenericGuidValue" />
<span id="textbox-generic-guid-value">@textboxGenericGuidValue</span>
<input id="textbox-generic-guid-mirror" @bind="textboxGenericGuidValue" readonly />
</p>
<h2>Text Area</h2>
<p>
Initially blank:
@ -138,36 +151,39 @@
</p>
@code {
string textboxInitiallyBlankValue = null;
string textboxInitiallyPopulatedValue = "Hello";
string textboxInitiallyBlankValue = null;
string textboxInitiallyPopulatedValue = "Hello";
string textAreaInitiallyBlankValue = null;
string textAreaInitiallyPopulatedValue = "Hello";
string textAreaInitiallyBlankValue = null;
string textAreaInitiallyPopulatedValue = "Hello";
bool? checkboxInitiallyNullValue = null;
bool checkboxInitiallyUncheckedValue = false;
bool checkboxInitiallyCheckedValue = true;
bool? checkboxInitiallyNullValue = null;
bool checkboxInitiallyUncheckedValue = false;
bool checkboxInitiallyCheckedValue = true;
int textboxIntValue = -42;
int? textboxNullableIntValue = null;
long textboxLongValue = 3_000_000_000;
long? textboxNullableLongValue = null;
float textboxFloatValue = 3.141f;
float? textboxNullableFloatValue = null;
double textboxDoubleValue = 3.14159265359d;
double? textboxNullableDoubleValue = null;
decimal textboxDecimalValue = 0.0000000000000000000000000001M;
decimal? textboxNullableDecimalValue = null;
decimal textboxDecimalInvalidValue = 0.0000000000000000000000000001M;
decimal? textboxNullableDecimalInvalidValue = null;
int textboxIntValue = -42;
int? textboxNullableIntValue = null;
long textboxLongValue = 3_000_000_000;
long? textboxNullableLongValue = null;
float textboxFloatValue = 3.141f;
float? textboxNullableFloatValue = null;
double textboxDoubleValue = 3.14159265359d;
double? textboxNullableDoubleValue = null;
decimal textboxDecimalValue = 0.0000000000000000000000000001M;
decimal? textboxNullableDecimalValue = null;
decimal textboxDecimalInvalidValue = 0.0000000000000000000000000001M;
decimal? textboxNullableDecimalInvalidValue = null;
bool includeFourthOption = false;
enum SelectableValue { First, Second, Third, Fourth }
SelectableValue selectValue = SelectableValue.Second;
int textboxGenericIntValue = -42;
Guid textboxGenericGuidValue = Guid.Empty;
void AddAndSelectNewSelectOption()
{
includeFourthOption = true;
selectValue = SelectableValue.Fourth;
}
bool includeFourthOption = false;
enum SelectableValue { First, Second, Third, Fourth }
SelectableValue selectValue = SelectableValue.Second;
void AddAndSelectNewSelectOption()
{
includeFourthOption = true;
selectValue = SelectableValue.Fourth;
}
}

View File

@ -0,0 +1,9 @@
@typeparam TValue
<input id="@Id" type="text" value="@Value" @onchange="@(EventCallback.Factory.CreateBinder<TValue>(this, _ => ValueChanged.InvokeAsync(_), Value))" />
@code {
[Parameter] string Id { get; set; }
[Parameter] TValue Value { get; set; }
[Parameter] EventCallback<TValue> ValueChanged { get; set; }
}

View File

@ -28,6 +28,7 @@ namespace Microsoft.AspNetCore.Hosting.FunctionalTests
[ConditionalFact]
[OSSkipCondition(OperatingSystems.Windows)]
[OSSkipCondition(OperatingSystems.MacOSX)]
[Flaky("https://github.com/aspnet/AspNetCore-Internal/issues/2577", FlakyOn.All)]
public async Task ShutdownTestRun()
{
await ExecuteShutdownTest(nameof(ShutdownTestRun), "Run");

View File

@ -1,10 +1,10 @@
<!-- This file is automatically generated. -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<TargetFrameworks>netstandard2.1</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<Compile Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore.netstandard2.0.cs" />
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.1'">
<Compile Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore.netstandard2.1.cs" />
<Reference Include="Microsoft.EntityFrameworkCore.Relational" />
<Reference Include="Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions" />
<Reference Include="Microsoft.Extensions.Diagnostics.HealthChecks" />

View File

@ -1,10 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>
Components for performing health checks using EntityFrameworkCore.
</Description>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netstandard2.1</TargetFramework>
<NoWarn>$(NoWarn);CS1591</NoWarn>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>diagnostics;healthchecks;entityframeworkcore</PackageTags>

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp3.0;net461</TargetFrameworks>
<TargetFramework>netcoreapp3.0</TargetFramework>
<RootNamespace>Microsoft.AspNetCore.Diagnostics.HealthChecks</RootNamespace>
</PropertyGroup>

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// 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.Collections.Generic;
@ -39,6 +39,8 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite
context.Logger?.ModRewriteNotMatchedRule();
return;
}
condBackReferences = condResult.BackReferences;
}
// At this point, we know our rule passed, first apply pre conditions,
@ -51,4 +53,4 @@ namespace Microsoft.AspNetCore.Rewrite.Internal.ApacheModRewrite
}
}
}
}
}

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// 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;
@ -308,5 +308,25 @@ namespace Microsoft.AspNetCore.Rewrite.Tests.ModRewrite
Assert.Equal("/foo", response.Headers.Location.OriginalString);
}
[Fact]
public async Task CapturedVariablesInConditionsArePreservedToRewriteRule()
{
var options = new RewriteOptions().AddApacheModRewrite(new StringReader(@"RewriteCond %{REQUEST_URI} /home
RewriteCond %{QUERY_STRING} report_id=(.+)
RewriteRule (.*) http://localhost:80/home/report/%1 [R=301,L,QSD]"));
var builder = new WebHostBuilder().Configure(app =>
{
app.UseRewriter(options);
app.Run(context => context.Response.WriteAsync(
context.Request.Path +
context.Request.QueryString));
});
var server = new TestServer(builder) { BaseAddress = new Uri("http://localhost:5000/foo") };
var response = await server.CreateClient().GetAsync("/home?report_id=123");
Assert.Equal("http://localhost:80/home/report/123", response.Headers.Location.OriginalString);
}
}
}

View File

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="Controllers/ValuesController.fs" />
<Compile Include="Controllers/WeatherController.fs" />
<Compile Include="Startup.fs" />
<Compile Include="Program.fs" />
</ItemGroup>

View File

@ -1,60 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
#if (!NoAuth)
using Microsoft.AspNetCore.Authorization;
#endif
using Microsoft.AspNetCore.Mvc;
namespace Company.WebApplication1.Controllers
{
#if (!NoAuth)
[Authorize]
#endif
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return "value";
}
// POST api/values
[HttpPost]
public void Post([FromBody] string value)
{
#if (OrganizationalAuth || WindowsAuth)
// For more information on protecting this API from Cross Site Request Forgery (CSRF) attacks, see https://go.microsoft.com/fwlink/?LinkID=717803
#endif
}
// PUT api/values/5
[HttpPut("{id}")]
public void Put(int id, [FromBody] string value)
{
#if (OrganizationalAuth || WindowsAuth)
// For more information on protecting this API from Cross Site Request Forgery (CSRF) attacks, see https://go.microsoft.com/fwlink/?LinkID=717803
#endif
}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete(int id)
{
#if (OrganizationalAuth || WindowsAuth)
// For more information on protecting this API from Cross Site Request Forgery (CSRF) attacks, see https://go.microsoft.com/fwlink/?LinkID=717803
#endif
}
}
}

View File

@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
#if (!NoAuth)
using Microsoft.AspNetCore.Authorization;
#endif
using Microsoft.AspNetCore.Mvc;
namespace Company.WebApplication1.Controllers
{
#if (!NoAuth)
[Authorize]
#endif
[Route("api/SampleData/[controller]")]
[ApiController]
public class WeatherController : ControllerBase
{
[HttpGet]
public ActionResult<WeatherResult> GetWeatherForecasts(string location, TemperatureUnit unit)
{
var rng = new Random();
return new WeatherResult
{
Location = location,
Temperature = rng.Next(-20, 55),
TemperatureUnit = unit
};
}
}
public enum TemperatureUnit
{
Celsius,
Fahrenheit
}
public class WeatherResult
{
public int Temperature { get; set; }
public TemperatureUnit TemperatureUnit { get; set; }
public string Location { get; set; }
}
}

View File

@ -1,34 +0,0 @@
namespace Company.WebApplication1.Controllers
open System
open System.Collections.Generic
open System.Linq
open System.Threading.Tasks
open Microsoft.AspNetCore.Mvc
[<Route("api/[controller]")>]
[<ApiController>]
type ValuesController () =
inherit ControllerBase()
[<HttpGet>]
member this.Get() =
let values = [|"value1"; "value2"|]
ActionResult<string[]>(values)
[<HttpGet("{id}")>]
member this.Get(id:int) =
let value = "value"
ActionResult<string>(value)
[<HttpPost>]
member this.Post([<FromBody>] value:string) =
()
[<HttpPut("{id}")>]
member this.Put(id:int, [<FromBody>] value:string ) =
()
[<HttpDelete("{id}")>]
member this.Delete(id:int) =
()

View File

@ -0,0 +1,32 @@
namespace WebApplication1.Controllers
open System
open System.Collections.Generic
open System.Linq
open System.Threading.Tasks
open Microsoft.AspNetCore.Mvc
type public TemperatureUnit =
| Celsius=0
| Fahrenheit=1
type WeatherResult = {
Location: string
TemperatureUnit: TemperatureUnit
Temperature: int
}
[<Route("api/SampleData/[controller]")>]
[<ApiController>]
type WeatherController () =
inherit ControllerBase()
[<HttpGet>]
member this.Get(location:string, unit: TemperatureUnit) =
let rnd = System.Random()
let result:WeatherResult = {
Location = location;
Temperature = rnd.Next(-20,55);
TemperatureUnit = unit
}
ActionResult<WeatherResult>(result)

View File

@ -48,7 +48,7 @@ namespace Templates.Test
aspNetProcess.Process.HasExited,
ErrorMessages.GetFailedProcessMessageOrEmpty("Run built project", Project, aspNetProcess.Process));
await aspNetProcess.AssertOk("/api/values");
await aspNetProcess.AssertOk("/api/SampleData/Weather");
await aspNetProcess.AssertNotFound("/");
}
@ -59,7 +59,7 @@ namespace Templates.Test
ErrorMessages.GetFailedProcessMessageOrEmpty("Run published project", Project, aspNetProcess.Process));
await aspNetProcess.AssertOk("/api/values");
await aspNetProcess.AssertOk("/api/SampleData/Weather");
await aspNetProcess.AssertNotFound("/");
}
}

View File

@ -404,7 +404,7 @@
"appsettings.json",
"Program.cs",
"Startup.cs",
"Controllers/ValuesController.cs",
"Controllers/WeatherController.cs",
"Properties/launchSettings.json"
],
"AuthOption": "IndividualB2C"
@ -417,7 +417,7 @@
"appsettings.json",
"Program.cs",
"Startup.cs",
"Controllers/ValuesController.cs",
"Controllers/WeatherController.cs",
"Properties/launchSettings.json"
],
"AuthOption": "SingleOrg"
@ -430,7 +430,7 @@
"appsettings.json",
"Program.cs",
"Startup.cs",
"Controllers/ValuesController.cs",
"Controllers/WeatherController.cs",
"Properties/launchSettings.json"
],
"AuthOption": "None"
@ -443,7 +443,7 @@
"appsettings.json",
"Program.cs",
"Startup.cs",
"Controllers/ValuesController.cs",
"Controllers/WeatherController.cs",
"Properties/launchSettings.json"
],
"AuthOption": "Windows"
@ -456,7 +456,7 @@
"appsettings.json",
"Program.fs",
"Startup.fs",
"Controllers/ValuesController.fs",
"Controllers/WeatherController.fs",
"Properties/launchSettings.json"
]
}

View File

@ -256,7 +256,7 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
Response.ContentType = "text/html;charset=UTF-8";
// Emit Cache-Control=no-cache to prevent client caching.
Response.Headers[HeaderNames.CacheControl] = "no-cache";
Response.Headers[HeaderNames.CacheControl] = "no-cache, no-store";
Response.Headers[HeaderNames.Pragma] = "no-cache";
Response.Headers[HeaderNames.Expires] = HeaderValueEpocDate;
@ -442,7 +442,7 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
Response.ContentType = "text/html;charset=UTF-8";
// Emit Cache-Control=no-cache to prevent client caching.
Response.Headers[HeaderNames.CacheControl] = "no-cache";
Response.Headers[HeaderNames.CacheControl] = "no-cache, no-store";
Response.Headers[HeaderNames.Pragma] = "no-cache";
Response.Headers[HeaderNames.Expires] = HeaderValueEpocDate;

View File

@ -11,16 +11,28 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal
{
// Category: DefaultHttpsProvider
private static readonly Action<ILogger, string, string, Exception> _locatedDevelopmentCertificate =
LoggerMessage.Define<string, string>(LogLevel.Debug, new EventId(0, nameof(LocatedDevelopmentCertificate)), "Using development certificate: {certificateSubjectName} (Thumbprint: {certificateThumbprint})");
LoggerMessage.Define<string, string>(
LogLevel.Debug,
new EventId(0, "LocatedDevelopmentCertificate"),
"Using development certificate: {certificateSubjectName} (Thumbprint: {certificateThumbprint})");
private static readonly Action<ILogger, Exception> _unableToLocateDevelopmentCertificate =
LoggerMessage.Define(LogLevel.Debug, new EventId(1, nameof(UnableToLocateDevelopmentCertificate)), "Unable to locate an appropriate development https certificate.");
LoggerMessage.Define(
LogLevel.Debug,
new EventId(1, "UnableToLocateDevelopmentCertificate"),
"Unable to locate an appropriate development https certificate.");
private static readonly Action<ILogger, string, Exception> _failedToLocateDevelopmentCertificateFile =
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(2, nameof(FailedToLocateDevelopmentCertificateFile)), "Failed to locate the development https certificate at '{certificatePath}'.");
LoggerMessage.Define<string>(
LogLevel.Debug,
new EventId(2, "FailedToLocateDevelopmentCertificateFile"),
"Failed to locate the development https certificate at '{certificatePath}'.");
private static readonly Action<ILogger, string, Exception> _failedToLoadDevelopmentCertificate =
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(3, nameof(FailedToLoadDevelopmentCertificate)), "Failed to load the development https certificate at '{certificatePath}'.");
LoggerMessage.Define<string>(
LogLevel.Debug,
new EventId(3, "FailedToLoadDevelopmentCertificate"),
"Failed to load the development https certificate at '{certificatePath}'.");
public static void LocatedDevelopmentCertificate(this ILogger logger, X509Certificate2 certificate) => _locatedDevelopmentCertificate(logger, certificate.Subject, certificate.Thumbprint, null);

View File

@ -3,7 +3,6 @@
using System;
using System.Buffers;
using System.IO.Pipelines;
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv
{
@ -28,9 +27,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv
/// </remarks>
public bool NoDelay { get; set; } = true;
public long? MaxReadBufferSize { get; set; } = PipeOptions.Default.PauseWriterThreshold;
public long? MaxReadBufferSize { get; set; } = 1024 * 1024;
public long? MaxWriteBufferSize { get; set; } = PipeOptions.Default.PauseWriterThreshold;
public long? MaxWriteBufferSize { get; set; } = 64 * 1024;
internal Func<MemoryPool<byte>> MemoryPoolFactory { get; set; } = System.Buffers.MemoryPoolFactory.Create;

View File

@ -3,7 +3,6 @@
using System;
using System.Buffers;
using System.IO.Pipelines;
namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
{
@ -25,9 +24,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets
/// </remarks>
public bool NoDelay { get; set; } = true;
public long? MaxReadBufferSize { get; set; } = PipeOptions.Default.PauseWriterThreshold;
public long? MaxReadBufferSize { get; set; } = 1024 * 1024;
public long? MaxWriteBufferSize { get; set; } = PipeOptions.Default.PauseWriterThreshold;
public long? MaxWriteBufferSize { get; set; } = 64 * 1024;
internal Func<MemoryPool<byte>> MemoryPoolFactory { get; set; } = System.Buffers.MemoryPoolFactory.Create;
}

View File

@ -16,6 +16,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
using Microsoft.AspNetCore.Testing;
using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.Logging.Testing;
using Moq;
using Xunit;
@ -42,6 +43,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests.Http2
};
}
[CollectDump]
[ConditionalFact]
[SkipOnHelix("https://github.com/aspnet/AspNetCore/issues/9985", Queues = "Fedora.28.Amd64.Open")] // https://github.com/aspnet/AspNetCore/issues/9985
[Flaky("https://github.com/aspnet/AspNetCore/issues/9985", FlakyOn.All)]

View File

@ -811,6 +811,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
[Fact]
[Flaky("https://github.com/dotnet/corefx/issues/30691", FlakyOn.AzP.Windows)]
[CollectDump]
public async Task ConnectionNotClosedWhenClientSatisfiesMinimumDataRateGivenLargeResponseHeaders()
{
var headerSize = 1024 * 1024; // 1 MB for each header value

View File

@ -14,6 +14,7 @@ using Microsoft.AspNetCore.Connections.Features;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Testing;
using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.Logging.Testing;
using Xunit;
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
@ -26,6 +27,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
[OSSkipCondition(OperatingSystems.Windows, WindowsVersions.Win7, WindowsVersions.Win8, WindowsVersions.Win81, WindowsVersions.Win2008R2, SkipReason = "UnixDomainSocketEndPoint is not supported on older versions of Windows")]
#endif
[ConditionalFact]
[CollectDump]
public async Task TestUnixDomainSocket()
{
var path = Path.GetTempFileName();

View File

@ -3,7 +3,7 @@
<AspNetCoreMajorVersion>3</AspNetCoreMajorVersion>
<AspNetCoreMinorVersion>0</AspNetCoreMinorVersion>
<AspNetCorePatchVersion>0</AspNetCorePatchVersion>
<PreReleasePreviewNumber>6</PreReleasePreviewNumber>
<PreReleasePreviewNumber>7</PreReleasePreviewNumber>
<PreReleaseLabel>preview$(PreReleasePreviewNumber)</PreReleaseLabel>
<PreReleaseBrandingLabel>Preview $(PreReleasePreviewNumber)</PreReleaseBrandingLabel>
<ExperimentalVersionPrefix>0.3.$(AspNetCorePatchVersion)</ExperimentalVersionPrefix>