Merge remote-tracking branch 'origin/release/2.2'
This commit is contained in:
commit
7a70c6c690
15
Mvc.sln
15
Mvc.sln
|
|
@ -178,6 +178,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicViews", "benchmarkapps
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mvc.Api.Analyzers.Test", "test\Mvc.Api.Analyzers.Test\Mvc.Api.Analyzers.Test.csproj", "{DD7B9F20-354C-4D9E-8C8A-8AE6E7595A87}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mvc.Api.Analyzers.Test", "test\Mvc.Api.Analyzers.Test\Mvc.Api.Analyzers.Test.csproj", "{DD7B9F20-354C-4D9E-8C8A-8AE6E7595A87}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.AspNetCore.Mvc.Api.Analyzers", "src\Microsoft.AspNetCore.Mvc.Api.Analyzers\Microsoft.AspNetCore.Mvc.Api.Analyzers.csproj", "{3B550487-10E4-4E6D-9CEF-B1B4CA1253DA}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -938,6 +940,18 @@ Global
|
||||||
{DD7B9F20-354C-4D9E-8C8A-8AE6E7595A87}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
{DD7B9F20-354C-4D9E-8C8A-8AE6E7595A87}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
{DD7B9F20-354C-4D9E-8C8A-8AE6E7595A87}.Release|x86.ActiveCfg = Release|Any CPU
|
{DD7B9F20-354C-4D9E-8C8A-8AE6E7595A87}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{DD7B9F20-354C-4D9E-8C8A-8AE6E7595A87}.Release|x86.Build.0 = Release|Any CPU
|
{DD7B9F20-354C-4D9E-8C8A-8AE6E7595A87}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{3B550487-10E4-4E6D-9CEF-B1B4CA1253DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3B550487-10E4-4E6D-9CEF-B1B4CA1253DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3B550487-10E4-4E6D-9CEF-B1B4CA1253DA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{3B550487-10E4-4E6D-9CEF-B1B4CA1253DA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{3B550487-10E4-4E6D-9CEF-B1B4CA1253DA}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{3B550487-10E4-4E6D-9CEF-B1B4CA1253DA}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{3B550487-10E4-4E6D-9CEF-B1B4CA1253DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3B550487-10E4-4E6D-9CEF-B1B4CA1253DA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{3B550487-10E4-4E6D-9CEF-B1B4CA1253DA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{3B550487-10E4-4E6D-9CEF-B1B4CA1253DA}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{3B550487-10E4-4E6D-9CEF-B1B4CA1253DA}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{3B550487-10E4-4E6D-9CEF-B1B4CA1253DA}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -1010,6 +1024,7 @@ Global
|
||||||
{910F023A-88E3-4CB4-8793-AC4005C7B421} = {2859F266-673A-45A2-9E3C-7B39C6DDD38E}
|
{910F023A-88E3-4CB4-8793-AC4005C7B421} = {2859F266-673A-45A2-9E3C-7B39C6DDD38E}
|
||||||
{E89EB74D-C1CE-456F-B42D-CCF1575E0CFB} = {2859F266-673A-45A2-9E3C-7B39C6DDD38E}
|
{E89EB74D-C1CE-456F-B42D-CCF1575E0CFB} = {2859F266-673A-45A2-9E3C-7B39C6DDD38E}
|
||||||
{DD7B9F20-354C-4D9E-8C8A-8AE6E7595A87} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
|
{DD7B9F20-354C-4D9E-8C8A-8AE6E7595A87} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
|
||||||
|
{3B550487-10E4-4E6D-9CEF-B1B4CA1253DA} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {63D344F6-F86D-40E6-85B9-0AABBE338C4A}
|
SolutionGuid = {63D344F6-F86D-40E6-85B9-0AABBE338C4A}
|
||||||
|
|
|
||||||
|
|
@ -171,38 +171,6 @@ namespace Microsoft.AspNetCore.Builder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IApplicationBuilder UseMvcWithEndpoint(
|
|
||||||
this IApplicationBuilder app,
|
|
||||||
Action<MvcEndpointInfoBuilder> configureRoutes)
|
|
||||||
{
|
|
||||||
if (app == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(app));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configureRoutes == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(configureRoutes));
|
|
||||||
}
|
|
||||||
|
|
||||||
VerifyMvcIsRegistered(app);
|
|
||||||
|
|
||||||
var mvcEndpointDataSource = app.ApplicationServices
|
|
||||||
.GetRequiredService<IEnumerable<EndpointDataSource>>()
|
|
||||||
.OfType<MvcEndpointDataSource>()
|
|
||||||
.First();
|
|
||||||
|
|
||||||
var constraintResolver = app.ApplicationServices.GetRequiredService<IInlineConstraintResolver>();
|
|
||||||
|
|
||||||
MvcEndpointInfoBuilder routeBuilder = new MvcEndpointInfoBuilder(constraintResolver);
|
|
||||||
|
|
||||||
configureRoutes(routeBuilder);
|
|
||||||
|
|
||||||
mvcEndpointDataSource.ConventionalEndpointInfos.AddRange(routeBuilder.EndpointInfos);
|
|
||||||
|
|
||||||
return app.UseEndpoint();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void VerifyMvcIsRegistered(IApplicationBuilder app)
|
private static void VerifyMvcIsRegistered(IApplicationBuilder app)
|
||||||
{
|
{
|
||||||
// Verify if AddMvc was done before calling UseMvc
|
// Verify if AddMvc was done before calling UseMvc
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ using Microsoft.AspNetCore.Routing.Template;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Builder
|
namespace Microsoft.AspNetCore.Builder
|
||||||
{
|
{
|
||||||
public class MvcEndpointInfo
|
internal class MvcEndpointInfo
|
||||||
{
|
{
|
||||||
public MvcEndpointInfo(
|
public MvcEndpointInfo(
|
||||||
string name,
|
string name,
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
// 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 Microsoft.AspNetCore.Routing;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Builder
|
|
||||||
{
|
|
||||||
public class MvcEndpointInfoBuilder
|
|
||||||
{
|
|
||||||
public MvcEndpointInfoBuilder(IInlineConstraintResolver constraintResolver)
|
|
||||||
{
|
|
||||||
ConstraintResolver = constraintResolver;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<MvcEndpointInfo> EndpointInfos { get; } = new List<MvcEndpointInfo>();
|
|
||||||
public IInlineConstraintResolver ConstraintResolver { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,229 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Core;
|
|
||||||
using Microsoft.AspNetCore.Routing;
|
|
||||||
using Microsoft.AspNetCore.Routing.Constraints;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Builder
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Provides extension methods for <see cref="MvcEndpointInfoBuilder" /> to add endpoints.
|
|
||||||
/// </summary>
|
|
||||||
public static class MvcEndpointInfoBuilderExtensions
|
|
||||||
{
|
|
||||||
#region MapEndpoint
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a endpoint to the <see cref="MvcEndpointInfoBuilder" /> with the specified name and template.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="endpointBuilder">The <see cref="MvcEndpointInfoBuilder" /> to add the endpoint to.</param>
|
|
||||||
/// <param name="name">The name of the endpoint.</param>
|
|
||||||
/// <param name="template">The URL pattern of the endpoint.</param>
|
|
||||||
/// <returns>A reference to this instance after the operation has completed.</returns>
|
|
||||||
public static MvcEndpointInfoBuilder MapEndpoint(this MvcEndpointInfoBuilder endpointBuilder, string name, string template)
|
|
||||||
{
|
|
||||||
endpointBuilder.MapEndpoint(name, template, null);
|
|
||||||
return endpointBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a endpoint to the <see cref="MvcEndpointInfoBuilder" /> with the specified name, template, and default values.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="endpointBuilder">The <see cref="MvcEndpointInfoBuilder" /> to add the endpoint to.</param>
|
|
||||||
/// <param name="name">The name of the endpoint.</param>
|
|
||||||
/// <param name="template">The URL pattern of the endpoint.</param>
|
|
||||||
/// <param name="defaults">
|
|
||||||
/// An object that contains default values for endpoint parameters. The object's properties represent the names
|
|
||||||
/// and values of the default values.
|
|
||||||
/// </param>
|
|
||||||
/// <returns>A reference to this instance after the operation has completed.</returns>
|
|
||||||
public static MvcEndpointInfoBuilder MapEndpoint(this MvcEndpointInfoBuilder endpointBuilder, string name, string template, object defaults)
|
|
||||||
{
|
|
||||||
return endpointBuilder.MapEndpoint(name, template, defaults, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a endpoint to the <see cref="MvcEndpointInfoBuilder" /> with the specified name, template, default values, and
|
|
||||||
/// constraints.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="endpointBuilder">The <see cref="MvcEndpointInfoBuilder" /> to add the endpoint to.</param>
|
|
||||||
/// <param name="name">The name of the endpoint.</param>
|
|
||||||
/// <param name="template">The URL pattern of the endpoint.</param>
|
|
||||||
/// <param name="defaults">
|
|
||||||
/// An object that contains default values for endpoint parameters. The object's properties represent the names
|
|
||||||
/// and values of the default values.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="constraints">
|
|
||||||
/// An object that contains constraints for the endpoint. The object's properties represent the names and values
|
|
||||||
/// of the constraints.
|
|
||||||
/// </param>
|
|
||||||
/// <returns>A reference to this instance after the operation has completed.</returns>
|
|
||||||
public static MvcEndpointInfoBuilder MapEndpoint(this MvcEndpointInfoBuilder endpointBuilder, string name, string template, object defaults, object constraints)
|
|
||||||
{
|
|
||||||
return endpointBuilder.MapEndpoint(name, template, defaults, constraints, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a endpoint to the <see cref="MvcEndpointInfoBuilder" /> with the specified name, template, default values, and
|
|
||||||
/// data tokens.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="endpointBuilder">The <see cref="MvcEndpointInfoBuilder" /> to add the endpoint to.</param>
|
|
||||||
/// <param name="name">The name of the endpoint.</param>
|
|
||||||
/// <param name="template">The URL pattern of the endpoint.</param>
|
|
||||||
/// <param name="defaults">
|
|
||||||
/// An object that contains default values for endpoint parameters. The object's properties represent the names
|
|
||||||
/// and values of the default values.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="constraints">
|
|
||||||
/// An object that contains constraints for the endpoint. The object's properties represent the names and values
|
|
||||||
/// of the constraints.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="dataTokens">
|
|
||||||
/// An object that contains data tokens for the endpoint. The object's properties represent the names and values
|
|
||||||
/// of the data tokens.
|
|
||||||
/// </param>
|
|
||||||
/// <returns>A reference to this instance after the operation has completed.</returns>
|
|
||||||
public static MvcEndpointInfoBuilder MapEndpoint(this MvcEndpointInfoBuilder endpointBuilder, string name, string template, object defaults, object constraints, object dataTokens)
|
|
||||||
{
|
|
||||||
endpointBuilder.EndpointInfos.Add(new MvcEndpointInfo(
|
|
||||||
name,
|
|
||||||
template,
|
|
||||||
new RouteValueDictionary(defaults),
|
|
||||||
new RouteValueDictionary(constraints),
|
|
||||||
new RouteValueDictionary(dataTokens),
|
|
||||||
endpointBuilder.ConstraintResolver));
|
|
||||||
|
|
||||||
return endpointBuilder;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region MapAreaEndpoint
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a endpoint to the <see cref="MvcEndpointInfoBuilder"/> with the given MVC area with the specified
|
|
||||||
/// <paramref name="name"/>, <paramref name="areaName"/> and <paramref name="template"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="endpointBuilder">The <see cref="MvcEndpointInfoBuilder"/> to add the endpoint to.</param>
|
|
||||||
/// <param name="name">The name of the endpoint.</param>
|
|
||||||
/// <param name="areaName">The MVC area name.</param>
|
|
||||||
/// <param name="template">The URL pattern of the endpoint.</param>
|
|
||||||
/// <returns>A reference to this instance after the operation has completed.</returns>
|
|
||||||
public static MvcEndpointInfoBuilder MapAreaEndpoint(
|
|
||||||
this MvcEndpointInfoBuilder endpointBuilder,
|
|
||||||
string name,
|
|
||||||
string areaName,
|
|
||||||
string template)
|
|
||||||
{
|
|
||||||
MapAreaEndpoint(endpointBuilder, name, areaName, template, defaults: null, constraints: null, dataTokens: null);
|
|
||||||
return endpointBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a endpoint to the <see cref="MvcEndpointInfoBuilder"/> with the given MVC area with the specified
|
|
||||||
/// <paramref name="name"/>, <paramref name="areaName"/>, <paramref name="template"/>, and
|
|
||||||
/// <paramref name="defaults"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="endpointBuilder">The <see cref="MvcEndpointInfoBuilder"/> to add the endpoint to.</param>
|
|
||||||
/// <param name="name">The name of the endpoint.</param>
|
|
||||||
/// <param name="areaName">The MVC area name.</param>
|
|
||||||
/// <param name="template">The URL pattern of the endpoint.</param>
|
|
||||||
/// <param name="defaults">
|
|
||||||
/// An object that contains default values for endpoint parameters. The object's properties represent the
|
|
||||||
/// names and values of the default values.
|
|
||||||
/// </param>
|
|
||||||
/// <returns>A reference to this instance after the operation has completed.</returns>
|
|
||||||
public static MvcEndpointInfoBuilder MapAreaEndpoint(
|
|
||||||
this MvcEndpointInfoBuilder endpointBuilder,
|
|
||||||
string name,
|
|
||||||
string areaName,
|
|
||||||
string template,
|
|
||||||
object defaults)
|
|
||||||
{
|
|
||||||
MapAreaEndpoint(endpointBuilder, name, areaName, template, defaults, constraints: null, dataTokens: null);
|
|
||||||
return endpointBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a endpoint to the <see cref="MvcEndpointInfoBuilder"/> with the given MVC area with the specified
|
|
||||||
/// <paramref name="name"/>, <paramref name="areaName"/>, <paramref name="template"/>,
|
|
||||||
/// <paramref name="defaults"/>, and <paramref name="constraints"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="endpointBuilder">The <see cref="MvcEndpointInfoBuilder"/> to add the endpoint to.</param>
|
|
||||||
/// <param name="name">The name of the endpoint.</param>
|
|
||||||
/// <param name="areaName">The MVC area name.</param>
|
|
||||||
/// <param name="template">The URL pattern of the endpoint.</param>
|
|
||||||
/// <param name="defaults">
|
|
||||||
/// An object that contains default values for endpoint parameters. The object's properties represent the
|
|
||||||
/// names and values of the default values.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="constraints">
|
|
||||||
/// An object that contains constraints for the endpoint. The object's properties represent the names and
|
|
||||||
/// values of the constraints.
|
|
||||||
/// </param>
|
|
||||||
/// <returns>A reference to this instance after the operation has completed.</returns>
|
|
||||||
public static MvcEndpointInfoBuilder MapAreaEndpoint(
|
|
||||||
this MvcEndpointInfoBuilder endpointBuilder,
|
|
||||||
string name,
|
|
||||||
string areaName,
|
|
||||||
string template,
|
|
||||||
object defaults,
|
|
||||||
object constraints)
|
|
||||||
{
|
|
||||||
MapAreaEndpoint(endpointBuilder, name, areaName, template, defaults, constraints, dataTokens: null);
|
|
||||||
return endpointBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a endpoint to the <see cref="MvcEndpointInfoBuilder"/> with the given MVC area with the specified
|
|
||||||
/// <paramref name="name"/>, <paramref name="areaName"/>, <paramref name="template"/>,
|
|
||||||
/// <paramref name="defaults"/>, <paramref name="constraints"/>, and <paramref name="dataTokens"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="endpointBuilder">The <see cref="MvcEndpointInfoBuilder"/> to add the endpoint to.</param>
|
|
||||||
/// <param name="name">The name of the endpoint.</param>
|
|
||||||
/// <param name="areaName">The MVC area name.</param>
|
|
||||||
/// <param name="template">The URL pattern of the endpoint.</param>
|
|
||||||
/// <param name="defaults">
|
|
||||||
/// An object that contains default values for endpoint parameters. The object's properties represent the
|
|
||||||
/// names and values of the default values.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="constraints">
|
|
||||||
/// An object that contains constraints for the endpoint. The object's properties represent the names and
|
|
||||||
/// values of the constraints.
|
|
||||||
/// </param>
|
|
||||||
/// <param name="dataTokens">
|
|
||||||
/// An object that contains data tokens for the endpoint. The object's properties represent the names and
|
|
||||||
/// values of the data tokens.
|
|
||||||
/// </param>
|
|
||||||
/// <returns>A reference to this instance after the operation has completed.</returns>
|
|
||||||
public static MvcEndpointInfoBuilder MapAreaEndpoint(
|
|
||||||
this MvcEndpointInfoBuilder endpointBuilder,
|
|
||||||
string name,
|
|
||||||
string areaName,
|
|
||||||
string template,
|
|
||||||
object defaults,
|
|
||||||
object constraints,
|
|
||||||
object dataTokens)
|
|
||||||
{
|
|
||||||
if (endpointBuilder == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(endpointBuilder));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(areaName))
|
|
||||||
{
|
|
||||||
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(areaName));
|
|
||||||
}
|
|
||||||
|
|
||||||
var defaultsDictionary = new RouteValueDictionary(defaults);
|
|
||||||
defaultsDictionary["area"] = defaultsDictionary["area"] ?? areaName;
|
|
||||||
|
|
||||||
var constraintsDictionary = new RouteValueDictionary(constraints);
|
|
||||||
constraintsDictionary["area"] = constraintsDictionary["area"] ?? new StringRouteConstraint(areaName);
|
|
||||||
|
|
||||||
endpointBuilder.MapEndpoint(name, template, defaultsDictionary, constraintsDictionary, dataTokens);
|
|
||||||
return endpointBuilder;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -442,7 +442,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// REVIEW: Infos added after endpoints are initialized will not be used
|
|
||||||
public List<MvcEndpointInfo> ConventionalEndpointInfos { get; }
|
public List<MvcEndpointInfo> ConventionalEndpointInfos { get; }
|
||||||
|
|
||||||
private class RouteNameMetadata : IRouteNameMetadata
|
private class RouteNameMetadata : IRouteNameMetadata
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
||||||
{
|
{
|
||||||
var descriptor = new PageActionDescriptor
|
var descriptor = new PageActionDescriptor
|
||||||
{
|
{
|
||||||
|
ActionConstraints = selector.ActionConstraints.ToList(),
|
||||||
|
AreaName = model.AreaName,
|
||||||
AttributeRouteInfo = new AttributeRouteInfo
|
AttributeRouteInfo = new AttributeRouteInfo
|
||||||
{
|
{
|
||||||
Name = selector.AttributeRouteModel.Name,
|
Name = selector.AttributeRouteModel.Name,
|
||||||
|
|
@ -84,11 +86,11 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
||||||
SuppressPathMatching = selector.AttributeRouteModel.SuppressPathMatching,
|
SuppressPathMatching = selector.AttributeRouteModel.SuppressPathMatching,
|
||||||
},
|
},
|
||||||
DisplayName = $"Page: {model.ViewEnginePath}",
|
DisplayName = $"Page: {model.ViewEnginePath}",
|
||||||
|
EndpointMetadata = selector.EndpointMetadata.ToList(),
|
||||||
FilterDescriptors = Array.Empty<FilterDescriptor>(),
|
FilterDescriptors = Array.Empty<FilterDescriptor>(),
|
||||||
Properties = new Dictionary<object, object>(model.Properties),
|
Properties = new Dictionary<object, object>(model.Properties),
|
||||||
RelativePath = model.RelativePath,
|
RelativePath = model.RelativePath,
|
||||||
ViewEnginePath = model.ViewEnginePath,
|
ViewEnginePath = model.ViewEnginePath,
|
||||||
AreaName = model.AreaName,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var kvp in model.RouteValues)
|
foreach (var kvp in model.RouteValues)
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
||||||
ActionConstraints = actionDescriptor.ActionConstraints,
|
ActionConstraints = actionDescriptor.ActionConstraints,
|
||||||
AttributeRouteInfo = actionDescriptor.AttributeRouteInfo,
|
AttributeRouteInfo = actionDescriptor.AttributeRouteInfo,
|
||||||
BoundProperties = boundProperties,
|
BoundProperties = boundProperties,
|
||||||
|
EndpointMetadata = actionDescriptor.EndpointMetadata,
|
||||||
FilterDescriptors = filters,
|
FilterDescriptors = filters,
|
||||||
HandlerMethods = handlerMethods,
|
HandlerMethods = handlerMethods,
|
||||||
HandlerTypeInfo = applicationModel.HandlerType,
|
HandlerTypeInfo = applicationModel.HandlerType,
|
||||||
|
|
|
||||||
|
|
@ -37,26 +37,6 @@ namespace Microsoft.AspNetCore.Mvc.Core.Builder
|
||||||
exception.Message);
|
exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void UseMvcWithEndpoint_ThrowsInvalidOperationException_IfMvcMarkerServiceIsNotRegistered()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var applicationBuilderMock = new Mock<IApplicationBuilder>();
|
|
||||||
applicationBuilderMock
|
|
||||||
.Setup(s => s.ApplicationServices)
|
|
||||||
.Returns(Mock.Of<IServiceProvider>());
|
|
||||||
|
|
||||||
// Act & Assert
|
|
||||||
var exception = Assert.Throws<InvalidOperationException>(
|
|
||||||
() => applicationBuilderMock.Object.UseMvcWithEndpoint(rb => { }));
|
|
||||||
|
|
||||||
Assert.Equal(
|
|
||||||
"Unable to find the required services. Please add all the required services by calling " +
|
|
||||||
"'IServiceCollection.AddMvc' inside the call to 'ConfigureServices(...)' " +
|
|
||||||
"in the application startup code.",
|
|
||||||
exception.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void UseMvc_EndpointRoutingDisabled_NoEndpointInfos()
|
public void UseMvc_EndpointRoutingDisabled_NoEndpointInfos()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,282 +0,0 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Routing;
|
|
||||||
using Microsoft.AspNetCore.Routing.Constraints;
|
|
||||||
using Moq;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Mvc.Core.Test.Builder
|
|
||||||
{
|
|
||||||
public class MvcEndpointInfoBuilderExtensionsTest
|
|
||||||
{
|
|
||||||
#region MapAreaEndpoint
|
|
||||||
[Fact]
|
|
||||||
public void MapAreaEndpoint_Simple()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var builder = CreateEndpointBuilder();
|
|
||||||
|
|
||||||
// Act
|
|
||||||
builder.MapAreaEndpoint(name: null, areaName: "admin", template: "site/Admin/");
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
var endpointInfo = Assert.Single(builder.EndpointInfos);
|
|
||||||
|
|
||||||
Assert.Null(endpointInfo.Name);
|
|
||||||
Assert.Equal("site/Admin/", endpointInfo.Template);
|
|
||||||
Assert.Collection(
|
|
||||||
endpointInfo.Constraints.OrderBy(kvp => kvp.Key),
|
|
||||||
kvp =>
|
|
||||||
{
|
|
||||||
Assert.Equal("area", kvp.Key);
|
|
||||||
Assert.IsType<StringRouteConstraint>(kvp.Value);
|
|
||||||
});
|
|
||||||
Assert.Empty(endpointInfo.DataTokens);
|
|
||||||
Assert.Collection(
|
|
||||||
endpointInfo.Defaults.OrderBy(kvp => kvp.Key),
|
|
||||||
kvp =>
|
|
||||||
{
|
|
||||||
Assert.Equal("area", kvp.Key);
|
|
||||||
Assert.Equal("admin", kvp.Value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void MapAreaEndpoint_Defaults()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var builder = CreateEndpointBuilder();
|
|
||||||
|
|
||||||
// Act
|
|
||||||
builder.MapAreaEndpoint(
|
|
||||||
name: "admin_area",
|
|
||||||
areaName: "admin",
|
|
||||||
template: "site/Admin/",
|
|
||||||
defaults: new { action = "Home" });
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
var endpointInfo = Assert.Single(builder.EndpointInfos);
|
|
||||||
|
|
||||||
Assert.Equal("admin_area", endpointInfo.Name);
|
|
||||||
Assert.Equal("site/Admin/", endpointInfo.Template);
|
|
||||||
Assert.Collection(
|
|
||||||
endpointInfo.Constraints.OrderBy(kvp => kvp.Key),
|
|
||||||
kvp =>
|
|
||||||
{
|
|
||||||
Assert.Equal("area", kvp.Key);
|
|
||||||
Assert.IsType<StringRouteConstraint>(kvp.Value);
|
|
||||||
});
|
|
||||||
Assert.Empty(endpointInfo.DataTokens);
|
|
||||||
Assert.Collection(
|
|
||||||
endpointInfo.Defaults.OrderBy(kvp => kvp.Key),
|
|
||||||
kvp =>
|
|
||||||
{
|
|
||||||
Assert.Equal("action", kvp.Key);
|
|
||||||
Assert.Equal("Home", kvp.Value);
|
|
||||||
},
|
|
||||||
kvp =>
|
|
||||||
{
|
|
||||||
Assert.Equal("area", kvp.Key);
|
|
||||||
Assert.Equal("admin", kvp.Value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void MapAreaEndpoint_DefaultsAndConstraints()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var builder = CreateEndpointBuilder();
|
|
||||||
|
|
||||||
// Act
|
|
||||||
builder.MapAreaEndpoint(
|
|
||||||
name: "admin_area",
|
|
||||||
areaName: "admin",
|
|
||||||
template: "site/Admin/",
|
|
||||||
defaults: new { action = "Home" },
|
|
||||||
constraints: new { id = new IntRouteConstraint() });
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
var endpointInfo = Assert.Single(builder.EndpointInfos);
|
|
||||||
|
|
||||||
Assert.Equal("admin_area", endpointInfo.Name);
|
|
||||||
Assert.Equal("site/Admin/", endpointInfo.Template);
|
|
||||||
Assert.Collection(
|
|
||||||
endpointInfo.Constraints.OrderBy(kvp => kvp.Key),
|
|
||||||
kvp =>
|
|
||||||
{
|
|
||||||
Assert.Equal("area", kvp.Key);
|
|
||||||
Assert.IsType<StringRouteConstraint>(kvp.Value);
|
|
||||||
},
|
|
||||||
kvp =>
|
|
||||||
{
|
|
||||||
Assert.Equal("id", kvp.Key);
|
|
||||||
Assert.IsType<IntRouteConstraint>(kvp.Value);
|
|
||||||
});
|
|
||||||
Assert.Empty(endpointInfo.DataTokens);
|
|
||||||
Assert.Collection(
|
|
||||||
endpointInfo.Defaults.OrderBy(kvp => kvp.Key),
|
|
||||||
kvp =>
|
|
||||||
{
|
|
||||||
Assert.Equal("action", kvp.Key);
|
|
||||||
Assert.Equal("Home", kvp.Value);
|
|
||||||
},
|
|
||||||
kvp =>
|
|
||||||
{
|
|
||||||
Assert.Equal("area", kvp.Key);
|
|
||||||
Assert.Equal("admin", kvp.Value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void MapAreaEndpoint_DefaultsConstraintsAndDataTokens()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var builder = CreateEndpointBuilder();
|
|
||||||
|
|
||||||
// Act
|
|
||||||
builder.MapAreaEndpoint(
|
|
||||||
name: "admin_area",
|
|
||||||
areaName: "admin",
|
|
||||||
template: "site/Admin/",
|
|
||||||
defaults: new { action = "Home" },
|
|
||||||
constraints: new { id = new IntRouteConstraint() },
|
|
||||||
dataTokens: new { some_token = "hello" });
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
var endpointInfo = Assert.Single(builder.EndpointInfos);
|
|
||||||
|
|
||||||
Assert.Equal("admin_area", endpointInfo.Name);
|
|
||||||
Assert.Equal("site/Admin/", endpointInfo.Template);
|
|
||||||
Assert.Collection(
|
|
||||||
endpointInfo.Constraints.OrderBy(kvp => kvp.Key),
|
|
||||||
kvp =>
|
|
||||||
{
|
|
||||||
Assert.Equal("area", kvp.Key);
|
|
||||||
Assert.IsType<StringRouteConstraint>(kvp.Value);
|
|
||||||
},
|
|
||||||
kvp =>
|
|
||||||
{
|
|
||||||
Assert.Equal("id", kvp.Key);
|
|
||||||
Assert.IsType<IntRouteConstraint>(kvp.Value);
|
|
||||||
});
|
|
||||||
Assert.Collection(
|
|
||||||
endpointInfo.DataTokens.OrderBy(kvp => kvp.Key),
|
|
||||||
kvp =>
|
|
||||||
{
|
|
||||||
Assert.Equal("some_token", kvp.Key);
|
|
||||||
Assert.Equal("hello", kvp.Value);
|
|
||||||
});
|
|
||||||
Assert.Collection(
|
|
||||||
endpointInfo.Defaults.OrderBy(kvp => kvp.Key),
|
|
||||||
kvp =>
|
|
||||||
{
|
|
||||||
Assert.Equal("action", kvp.Key);
|
|
||||||
Assert.Equal("Home", kvp.Value);
|
|
||||||
},
|
|
||||||
kvp =>
|
|
||||||
{
|
|
||||||
Assert.Equal("area", kvp.Key);
|
|
||||||
Assert.Equal("admin", kvp.Value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void MapAreaEndpoint_DoesNotReplaceValuesForAreaIfAlreadyPresentInConstraintsOrDefaults()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var builder = CreateEndpointBuilder();
|
|
||||||
|
|
||||||
// Act
|
|
||||||
builder.MapAreaEndpoint(
|
|
||||||
name: "admin_area",
|
|
||||||
areaName: "admin",
|
|
||||||
template: "site/Admin/",
|
|
||||||
defaults: new { area = "Home" },
|
|
||||||
constraints: new { area = new IntRouteConstraint() },
|
|
||||||
dataTokens: new { some_token = "hello" });
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
var endpointInfo = Assert.Single(builder.EndpointInfos);
|
|
||||||
|
|
||||||
Assert.Equal("admin_area", endpointInfo.Name);
|
|
||||||
Assert.Equal("site/Admin/", endpointInfo.Template);
|
|
||||||
Assert.Collection(
|
|
||||||
endpointInfo.Constraints.OrderBy(kvp => kvp.Key),
|
|
||||||
kvp =>
|
|
||||||
{
|
|
||||||
Assert.Equal("area", kvp.Key);
|
|
||||||
Assert.IsType<IntRouteConstraint>(kvp.Value);
|
|
||||||
});
|
|
||||||
Assert.Collection(
|
|
||||||
endpointInfo.DataTokens.OrderBy(kvp => kvp.Key),
|
|
||||||
kvp =>
|
|
||||||
{
|
|
||||||
Assert.Equal("some_token", kvp.Key);
|
|
||||||
Assert.Equal("hello", kvp.Value);
|
|
||||||
});
|
|
||||||
Assert.Collection(
|
|
||||||
endpointInfo.Defaults.OrderBy(kvp => kvp.Key),
|
|
||||||
kvp =>
|
|
||||||
{
|
|
||||||
Assert.Equal("area", kvp.Key);
|
|
||||||
Assert.Equal("Home", kvp.Value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void MapAreaEndpoint_UsesPassedInAreaNameAsIs()
|
|
||||||
{
|
|
||||||
// Arrange
|
|
||||||
var builder = CreateEndpointBuilder();
|
|
||||||
var areaName = "user.admin";
|
|
||||||
|
|
||||||
// Act
|
|
||||||
builder.MapAreaEndpoint(name: null, areaName: areaName, template: "site/Admin/");
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
var endpointInfo = Assert.Single(builder.EndpointInfos);
|
|
||||||
|
|
||||||
Assert.Null(endpointInfo.Name);
|
|
||||||
Assert.Equal("site/Admin/", endpointInfo.Template);
|
|
||||||
Assert.Collection(
|
|
||||||
endpointInfo.Constraints.OrderBy(kvp => kvp.Key),
|
|
||||||
kvp =>
|
|
||||||
{
|
|
||||||
Assert.Equal("area", kvp.Key);
|
|
||||||
Assert.IsType<StringRouteConstraint>(kvp.Value);
|
|
||||||
|
|
||||||
var values = new RouteValueDictionary(new { area = areaName });
|
|
||||||
var match = kvp.Value.Match(
|
|
||||||
new DefaultHttpContext(),
|
|
||||||
route: new Mock<IRouter>().Object,
|
|
||||||
routeKey: kvp.Key,
|
|
||||||
values: values,
|
|
||||||
routeDirection: RouteDirection.UrlGeneration);
|
|
||||||
|
|
||||||
Assert.True(match);
|
|
||||||
});
|
|
||||||
Assert.Empty(endpointInfo.DataTokens);
|
|
||||||
Assert.Collection(
|
|
||||||
endpointInfo.Defaults.OrderBy(kvp => kvp.Key),
|
|
||||||
kvp =>
|
|
||||||
{
|
|
||||||
Assert.Equal("area", kvp.Key);
|
|
||||||
Assert.Equal(kvp.Value, areaName);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private MvcEndpointInfoBuilder CreateEndpointBuilder()
|
|
||||||
{
|
|
||||||
var builder = new MvcEndpointInfoBuilder(Mock.Of<IInlineConstraintResolver>());
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||||
|
using Microsoft.AspNetCore.Mvc.ActionConstraints;
|
||||||
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
|
@ -167,6 +168,74 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
||||||
Assert.Equal("Accounts/Test/{id:int?}", descriptor.AttributeRouteInfo.Template);
|
Assert.Equal("Accounts/Test/{id:int?}", descriptor.AttributeRouteInfo.Template);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetDescriptors_CopiesActionConstraintsFromModel()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expected = Mock.Of<IActionConstraint>();
|
||||||
|
var model = new PageRouteModel("/Areas/Accounts/Pages/Test.cshtml", "/Test", "Accounts")
|
||||||
|
{
|
||||||
|
Selectors =
|
||||||
|
{
|
||||||
|
new SelectorModel
|
||||||
|
{
|
||||||
|
AttributeRouteModel = new AttributeRouteModel(),
|
||||||
|
ActionConstraints = { expected }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var applicationModelProvider = new TestPageRouteModelProvider(model);
|
||||||
|
var provider = new PageActionDescriptorProvider(
|
||||||
|
new[] { applicationModelProvider },
|
||||||
|
GetAccessor<MvcOptions>(),
|
||||||
|
GetRazorPagesOptions());
|
||||||
|
var context = new ActionDescriptorProviderContext();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
provider.OnProvidersExecuting(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var result = Assert.Single(context.Results);
|
||||||
|
var descriptor = Assert.IsType<PageActionDescriptor>(result);
|
||||||
|
Assert.Equal(model.RelativePath, descriptor.RelativePath);
|
||||||
|
var actual = Assert.Single(descriptor.ActionConstraints);
|
||||||
|
Assert.Same(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GetDescriptors_CopiesEndPointMetadataFromModel()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expected = new object();
|
||||||
|
var model = new PageRouteModel("/Test.cshtml", "/Test", "Accounts")
|
||||||
|
{
|
||||||
|
Selectors =
|
||||||
|
{
|
||||||
|
new SelectorModel
|
||||||
|
{
|
||||||
|
AttributeRouteModel = new AttributeRouteModel(),
|
||||||
|
EndpointMetadata = { expected }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var applicationModelProvider = new TestPageRouteModelProvider(model);
|
||||||
|
var provider = new PageActionDescriptorProvider(
|
||||||
|
new[] { applicationModelProvider },
|
||||||
|
GetAccessor<MvcOptions>(),
|
||||||
|
GetRazorPagesOptions());
|
||||||
|
var context = new ActionDescriptorProviderContext();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
provider.OnProvidersExecuting(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var result = Assert.Single(context.Results);
|
||||||
|
var descriptor = Assert.IsType<PageActionDescriptor>(result);
|
||||||
|
Assert.Equal(model.RelativePath, descriptor.RelativePath);
|
||||||
|
var actual = Assert.Single(descriptor.EndpointMetadata);
|
||||||
|
Assert.Same(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetDescriptors_AddsActionDescriptorForEachSelector()
|
public void GetDescriptors_AddsActionDescriptorForEachSelector()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
||||||
{
|
{
|
||||||
ActionConstraints = new List<IActionConstraintMetadata>(),
|
ActionConstraints = new List<IActionConstraintMetadata>(),
|
||||||
AttributeRouteInfo = new AttributeRouteInfo(),
|
AttributeRouteInfo = new AttributeRouteInfo(),
|
||||||
|
EndpointMetadata = new List<object>(),
|
||||||
FilterDescriptors = new List<FilterDescriptor>(),
|
FilterDescriptors = new List<FilterDescriptor>(),
|
||||||
RelativePath = "/Foo",
|
RelativePath = "/Foo",
|
||||||
RouteValues = new Dictionary<string, string>(),
|
RouteValues = new Dictionary<string, string>(),
|
||||||
|
|
@ -40,6 +41,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Same(actionDescriptor.ActionConstraints, actual.ActionConstraints);
|
Assert.Same(actionDescriptor.ActionConstraints, actual.ActionConstraints);
|
||||||
Assert.Same(actionDescriptor.AttributeRouteInfo, actual.AttributeRouteInfo);
|
Assert.Same(actionDescriptor.AttributeRouteInfo, actual.AttributeRouteInfo);
|
||||||
|
Assert.Same(actionDescriptor.EndpointMetadata, actual.EndpointMetadata);
|
||||||
Assert.Same(actionDescriptor.RelativePath, actual.RelativePath);
|
Assert.Same(actionDescriptor.RelativePath, actual.RelativePath);
|
||||||
Assert.Same(actionDescriptor.RouteValues, actual.RouteValues);
|
Assert.Same(actionDescriptor.RouteValues, actual.RouteValues);
|
||||||
Assert.Same(actionDescriptor.ViewEnginePath, actual.ViewEnginePath);
|
Assert.Same(actionDescriptor.ViewEnginePath, actual.ViewEnginePath);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue