Merge release/2.2
This commit is contained in:
parent
11a9bafeb4
commit
737464eafa
|
|
@ -12,11 +12,12 @@ Microsoft.AspNetCore.Mvc.IActionResult</Description>
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Routing.Abstractions" Version="$(MicrosoftAspNetCoreRoutingAbstractionsPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.ClosedGenericMatcher.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.CopyOnWriteDictionary.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.HashCodeCombiner.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.PropertyHelper.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsPropertyHelperSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Net.Http.Headers" Version="$(MicrosoftNetHttpHeadersPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Label="Sources packages">
|
||||
<PackageReference Include="Microsoft.Extensions.ClosedGenericMatcher.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.HashCodeCombiner.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -3,5 +3,35 @@
|
|||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.ApiExplorer, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Core, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Cors, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.DataAnnotations, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Formatters.Json, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Formatters.Xml, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Localization, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.RazorPages, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.TagHelpers, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Testing, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.ViewFeatures, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Abstractions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.ApiExplorer.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Core.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Core.TestCommon, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Cors.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.DataAnnotations.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Formatters.Json.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Formatters.Xml.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.IntegrationTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Localization.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.RazorPages.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.TagHelpers.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.ViewFeatures.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Views.TestCommon, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
|
||||
|
|
|
|||
|
|
@ -10,10 +10,6 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.AspNetCore.Mvc.Core\Microsoft.AspNetCore.Mvc.Core.csproj" />
|
||||
|
||||
<PackageReference Include="Microsoft.Extensions.ClosedGenericMatcher.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.HashCodeCombiner.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.PropertyHelper.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsPropertyHelperSourcesPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@ using System.Linq;
|
|||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
||||
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
||||
using Microsoft.AspNetCore.Mvc.Core;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.AspNetCore.Routing.EndpointConstraints;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Resources = Microsoft.AspNetCore.Mvc.Core.Resources;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ using System.Linq;
|
|||
using System.Threading;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
||||
using Microsoft.AspNetCore.Mvc.Core;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Internal;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Resources = Microsoft.AspNetCore.Mvc.Core.Resources;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Internal
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.Core;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.AspNetCore.Routing.Template;
|
||||
using Microsoft.AspNetCore.Routing.Tree;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Internal;
|
||||
using Resources = Microsoft.AspNetCore.Mvc.Core.Resources;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Internal
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ using Microsoft.AspNetCore.Mvc.Abstractions;
|
|||
using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.AspNetCore.Mvc.Core;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.Routing;
|
||||
using Resources = Microsoft.AspNetCore.Mvc.Core.Resources;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Internal
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ using System.Diagnostics;
|
|||
using System.Runtime.ExceptionServices;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.Core;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.Extensions.Internal;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Resources = Microsoft.AspNetCore.Mvc.Core.Resources;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Internal
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ using System;
|
|||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.Core;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Resources = Microsoft.AspNetCore.Mvc.Core.Resources;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Internal
|
||||
{
|
||||
|
|
|
|||
|
|
@ -293,6 +293,25 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
return invoker.InvokeAsync();
|
||||
};
|
||||
|
||||
var metadataCollection = BuildEndpointMetadata(action, routeName, source);
|
||||
var endpoint = new MatcherEndpoint(
|
||||
next => invokerDelegate,
|
||||
template,
|
||||
new RouteValueDictionary(nonInlineDefaults),
|
||||
new RouteValueDictionary(action.RouteValues),
|
||||
order,
|
||||
metadataCollection,
|
||||
action.DisplayName);
|
||||
|
||||
// Use defaults after the endpoint is created as it merges both the inline and
|
||||
// non-inline defaults into one.
|
||||
EnsureRequiredValuesInDefaults(endpoint.RequiredValues, endpoint.Defaults);
|
||||
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
private static EndpointMetadataCollection BuildEndpointMetadata(ActionDescriptor action, string routeName, object source)
|
||||
{
|
||||
var metadata = new List<object>();
|
||||
// REVIEW: Used for debugging. Consider removing before release
|
||||
metadata.Add(source);
|
||||
|
|
@ -312,30 +331,27 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
|
||||
if (action.ActionConstraints != null && action.ActionConstraints.Count > 0)
|
||||
{
|
||||
// REVIEW: What is the best way to pick up endpoint constraints of an ActionDescriptor?
|
||||
// Currently they need to implement IActionConstraintMetadata
|
||||
foreach (var actionConstraint in action.ActionConstraints)
|
||||
{
|
||||
if (actionConstraint is HttpMethodActionConstraint httpMethodActionConstraint)
|
||||
{
|
||||
metadata.Add(new HttpMethodEndpointConstraint(httpMethodActionConstraint.HttpMethods));
|
||||
}
|
||||
else if (actionConstraint is IEndpointConstraintMetadata)
|
||||
{
|
||||
// The constraint might have been added earlier, e.g. it is also a filter descriptor
|
||||
if (!metadata.Contains(actionConstraint))
|
||||
{
|
||||
metadata.Add(actionConstraint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var metadataCollection = new EndpointMetadataCollection(metadata);
|
||||
var endpoint = new MatcherEndpoint(
|
||||
next => invokerDelegate,
|
||||
template,
|
||||
new RouteValueDictionary(nonInlineDefaults),
|
||||
new RouteValueDictionary(action.RouteValues),
|
||||
order,
|
||||
metadataCollection,
|
||||
action.DisplayName);
|
||||
|
||||
// Use defaults after the endpoint is created as it merges both the inline and
|
||||
// non-inline defaults into one.
|
||||
EnsureRequiredValuesInDefaults(endpoint.RequiredValues, endpoint.Defaults);
|
||||
|
||||
return endpoint;
|
||||
return metadataCollection;
|
||||
}
|
||||
|
||||
// Ensure required values are a subset of defaults
|
||||
|
|
|
|||
|
|
@ -24,24 +24,27 @@ Microsoft.AspNetCore.Mvc.RouteAttribute</Description>
|
|||
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="$(MicrosoftAspNetCoreHostingAbstractionsPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="$(MicrosoftAspNetCoreHttpPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="$(MicrosoftAspNetCoreHttpExtensionsPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.RangeHelper.Sources" PrivateAssets="All" Version="$(MicrosoftAspNetCoreRangeHelperSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.ResponseCaching.Abstractions" Version="$(MicrosoftAspNetCoreResponseCachingAbstractionsPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Routing" Version="$(MicrosoftAspNetCoreRoutingPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.ClosedGenericMatcher.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="$(MicrosoftExtensionsDependencyModelPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.FileProviders.Abstractions" Version="$(MicrosoftExtensionsFileProvidersAbstractionsPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.HashCodeCombiner.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MicrosoftExtensionsLoggingAbstractionsPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectMethodExecutor.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsObjectMethodExecutorSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.ParameterDefaultValue.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.PropertyActivator.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsPropertyActivatorSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.PropertyHelper.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsPropertyHelperSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.SecurityHelper.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsSecurityHelperSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.TypeNameHelper.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsTypeNameHelperSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.ValueStopwatch.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsValueStopwatchSourcesPackageVersion)" />
|
||||
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="$(SystemDiagnosticsDiagnosticSourcePackageVersion)" />
|
||||
<PackageReference Include="System.Threading.Tasks.Extensions" Version="$(SystemThreadingTasksExtensionsPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<ItemGroup Label="Sources packages">
|
||||
<PackageReference Include="Microsoft.AspNetCore.ChunkingCookieManager.Sources" PrivateAssets="All" Version="$(MicrosoftAspNetCoreChunkingCookieManagerSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.CopyOnWriteDictionary.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectMethodExecutor.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsObjectMethodExecutorSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.ParameterDefaultValue.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.PropertyActivator.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsPropertyActivatorSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.PropertyHelper.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsPropertyHelperSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.RangeHelper.Sources" PrivateAssets="All" Version="$(MicrosoftAspNetCoreRangeHelperSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.SecurityHelper.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsSecurityHelperSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.TypeNameHelper.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsTypeNameHelperSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.ValueStopwatch.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsValueStopwatchSourcesPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -4,8 +4,36 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: TypeForwardedTo(typeof(InputFormatterException))]
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.ApiExplorer, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Cors, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.DataAnnotations, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Formatters.Json, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Formatters.Xml, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Localization, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.RazorPages, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.TagHelpers, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Testing, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.ViewFeatures, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Abstractions.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.ApiExplorer.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Core.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Core.TestCommon, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Cors.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.DataAnnotations.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Formatters.Json.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Formatters.Xml.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.IntegrationTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Localization.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.RazorPages.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.TagHelpers.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.ViewFeatures.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Views.TestCommon, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
|
||||
[assembly: TypeForwardedTo(typeof(InputFormatterException))]
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@
|
|||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.AspNetCore.Mvc.Core\Microsoft.AspNetCore.Mvc.Core.csproj" />
|
||||
|
||||
<PackageReference Include="Microsoft.Extensions.ClosedGenericMatcher.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.CopyOnWriteDictionary.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="$(MicrosoftExtensionsLocalizationPackageVersion)" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="$(SystemComponentModelAnnotationsPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -10,8 +10,5 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.AspNetCore.Mvc.Core\Microsoft.AspNetCore.Mvc.Core.csproj" />
|
||||
|
||||
<PackageReference Include="Microsoft.Extensions.ClosedGenericMatcher.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.PropertyHelper.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsPropertyHelperSourcesPackageVersion)" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ Microsoft.AspNetCore.Mvc.Localization.IViewLocalizer</Description>
|
|||
<PackageReference Include="Microsoft.AspNetCore.Localization" Version="$(MicrosoftAspNetCoreLocalizationPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Localization" Version="$(MicrosoftExtensionsLocalizationPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.PropertyHelper.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsPropertyHelperSourcesPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
using System;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor
|
||||
{
|
||||
internal interface IModelTypeProvider
|
||||
{
|
||||
Type GetModelType();
|
||||
}
|
||||
}
|
||||
|
|
@ -19,10 +19,6 @@
|
|||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="$(MicrosoftCodeAnalysisCSharpPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="$(MicrosoftExtensionsCachingMemoryPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.FileProviders.Composite" Version="$(MicrosoftExtensionsFileProvidersCompositePackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.ClosedGenericMatcher.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.HashCodeCombiner.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.PropertyActivator.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsPropertyActivatorSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.PropertyHelper.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsPropertyHelperSourcesPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -3,5 +3,7 @@
|
|||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.RazorPages, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("Microsoft.AspNetCore.Mvc.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Mvc.Razor.Internal;
|
|||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.AspNetCore.Mvc.Routing;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
using Microsoft.Extensions.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Razor
|
||||
{
|
||||
|
|
@ -19,7 +20,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
|||
{
|
||||
// Name of the "public TModel Model" property on RazorPage<TModel>
|
||||
private const string ModelPropertyName = "Model";
|
||||
private readonly ConcurrentDictionary<Type, RazorPagePropertyActivator> _activationInfo;
|
||||
private readonly ConcurrentDictionary<CacheKey, RazorPagePropertyActivator> _activationInfo;
|
||||
private readonly IModelMetadataProvider _metadataProvider;
|
||||
|
||||
// Value accessors for common singleton properties activated in a RazorPage.
|
||||
|
|
@ -36,7 +37,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
|||
HtmlEncoder htmlEncoder,
|
||||
IModelExpressionProvider modelExpressionProvider)
|
||||
{
|
||||
_activationInfo = new ConcurrentDictionary<Type, RazorPagePropertyActivator>();
|
||||
_activationInfo = new ConcurrentDictionary<CacheKey, RazorPagePropertyActivator>();
|
||||
_metadataProvider = metadataProvider;
|
||||
|
||||
_propertyAccessors = new RazorPagePropertyActivator.PropertyValueAccessors
|
||||
|
|
@ -62,26 +63,76 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
|||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
var propertyActivator = GetOrAddCacheEntry(page);
|
||||
propertyActivator.Activate(page, context);
|
||||
}
|
||||
|
||||
internal RazorPagePropertyActivator GetOrAddCacheEntry(IRazorPage page)
|
||||
{
|
||||
var pageType = page.GetType();
|
||||
RazorPagePropertyActivator propertyActivator;
|
||||
if (!_activationInfo.TryGetValue(pageType, out propertyActivator))
|
||||
Type providedModelType = null;
|
||||
if (page is IModelTypeProvider modelTypeProvider)
|
||||
{
|
||||
providedModelType = modelTypeProvider.GetModelType();
|
||||
}
|
||||
|
||||
// We only need to vary by providedModelType since it varies at runtime. Defined model type
|
||||
// is synonymous with the pageType and consequently does not need to be accounted for in the cache key.
|
||||
var cacheKey = new CacheKey(pageType, providedModelType);
|
||||
if (!_activationInfo.TryGetValue(cacheKey, out var propertyActivator))
|
||||
{
|
||||
// Look for a property named "Model". If it is non-null, we'll assume this is
|
||||
// the equivalent of TModel Model property on RazorPage<TModel>.
|
||||
//
|
||||
// Otherwise if we don't have a model property the activator will just skip setting
|
||||
// the view data.
|
||||
var modelType = pageType.GetRuntimeProperty(ModelPropertyName)?.PropertyType;
|
||||
var modelType = providedModelType;
|
||||
if (modelType == null)
|
||||
{
|
||||
modelType = pageType.GetRuntimeProperty(ModelPropertyName)?.PropertyType;
|
||||
}
|
||||
|
||||
propertyActivator = new RazorPagePropertyActivator(
|
||||
pageType,
|
||||
modelType,
|
||||
_metadataProvider,
|
||||
_propertyAccessors);
|
||||
|
||||
propertyActivator = _activationInfo.GetOrAdd(pageType, propertyActivator);
|
||||
propertyActivator = _activationInfo.GetOrAdd(cacheKey, propertyActivator);
|
||||
}
|
||||
|
||||
propertyActivator.Activate(page, context);
|
||||
return propertyActivator;
|
||||
}
|
||||
|
||||
private readonly struct CacheKey : IEquatable<CacheKey>
|
||||
{
|
||||
public CacheKey(Type pageType, Type providedModelType)
|
||||
{
|
||||
PageType = pageType;
|
||||
ProvidedModelType = providedModelType;
|
||||
}
|
||||
|
||||
public Type PageType { get; }
|
||||
|
||||
public Type ProvidedModelType { get; }
|
||||
|
||||
public bool Equals(CacheKey other)
|
||||
{
|
||||
return PageType == other.PageType &&
|
||||
ProvidedModelType == other.ProvidedModelType;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hashCodeCombiner = HashCodeCombiner.Start();
|
||||
hashCodeCombiner.Add(PageType);
|
||||
if (ProvidedModelType != null)
|
||||
{
|
||||
hashCodeCombiner.Add(ProvidedModelType);
|
||||
}
|
||||
|
||||
return hashCodeCombiner.CombinedHash;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -96,6 +96,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
|||
/// </summary>
|
||||
public IReadOnlyList<IRazorPage> ViewStartPages { get; }
|
||||
|
||||
internal Action<IRazorPage, ViewContext> OnAfterPageActivated { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task RenderAsync(ViewContext context)
|
||||
{
|
||||
|
|
@ -167,6 +169,8 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
|||
page.ViewContext = context;
|
||||
_pageActivator.Activate(page, context);
|
||||
|
||||
OnAfterPageActivated?.Invoke(page, context);
|
||||
|
||||
_diagnosticSource.BeforeViewPage(page, context);
|
||||
|
||||
try
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc.Razor;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Resources = Microsoft.AspNetCore.Mvc.RazorPages.Resources;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
|
|||
using Microsoft.AspNetCore.Mvc.RazorPages.Internal;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Resources = Microsoft.AspNetCore.Mvc.RazorPages.Resources;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
|
|
|
|||
|
|
@ -76,13 +76,29 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
|||
}
|
||||
|
||||
var viewContext = result.Page.ViewContext;
|
||||
var pageAdapter = new RazorPageAdapter(result.Page, pageContext.ActionDescriptor.DeclaredModelTypeInfo);
|
||||
|
||||
viewContext.View = new RazorView(
|
||||
_razorViewEngine,
|
||||
_razorPageActivator,
|
||||
viewStarts,
|
||||
new RazorPageAdapter(result.Page),
|
||||
pageAdapter,
|
||||
_htmlEncoder,
|
||||
_diagnosticSource);
|
||||
_diagnosticSource)
|
||||
{
|
||||
OnAfterPageActivated = (page, currentViewContext) =>
|
||||
{
|
||||
if (page != pageAdapter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// ViewContext is always activated with the "right" ViewData<T> type.
|
||||
// Copy that over to the PageContext since PageContext.ViewData is exposed
|
||||
// as the ViewData property on the Page that the user works with.
|
||||
pageContext.ViewData = currentViewContext.ViewData;
|
||||
},
|
||||
};
|
||||
|
||||
return ExecuteAsync(viewContext, result.ContentType, result.StatusCode);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,10 +14,12 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
|||
//
|
||||
// The page gets activated before handler methods run, but the RazorView will also activate
|
||||
// each page.
|
||||
public class RazorPageAdapter : IRazorPage
|
||||
public class RazorPageAdapter : IRazorPage, IModelTypeProvider
|
||||
{
|
||||
private readonly RazorPageBase _page;
|
||||
private readonly Type _modelType;
|
||||
|
||||
[Obsolete("This constructor is obsolete and will be removed in a future version.")]
|
||||
public RazorPageAdapter(RazorPageBase page)
|
||||
{
|
||||
if (page == null)
|
||||
|
|
@ -28,6 +30,12 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
|||
_page = page;
|
||||
}
|
||||
|
||||
public RazorPageAdapter(RazorPageBase page, Type modelType)
|
||||
{
|
||||
_page = page ?? throw new ArgumentNullException(nameof(page));
|
||||
_modelType = modelType ?? throw new ArgumentNullException(nameof(modelType));
|
||||
}
|
||||
|
||||
public ViewContext ViewContext
|
||||
{
|
||||
get { return _page.ViewContext; }
|
||||
|
|
@ -75,5 +83,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
|||
{
|
||||
return _page.ExecuteAsync();
|
||||
}
|
||||
|
||||
Type IModelTypeProvider.GetModelType() => _modelType;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,16 +10,6 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Microsoft.AspNetCore.Mvc.Razor\Microsoft.AspNetCore.Mvc.Razor.csproj" />
|
||||
|
||||
<PackageReference Include="Microsoft.Extensions.ClosedGenericMatcher.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.CopyOnWriteDictionary.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.ParameterDefaultValue.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsParameterDefaultValueSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.PropertyActivator.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsPropertyActivatorSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.PropertyHelper.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsPropertyHelperSourcesPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Filters\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@
|
|||
<PackageReference Include="Microsoft.AspNetCore.Routing.Abstractions" Version="$(MicrosoftAspNetCoreRoutingAbstractionsPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="$(MicrosoftExtensionsCachingMemoryPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" Version="$(MicrosoftExtensionsFileSystemGlobbingPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.HashCodeCombiner.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Primitives" Version="$(MicrosoftExtensionsPrimitivesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.PropertyHelper.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsPropertyHelperSourcesPackageVersion)" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -19,16 +19,8 @@ Microsoft.AspNetCore.Mvc.ViewComponent</Description>
|
|||
<ProjectReference Include="..\Microsoft.AspNetCore.Mvc.Formatters.Json\Microsoft.AspNetCore.Mvc.Formatters.Json.csproj" />
|
||||
|
||||
<PackageReference Include="Microsoft.AspNetCore.Antiforgery" Version="$(MicrosoftAspNetCoreAntiforgeryPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.ChunkingCookieManager.Sources" PrivateAssets="All" Version="$(MicrosoftAspNetCoreChunkingCookieManagerSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.Abstractions" Version="$(MicrosoftAspNetCoreDiagnosticsAbstractionsPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Html.Abstractions" Version="$(MicrosoftAspNetCoreHtmlAbstractionsPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.ClosedGenericMatcher.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsClosedGenericMatcherSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.CopyOnWriteDictionary.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsCopyOnWriteDictionarySourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectMethodExecutor.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsObjectMethodExecutorSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.HashCodeCombiner.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsHashCodeCombinerSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.PropertyActivator.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsPropertyActivatorSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.PropertyHelper.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsPropertyHelperSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.ValueStopwatch.Sources" PrivateAssets="All" Version="$(MicrosoftExtensionsValueStopwatchSourcesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.WebEncoders" Version="$(MicrosoftExtensionsWebEncodersPackageVersion)" />
|
||||
<PackageReference Include="Newtonsoft.Json.Bson" Version="$(NewtonsoftJsonBsonPackageVersion)" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Globalization;
|
||||
using Microsoft.AspNetCore.Mvc.DataAnnotations.Test;
|
||||
using Resources = Microsoft.AspNetCore.Mvc.DataAnnotations.Test.Resources;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||
{
|
||||
|
|
|
|||
|
|
@ -607,6 +607,22 @@ Hello from /Pages/Shared/";
|
|||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ViewDataSetInViewStart_IsAvailableToPage()
|
||||
{
|
||||
// Arrange & Act
|
||||
var document = await Client.GetHtmlDocumentAsync("/ViewData/ViewDataSetInViewStart");
|
||||
|
||||
// Assert
|
||||
var valueSetInViewStart = document.RequiredQuerySelector("#valuefromviewstart").TextContent;
|
||||
var valueSetInPageModel = document.RequiredQuerySelector("#valuefrompagemodel").TextContent;
|
||||
var valueSetInPage = document.RequiredQuerySelector("#valuefrompage").TextContent;
|
||||
|
||||
Assert.Equal("Value from _ViewStart", valueSetInViewStart);
|
||||
Assert.Equal("Value from Page Model", valueSetInPageModel);
|
||||
Assert.Equal("Value from Page", valueSetInPage);
|
||||
}
|
||||
|
||||
private async Task AddAntiforgeryHeadersAsync(HttpRequestMessage request)
|
||||
{
|
||||
var response = await Client.GetAsync(request.RequestUri);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||
{
|
||||
public class VersioningDispatchingTests : VersioningTestsBase<VersioningWebSite.StartupWithDispatching>
|
||||
{
|
||||
public VersioningDispatchingTests(MvcTestFixture<VersioningWebSite.StartupWithDispatching> fixture)
|
||||
: base(fixture)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,562 +1,13 @@
|
|||
// 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;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||
{
|
||||
public class VersioningTests : IClassFixture<MvcTestFixture<VersioningWebSite.Startup>>
|
||||
public class VersioningTests : VersioningTestsBase<VersioningWebSite.Startup>
|
||||
{
|
||||
public VersioningTests(MvcTestFixture<VersioningWebSite.Startup> fixture)
|
||||
: base(fixture)
|
||||
{
|
||||
Client = fixture.CreateDefaultClient();
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
||||
[Theory]
|
||||
[InlineData("1")]
|
||||
[InlineData("2")]
|
||||
public async Task AttributeRoutedAction_WithVersionedRoutes_IsNotAmbiguous(string version)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/api/Addresses?version=" + version);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Contains("api/addresses", result.ExpectedUrls);
|
||||
Assert.Equal("Address", result.Controller);
|
||||
Assert.Equal("GetV" + version, result.Action);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("1")]
|
||||
[InlineData("2")]
|
||||
public async Task AttributeRoutedAction_WithAmbiguousVersionedRoutes_CanBeDisambiguatedUsingOrder(string version)
|
||||
{
|
||||
// Arrange
|
||||
var query = "?version=" + version;
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/api/Addresses/All" + query);
|
||||
|
||||
// Act
|
||||
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Contains("/api/addresses/all?version=" + version, result.ExpectedUrls);
|
||||
Assert.Equal("Address", result.Controller);
|
||||
Assert.Equal("GetAllV" + version, result.Action);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VersionedApi_CanReachV1Operations_OnTheSameController_WithNoVersionSpecified()
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Tickets");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Tickets", result.Controller);
|
||||
Assert.Equal("Get", result.Action);
|
||||
|
||||
Assert.DoesNotContain("id", result.RouteValues.Keys);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VersionedApi_CanReachV1Operations_OnTheSameController_WithVersionSpecified()
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Tickets?version=2");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Tickets", result.Controller);
|
||||
Assert.Equal("Get", result.Action);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VersionedApi_CanReachV1OperationsWithParameters_OnTheSameController()
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Tickets/5");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Tickets", result.Controller);
|
||||
Assert.Equal("GetById", result.Action);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VersionedApi_CanReachV1OperationsWithParameters_OnTheSameController_WithVersionSpecified()
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Tickets/5?version=2");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Tickets", result.Controller);
|
||||
Assert.Equal("GetById", result.Action);
|
||||
Assert.NotEmpty(result.RouteValues);
|
||||
|
||||
Assert.Contains(
|
||||
new KeyValuePair<string, object>("id", "5"),
|
||||
result.RouteValues);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("2")]
|
||||
[InlineData("3")]
|
||||
[InlineData("4")]
|
||||
public async Task VersionedApi_CanReachOtherVersionOperations_OnTheSameController(string version)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Post, "http://localhost/Tickets?version=" + version);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Tickets", result.Controller);
|
||||
Assert.Equal("Post", result.Action);
|
||||
Assert.NotEmpty(result.RouteValues);
|
||||
|
||||
Assert.DoesNotContain(
|
||||
new KeyValuePair<string, object>("id", "5"),
|
||||
result.RouteValues);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VersionedApi_CanNotReachOtherVersionOperations_OnTheSameController_WithNoVersionSpecified()
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Post, "http://localhost/Tickets");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsByteArrayAsync();
|
||||
Assert.Empty(body);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("PUT", "Put", "2")]
|
||||
[InlineData("PUT", "Put", "3")]
|
||||
[InlineData("PUT", "Put", "4")]
|
||||
[InlineData("DELETE", "Delete", "2")]
|
||||
[InlineData("DELETE", "Delete", "3")]
|
||||
[InlineData("DELETE", "Delete", "4")]
|
||||
public async Task VersionedApi_CanReachOtherVersionOperationsWithParameters_OnTheSameController(
|
||||
string method,
|
||||
string action,
|
||||
string version)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(new HttpMethod(method), "http://localhost/Tickets/5?version=" + version);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Tickets", result.Controller);
|
||||
Assert.Equal(action, result.Action);
|
||||
Assert.NotEmpty(result.RouteValues);
|
||||
|
||||
Assert.Contains(
|
||||
new KeyValuePair<string, object>("id", "5"),
|
||||
result.RouteValues);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("PUT")]
|
||||
[InlineData("DELETE")]
|
||||
public async Task VersionedApi_CanNotReachOtherVersionOperationsWithParameters_OnTheSameController_WithNoVersionSpecified(string method)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(new HttpMethod(method), "http://localhost/Tickets/5");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsByteArrayAsync();
|
||||
Assert.Empty(body);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("3")]
|
||||
[InlineData("4")]
|
||||
[InlineData("5")]
|
||||
public async Task VersionedApi_CanUseOrderToDisambiguate_OverlappingVersionRanges(string version)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Books?version=" + version);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Books", result.Controller);
|
||||
Assert.Equal("GetBreakingChange", result.Action);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("1")]
|
||||
[InlineData("2")]
|
||||
[InlineData("6")]
|
||||
public async Task VersionedApi_OverlappingVersionRanges_FallsBackToLowerOrderAction(string version)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Books?version=" + version);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Books", result.Controller);
|
||||
Assert.Equal("Get", result.Action);
|
||||
}
|
||||
|
||||
|
||||
[Theory]
|
||||
[InlineData("GET", "Get")]
|
||||
[InlineData("POST", "Post")]
|
||||
public async Task VersionedApi_CanReachV1Operations_OnTheOriginalController_WithNoVersionSpecified(string method, string action)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(new HttpMethod(method), "http://localhost/Movies");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Movies", result.Controller);
|
||||
Assert.Equal(action, result.Action);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("GET", "Get")]
|
||||
[InlineData("POST", "Post")]
|
||||
public async Task VersionedApi_CanReachV1Operations_OnTheOriginalController_WithVersionSpecified(string method, string action)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(new HttpMethod(method), "http://localhost/Movies?version=2");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Movies", result.Controller);
|
||||
Assert.Equal(action, result.Action);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("GET", "GetById")]
|
||||
[InlineData("PUT", "Put")]
|
||||
[InlineData("DELETE", "Delete")]
|
||||
public async Task VersionedApi_CanReachV1OperationsWithParameters_OnTheOriginalController(string method, string action)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(new HttpMethod(method), "http://localhost/Movies/5");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Movies", result.Controller);
|
||||
Assert.Equal(action, result.Action);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("GET", "GetById")]
|
||||
[InlineData("DELETE", "Delete")]
|
||||
public async Task VersionedApi_CanReachV1OperationsWithParameters_OnTheOriginalController_WithVersionSpecified(string method, string action)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(new HttpMethod(method), "http://localhost/Movies/5?version=2");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Movies", result.Controller);
|
||||
Assert.Equal(action, result.Action);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VersionedApi_CanReachOtherVersionOperationsWithParameters_OnTheV2Controller()
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Put, "http://localhost/Movies/5?version=2");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("MoviesV2", result.Controller);
|
||||
Assert.Equal("Put", result.Action);
|
||||
Assert.NotEmpty(result.RouteValues);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("v1/Pets")]
|
||||
[InlineData("v2/Pets")]
|
||||
public async Task VersionedApi_CanHaveTwoRoutesWithVersionOnTheUrl_OnTheSameAction(string url)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/" + url);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Pets", result.Controller);
|
||||
Assert.Equal("Get", result.Action);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("v1/Pets/5", "V1")]
|
||||
[InlineData("v2/Pets/5", "V2")]
|
||||
public async Task VersionedApi_CanHaveTwoRoutesWithVersionOnTheUrl_OnDifferentActions(string url, string version)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/" + url);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Pets", result.Controller);
|
||||
Assert.Equal("Get" + version, result.Action);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("v1/Pets", "V1")]
|
||||
[InlineData("v2/Pets", "V2")]
|
||||
public async Task VersionedApi_CanHaveTwoRoutesWithVersionOnTheUrl_OnDifferentActions_WithInlineConstraint(string url, string version)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Post, "http://localhost/" + url);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Pets", result.Controller);
|
||||
Assert.Equal("Post" + version, result.Action);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Customers/5", "?version=1", "Get")]
|
||||
[InlineData("Customers/5", "?version=2", "Get")]
|
||||
[InlineData("Customers/5", "?version=3", "GetV3ToV5")]
|
||||
[InlineData("Customers/5", "?version=4", "GetV3ToV5")]
|
||||
[InlineData("Customers/5", "?version=5", "GetV3ToV5")]
|
||||
public async Task VersionedApi_CanProvideVersioningInformation_UsingPlainActionConstraint(string url, string query, string actionName)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/" + url + query);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Customers", result.Controller);
|
||||
Assert.Equal(actionName, result.Action);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VersionedApi_ConstraintOrder_IsRespected()
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Post, "http://localhost/" + "Customers?version=2");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Customers", result.Controller);
|
||||
Assert.Equal("AnyV2OrHigher", result.Action);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VersionedApi_CanUseConstraintOrder_ToChangeSelectedAction()
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Delete, "http://localhost/" + "Customers/5?version=2");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Customers", result.Controller);
|
||||
Assert.Equal("Delete", result.Action);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("1")]
|
||||
[InlineData("2")]
|
||||
public async Task VersionedApi_MultipleVersionsUsingAttributeRouting_OnTheSameMethod(string version)
|
||||
{
|
||||
// Arrange
|
||||
var path = "/" + version + "/Vouchers?version=" + version;
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost" + path);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Vouchers", result.Controller);
|
||||
Assert.Equal("GetVouchersMultipleVersions", result.Action);
|
||||
|
||||
var actualUrl = Assert.Single(result.ExpectedUrls);
|
||||
Assert.Equal(path, actualUrl);
|
||||
}
|
||||
|
||||
private class RoutingResult
|
||||
{
|
||||
public string[] ExpectedUrls { get; set; }
|
||||
|
||||
public string ActualUrl { get; set; }
|
||||
|
||||
public Dictionary<string, object> RouteValues { get; set; }
|
||||
|
||||
public string RouteName { get; set; }
|
||||
|
||||
public string Action { get; set; }
|
||||
|
||||
public string Controller { get; set; }
|
||||
|
||||
public string Link { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,568 @@
|
|||
// 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;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||
{
|
||||
public abstract class VersioningTestsBase<TStartup> : IClassFixture<MvcTestFixture<TStartup>> where TStartup : class
|
||||
{
|
||||
protected VersioningTestsBase(MvcTestFixture<TStartup> fixture)
|
||||
{
|
||||
var factory = fixture.Factories.FirstOrDefault() ?? fixture.WithWebHostBuilder(ConfigureWebHostBuilder);
|
||||
Client = factory.CreateDefaultClient();
|
||||
}
|
||||
|
||||
private static void ConfigureWebHostBuilder(IWebHostBuilder builder) =>
|
||||
builder.UseStartup<TStartup>();
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
||||
[Theory]
|
||||
[InlineData("1")]
|
||||
[InlineData("2")]
|
||||
public async Task AttributeRoutedAction_WithVersionedRoutes_IsNotAmbiguous(string version)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/api/Addresses?version=" + version);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Contains("api/addresses", result.ExpectedUrls);
|
||||
Assert.Equal("Address", result.Controller);
|
||||
Assert.Equal("GetV" + version, result.Action);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("1")]
|
||||
[InlineData("2")]
|
||||
public async Task AttributeRoutedAction_WithAmbiguousVersionedRoutes_CanBeDisambiguatedUsingOrder(string version)
|
||||
{
|
||||
// Arrange
|
||||
var query = "?version=" + version;
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/api/Addresses/All" + query);
|
||||
|
||||
// Act
|
||||
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Contains("/api/addresses/all?version=" + version, result.ExpectedUrls);
|
||||
Assert.Equal("Address", result.Controller);
|
||||
Assert.Equal("GetAllV" + version, result.Action);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VersionedApi_CanReachV1Operations_OnTheSameController_WithNoVersionSpecified()
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Tickets");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Tickets", result.Controller);
|
||||
Assert.Equal("Get", result.Action);
|
||||
|
||||
Assert.DoesNotContain("id", result.RouteValues.Keys);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VersionedApi_CanReachV1Operations_OnTheSameController_WithVersionSpecified()
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Tickets?version=2");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Tickets", result.Controller);
|
||||
Assert.Equal("Get", result.Action);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VersionedApi_CanReachV1OperationsWithParameters_OnTheSameController()
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Tickets/5");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Tickets", result.Controller);
|
||||
Assert.Equal("GetById", result.Action);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VersionedApi_CanReachV1OperationsWithParameters_OnTheSameController_WithVersionSpecified()
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Tickets/5?version=2");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Tickets", result.Controller);
|
||||
Assert.Equal("GetById", result.Action);
|
||||
Assert.NotEmpty(result.RouteValues);
|
||||
|
||||
Assert.Contains(
|
||||
new KeyValuePair<string, object>("id", "5"),
|
||||
result.RouteValues);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("2")]
|
||||
[InlineData("3")]
|
||||
[InlineData("4")]
|
||||
public async Task VersionedApi_CanReachOtherVersionOperations_OnTheSameController(string version)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Post, "http://localhost/Tickets?version=" + version);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Tickets", result.Controller);
|
||||
Assert.Equal("Post", result.Action);
|
||||
Assert.NotEmpty(result.RouteValues);
|
||||
|
||||
Assert.DoesNotContain(
|
||||
new KeyValuePair<string, object>("id", "5"),
|
||||
result.RouteValues);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VersionedApi_CanNotReachOtherVersionOperations_OnTheSameController_WithNoVersionSpecified()
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Post, "http://localhost/Tickets");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsByteArrayAsync();
|
||||
Assert.Empty(body);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("PUT", "Put", "2")]
|
||||
[InlineData("PUT", "Put", "3")]
|
||||
[InlineData("PUT", "Put", "4")]
|
||||
[InlineData("DELETE", "Delete", "2")]
|
||||
[InlineData("DELETE", "Delete", "3")]
|
||||
[InlineData("DELETE", "Delete", "4")]
|
||||
public async Task VersionedApi_CanReachOtherVersionOperationsWithParameters_OnTheSameController(
|
||||
string method,
|
||||
string action,
|
||||
string version)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(new HttpMethod(method), "http://localhost/Tickets/5?version=" + version);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Tickets", result.Controller);
|
||||
Assert.Equal(action, result.Action);
|
||||
Assert.NotEmpty(result.RouteValues);
|
||||
|
||||
Assert.Contains(
|
||||
new KeyValuePair<string, object>("id", "5"),
|
||||
result.RouteValues);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("PUT")]
|
||||
[InlineData("DELETE")]
|
||||
public async Task VersionedApi_CanNotReachOtherVersionOperationsWithParameters_OnTheSameController_WithNoVersionSpecified(string method)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(new HttpMethod(method), "http://localhost/Tickets/5");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsByteArrayAsync();
|
||||
Assert.Empty(body);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("3")]
|
||||
[InlineData("4")]
|
||||
[InlineData("5")]
|
||||
public async Task VersionedApi_CanUseOrderToDisambiguate_OverlappingVersionRanges(string version)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Books?version=" + version);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Books", result.Controller);
|
||||
Assert.Equal("GetBreakingChange", result.Action);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("1")]
|
||||
[InlineData("2")]
|
||||
[InlineData("6")]
|
||||
public async Task VersionedApi_OverlappingVersionRanges_FallsBackToLowerOrderAction(string version)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/Books?version=" + version);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Books", result.Controller);
|
||||
Assert.Equal("Get", result.Action);
|
||||
}
|
||||
|
||||
|
||||
[Theory]
|
||||
[InlineData("GET", "Get")]
|
||||
[InlineData("POST", "Post")]
|
||||
public async Task VersionedApi_CanReachV1Operations_OnTheOriginalController_WithNoVersionSpecified(string method, string action)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(new HttpMethod(method), "http://localhost/Movies");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Movies", result.Controller);
|
||||
Assert.Equal(action, result.Action);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("GET", "Get")]
|
||||
[InlineData("POST", "Post")]
|
||||
public async Task VersionedApi_CanReachV1Operations_OnTheOriginalController_WithVersionSpecified(string method, string action)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(new HttpMethod(method), "http://localhost/Movies?version=2");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Movies", result.Controller);
|
||||
Assert.Equal(action, result.Action);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("GET", "GetById")]
|
||||
[InlineData("PUT", "Put")]
|
||||
[InlineData("DELETE", "Delete")]
|
||||
public async Task VersionedApi_CanReachV1OperationsWithParameters_OnTheOriginalController(string method, string action)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(new HttpMethod(method), "http://localhost/Movies/5");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Movies", result.Controller);
|
||||
Assert.Equal(action, result.Action);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("GET", "GetById")]
|
||||
[InlineData("DELETE", "Delete")]
|
||||
public async Task VersionedApi_CanReachV1OperationsWithParameters_OnTheOriginalController_WithVersionSpecified(string method, string action)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(new HttpMethod(method), "http://localhost/Movies/5?version=2");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Movies", result.Controller);
|
||||
Assert.Equal(action, result.Action);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VersionedApi_CanReachOtherVersionOperationsWithParameters_OnTheV2Controller()
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Put, "http://localhost/Movies/5?version=2");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("MoviesV2", result.Controller);
|
||||
Assert.Equal("Put", result.Action);
|
||||
Assert.NotEmpty(result.RouteValues);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("v1/Pets")]
|
||||
[InlineData("v2/Pets")]
|
||||
public async Task VersionedApi_CanHaveTwoRoutesWithVersionOnTheUrl_OnTheSameAction(string url)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/" + url);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Pets", result.Controller);
|
||||
Assert.Equal("Get", result.Action);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("v1/Pets/5", "V1")]
|
||||
[InlineData("v2/Pets/5", "V2")]
|
||||
public async Task VersionedApi_CanHaveTwoRoutesWithVersionOnTheUrl_OnDifferentActions(string url, string version)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/" + url);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Pets", result.Controller);
|
||||
Assert.Equal("Get" + version, result.Action);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("v1/Pets", "V1")]
|
||||
[InlineData("v2/Pets", "V2")]
|
||||
public async Task VersionedApi_CanHaveTwoRoutesWithVersionOnTheUrl_OnDifferentActions_WithInlineConstraint(string url, string version)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Post, "http://localhost/" + url);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Pets", result.Controller);
|
||||
Assert.Equal("Post" + version, result.Action);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Customers/5", "?version=1", "Get")]
|
||||
[InlineData("Customers/5", "?version=2", "Get")]
|
||||
[InlineData("Customers/5", "?version=3", "GetV3ToV5")]
|
||||
[InlineData("Customers/5", "?version=4", "GetV3ToV5")]
|
||||
[InlineData("Customers/5", "?version=5", "GetV3ToV5")]
|
||||
public async Task VersionedApi_CanProvideVersioningInformation_UsingPlainActionConstraint(string url, string query, string actionName)
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost/" + url + query);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Customers", result.Controller);
|
||||
Assert.Equal(actionName, result.Action);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VersionedApi_ConstraintOrder_IsRespected()
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Post, "http://localhost/" + "Customers?version=2");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Customers", result.Controller);
|
||||
Assert.Equal("AnyV2OrHigher", result.Action);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VersionedApi_CanUseConstraintOrder_ToChangeSelectedAction()
|
||||
{
|
||||
// Arrange
|
||||
var message = new HttpRequestMessage(HttpMethod.Delete, "http://localhost/" + "Customers/5?version=2");
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Customers", result.Controller);
|
||||
Assert.Equal("Delete", result.Action);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("1")]
|
||||
[InlineData("2")]
|
||||
public async Task VersionedApi_MultipleVersionsUsingAttributeRouting_OnTheSameMethod(string version)
|
||||
{
|
||||
// Arrange
|
||||
var path = "/" + version + "/Vouchers?version=" + version;
|
||||
var message = new HttpRequestMessage(HttpMethod.Get, "http://localhost" + path);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(message);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonConvert.DeserializeObject<RoutingResult>(body);
|
||||
|
||||
Assert.Equal("Vouchers", result.Controller);
|
||||
Assert.Equal("GetVouchersMultipleVersions", result.Action);
|
||||
|
||||
var actualUrl = Assert.Single(result.ExpectedUrls);
|
||||
Assert.Equal(path, actualUrl);
|
||||
}
|
||||
|
||||
private class RoutingResult
|
||||
{
|
||||
public string[] ExpectedUrls { get; set; }
|
||||
|
||||
public string ActualUrl { get; set; }
|
||||
|
||||
public Dictionary<string, object> RouteValues { get; set; }
|
||||
|
||||
public string RouteName { get; set; }
|
||||
|
||||
public string Action { get; set; }
|
||||
|
||||
public string Controller { get; set; }
|
||||
|
||||
public string Link { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -165,6 +165,69 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
|||
Assert.Throws<InvalidCastException>(() => activator.Activate(instance, viewContext));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Activate_UsesModelFromModelTypeProvider()
|
||||
{
|
||||
// Arrange
|
||||
var activator = CreateActivator();
|
||||
|
||||
var viewData = new ViewDataDictionary<object>(MetadataProvider, new ModelStateDictionary())
|
||||
{
|
||||
{ "key", "value" },
|
||||
};
|
||||
var viewContext = CreateViewContext(viewData);
|
||||
var page = new ModelTypeProviderRazorPage();
|
||||
|
||||
// Act
|
||||
activator.Activate(page, viewContext);
|
||||
|
||||
// Assert
|
||||
Assert.Same(viewContext.ViewData, page.ViewData);
|
||||
Assert.NotSame(viewData, viewContext.ViewData);
|
||||
|
||||
Assert.IsType<ViewDataDictionary<Guid>>(viewContext.ViewData);
|
||||
Assert.Equal("value", viewContext.ViewData["key"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetOrAddCacheEntry_CachesPages()
|
||||
{
|
||||
// Arrange
|
||||
var activator = CreateActivator();
|
||||
var page = new TestRazorPage();
|
||||
|
||||
// Act
|
||||
var result1 = activator.GetOrAddCacheEntry(page);
|
||||
var result2 = activator.GetOrAddCacheEntry(page);
|
||||
|
||||
// Assert
|
||||
Assert.Same(result1, result2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetOrAddCacheEntry_VariesByModelType_IfPageIsModelTypeProvider()
|
||||
{
|
||||
// Arrange
|
||||
var activator = CreateActivator();
|
||||
var page = new ModelTypeProviderRazorPage();
|
||||
|
||||
// Act - 1
|
||||
var result1 = activator.GetOrAddCacheEntry(page);
|
||||
var result2 = activator.GetOrAddCacheEntry(page);
|
||||
|
||||
// Assert - 1
|
||||
Assert.Same(result1, result2);
|
||||
|
||||
// Act - 2
|
||||
page.ModelType = typeof(string);
|
||||
var result3 = activator.GetOrAddCacheEntry(page);
|
||||
var result4 = activator.GetOrAddCacheEntry(page);
|
||||
|
||||
// Assert - 2
|
||||
Assert.Same(result3, result4);
|
||||
Assert.NotSame(result1, result3);
|
||||
}
|
||||
|
||||
private RazorPageActivator CreateActivator()
|
||||
{
|
||||
return new RazorPageActivator(MetadataProvider, UrlHelperFactory, JsonHelper, DiagnosticSource, HtmlEncoder, ModelExpressionProvider);
|
||||
|
|
@ -225,6 +288,21 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
|||
}
|
||||
}
|
||||
|
||||
private class ModelTypeProviderRazorPage : RazorPage, IModelTypeProvider
|
||||
{
|
||||
[RazorInject]
|
||||
public ViewDataDictionary ViewData { get; set; }
|
||||
|
||||
public Type ModelType { get; set; } = typeof(Guid);
|
||||
|
||||
public override Task ExecuteAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Type GetModelType() => ModelType;
|
||||
}
|
||||
|
||||
private abstract class NoModelPropertyBase<TModel> : RazorPage
|
||||
{
|
||||
[RazorInject]
|
||||
|
|
|
|||
|
|
@ -1747,6 +1747,49 @@ namespace Microsoft.AspNetCore.Mvc.Razor
|
|||
Assert.Equal(expected, viewContext.Writer.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RenderAsync_InvokesOnAfterPageActivated()
|
||||
{
|
||||
// Arrange
|
||||
var viewStart = new TestableRazorPage(_ => { });
|
||||
var page = new TestableRazorPage(p => { p.Layout = LayoutPath; });
|
||||
var layout = new TestableRazorPage(p => { p.RenderBodyPublic(); });
|
||||
var expected = new HashSet<IRazorPage>();
|
||||
var onAfterPageActivatedCalled = 0;
|
||||
|
||||
var activated = new HashSet<IRazorPage>();
|
||||
var pageActivator = new Mock<IRazorPageActivator>();
|
||||
pageActivator.Setup(p => p.Activate(It.IsAny<IRazorPage>(), It.IsAny<ViewContext>()))
|
||||
.Callback((IRazorPage p, ViewContext v) => activated.Add(p));
|
||||
|
||||
var viewEngine = new Mock<IRazorViewEngine>();
|
||||
viewEngine.Setup(v => v.FindPage(It.IsAny<ActionContext>(), LayoutPath))
|
||||
.Returns(new RazorPageResult(LayoutPath, layout));
|
||||
|
||||
var view = new RazorView(
|
||||
viewEngine.Object,
|
||||
pageActivator.Object,
|
||||
new[] { viewStart },
|
||||
page,
|
||||
new HtmlTestEncoder(),
|
||||
new DiagnosticListener("Microsoft.AspNetCore.Mvc.Razor"))
|
||||
{
|
||||
OnAfterPageActivated = AssertActivated,
|
||||
};
|
||||
var viewContext = CreateViewContext(view);
|
||||
|
||||
// Act
|
||||
await view.RenderAsync(viewContext);
|
||||
Assert.Equal(3, onAfterPageActivatedCalled);
|
||||
|
||||
void AssertActivated(IRazorPage p, ViewContext v)
|
||||
{
|
||||
onAfterPageActivatedCalled++;
|
||||
expected.Add(p);
|
||||
Assert.Equal(expected, activated);
|
||||
}
|
||||
}
|
||||
|
||||
private static ViewContext CreateViewContext(RazorView view)
|
||||
{
|
||||
var httpContext = new DefaultHttpContext();
|
||||
|
|
|
|||
|
|
@ -1,7 +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 Microsoft.AspNetCore.Mvc.ViewFeatures.Test;
|
||||
using Resources = Microsoft.AspNetCore.Mvc.ViewFeatures.Test.Resources;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace RazorPagesWebSite.ViewDataSetInViewStart
|
||||
{
|
||||
public class Index : PageModel
|
||||
{
|
||||
[ViewData]
|
||||
public string ValueFromPageModel => "Value from Page Model";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
@page
|
||||
@namespace RazorPagesWebSite.ViewDataSetInViewStart
|
||||
@model Index
|
||||
@{
|
||||
ViewData["ValueFromPage"] = "Value from Page";
|
||||
}
|
||||
Sample that shows ViewData attributes being set in a PageModel.
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
@RenderBody()
|
||||
<span id="valuefromviewstart">@ViewData["ValueFromViewStart"]</span>
|
||||
<span id="valuefrompage">@ViewData["ValueFromPage"]</span>
|
||||
<span id="valuefrompagemodel">@ViewData["ValueFromPageModel"]</span>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
@{
|
||||
Layout = "_Layout";
|
||||
ViewData["ValueFromViewStart"] = "Value from _ViewStart";
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
// 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.IO;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
|
||||
namespace VersioningWebSite
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var host = CreateWebHostBuilder(args)
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration();
|
||||
}
|
||||
}
|
||||
|
|
@ -24,21 +24,5 @@ namespace VersioningWebSite
|
|||
{
|
||||
app.UseMvcWithDefaultRoute();
|
||||
}
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var host = CreateWebHostBuilder(args)
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
new WebHostBuilder()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseStartup<Startup>()
|
||||
.UseKestrel()
|
||||
.UseIISIntegration();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// 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.IO;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace VersioningWebSite
|
||||
{
|
||||
public class StartupWithDispatching
|
||||
{
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddDispatcher();
|
||||
|
||||
// Add MVC services to the services container
|
||||
services.AddMvc();
|
||||
|
||||
services.AddScoped<TestResponseGenerator>();
|
||||
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
app.UseDispatcher();
|
||||
|
||||
app.UseMvcWithEndpoint(endpoints =>
|
||||
{
|
||||
endpoints.MapEndpoint(
|
||||
name: "default",
|
||||
template: "{controller=Home}/{action=Index}/{id?}");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,10 +3,11 @@
|
|||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
||||
using Microsoft.AspNetCore.Routing.EndpointConstraints;
|
||||
|
||||
namespace VersioningWebSite
|
||||
{
|
||||
public class VersionAttribute : Attribute, IActionConstraintFactory
|
||||
public class VersionAttribute : Attribute, IActionConstraintFactory, IEndpointConstraintFactory
|
||||
{
|
||||
private int? _maxVersion;
|
||||
private int? _minVersion;
|
||||
|
|
@ -32,7 +33,12 @@ namespace VersioningWebSite
|
|||
|
||||
public bool IsReusable => true;
|
||||
|
||||
public IActionConstraint CreateInstance(IServiceProvider services)
|
||||
IActionConstraint IActionConstraintFactory.CreateInstance(IServiceProvider services)
|
||||
{
|
||||
return new VersionRangeValidator(_minVersion, _maxVersion) { Order = _order ?? 0 };
|
||||
}
|
||||
|
||||
IEndpointConstraint IEndpointConstraintFactory.CreateInstance(IServiceProvider services)
|
||||
{
|
||||
return new VersionRangeValidator(_minVersion, _maxVersion) { Order = _order ?? 0 };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Mvc.Routing;
|
|||
|
||||
namespace VersioningWebSite
|
||||
{
|
||||
public class VersionDeleteAttribute : VersionRoute, IActionHttpMethodProvider
|
||||
public class VersionDeleteAttribute : VersionRouteAttribute, IActionHttpMethodProvider
|
||||
{
|
||||
public VersionDeleteAttribute(string template)
|
||||
: base(template)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Mvc.Routing;
|
|||
|
||||
namespace VersioningWebSite
|
||||
{
|
||||
public class VersionGetAttribute : VersionRoute, IActionHttpMethodProvider
|
||||
public class VersionGetAttribute : VersionRouteAttribute, IActionHttpMethodProvider
|
||||
{
|
||||
public VersionGetAttribute(string template)
|
||||
: base(template)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Mvc.Routing;
|
|||
|
||||
namespace VersioningWebSite
|
||||
{
|
||||
public class VersionPostAttribute : VersionRoute, IActionHttpMethodProvider
|
||||
public class VersionPostAttribute : VersionRouteAttribute, IActionHttpMethodProvider
|
||||
{
|
||||
public VersionPostAttribute(string template)
|
||||
: base(template)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Mvc.Routing;
|
|||
|
||||
namespace VersioningWebSite
|
||||
{
|
||||
public class VersionPutAttribute : VersionRoute, IActionHttpMethodProvider
|
||||
public class VersionPutAttribute : VersionRouteAttribute, IActionHttpMethodProvider
|
||||
{
|
||||
public VersionPutAttribute(string template)
|
||||
: base(template)
|
||||
|
|
|
|||
|
|
@ -3,10 +3,11 @@
|
|||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
||||
using Microsoft.AspNetCore.Routing.EndpointConstraints;
|
||||
|
||||
namespace VersioningWebSite
|
||||
{
|
||||
public class VersionRangeValidator : IActionConstraint
|
||||
public class VersionRangeValidator : IActionConstraint, IEndpointConstraint
|
||||
{
|
||||
private readonly int? _minVersion;
|
||||
private readonly int? _maxVersion;
|
||||
|
|
@ -25,9 +26,19 @@ namespace VersioningWebSite
|
|||
}
|
||||
|
||||
public bool Accept(ActionConstraintContext context)
|
||||
{
|
||||
return ProcessRequest(context.RouteContext.HttpContext.Request);
|
||||
}
|
||||
|
||||
public bool Accept(EndpointConstraintContext context)
|
||||
{
|
||||
return ProcessRequest(context.HttpContext.Request);
|
||||
}
|
||||
|
||||
private bool ProcessRequest(HttpRequest request)
|
||||
{
|
||||
int version;
|
||||
if (int.TryParse(GetVersion(context.RouteContext.HttpContext.Request), out version))
|
||||
if (int.TryParse(GetVersion(request), out version))
|
||||
{
|
||||
return (_minVersion == null || _minVersion <= version) &&
|
||||
(_maxVersion == null || _maxVersion >= version);
|
||||
|
|
|
|||
|
|
@ -5,12 +5,13 @@ using System;
|
|||
using System.Text.RegularExpressions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
||||
using Microsoft.AspNetCore.Routing.EndpointConstraints;
|
||||
|
||||
namespace VersioningWebSite
|
||||
{
|
||||
public class VersionRoute : RouteAttribute, IActionConstraintFactory
|
||||
public class VersionRouteAttribute : RouteAttribute, IActionConstraintFactory, IEndpointConstraintFactory
|
||||
{
|
||||
private readonly IActionConstraint _constraint;
|
||||
private readonly IActionConstraint _actionConstraint;
|
||||
|
||||
// 5
|
||||
// [5]
|
||||
|
|
@ -28,12 +29,12 @@ namespace VersioningWebSite
|
|||
|
||||
public bool IsReusable => true;
|
||||
|
||||
public VersionRoute(string template)
|
||||
public VersionRouteAttribute(string template)
|
||||
: base(template)
|
||||
{
|
||||
}
|
||||
|
||||
public VersionRoute(string template, string versionRange)
|
||||
public VersionRouteAttribute(string template, string versionRange)
|
||||
: base(template)
|
||||
{
|
||||
var constraint = CreateVersionConstraint(versionRange);
|
||||
|
|
@ -44,7 +45,7 @@ namespace VersioningWebSite
|
|||
throw new ArgumentException(message, "versionRange");
|
||||
}
|
||||
|
||||
_constraint = constraint;
|
||||
_actionConstraint = constraint;
|
||||
}
|
||||
|
||||
private static IActionConstraint CreateVersionConstraint(string versionRange)
|
||||
|
|
@ -122,9 +123,14 @@ namespace VersioningWebSite
|
|||
}
|
||||
}
|
||||
|
||||
public IActionConstraint CreateInstance(IServiceProvider services)
|
||||
IActionConstraint IActionConstraintFactory.CreateInstance(IServiceProvider services)
|
||||
{
|
||||
return _constraint;
|
||||
return _actionConstraint;
|
||||
}
|
||||
|
||||
IEndpointConstraint IEndpointConstraintFactory.CreateInstance(IServiceProvider services)
|
||||
{
|
||||
return (IEndpointConstraint)_actionConstraint;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue