parent
083f55e337
commit
39f1f5c933
|
|
@ -92,8 +92,6 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
internal static void AddServices(IServiceCollection services)
|
||||
{
|
||||
// Options
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IConfigureOptions<RazorPagesOptions>, RazorPagesOptionsSetup>());
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IConfigureOptions<RazorViewEngineOptions>, RazorPagesRazorViewEngineOptionsSetup>());
|
||||
|
||||
|
|
@ -105,6 +103,8 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
ServiceDescriptor.Singleton<IPageApplicationModelProvider, RazorProjectPageApplicationModelProvider>());
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Singleton<IPageApplicationModelProvider, CompiledPageApplicationModelProvider>());
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Singleton<IPageApplicationModelProvider, PageFilterApplicationModelProvider>());
|
||||
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Singleton<IActionInvokerProvider, PageActionInvokerProvider>());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
// 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 Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
||||
{
|
||||
public class PageFilterApplicationModelProvider : IPageApplicationModelProvider
|
||||
{
|
||||
/// <remarks>This order ensures that <see cref="PageFilterApplicationModelProvider"/> runs after
|
||||
/// <see cref="RazorProjectPageApplicationModelProvider"/> and <see cref="CompiledPageApplicationModelProvider"/>.
|
||||
/// </remarks>
|
||||
public int Order => -1000 + 10;
|
||||
|
||||
public void OnProvidersExecuted(PageApplicationModelProviderContext context)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public void OnProvidersExecuting(PageApplicationModelProviderContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
for (var i = 0; i < context.Results.Count; i++)
|
||||
{
|
||||
var pageApplicationModel = context.Results[i];
|
||||
|
||||
// Support for [TempData] on properties
|
||||
pageApplicationModel.Filters.Add(new PageSaveTempDataPropertyFilterFactory());
|
||||
|
||||
// Always require an antiforgery token on post
|
||||
pageApplicationModel.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +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 Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
||||
{
|
||||
public class RazorPagesOptionsSetup : IConfigureOptions<RazorPagesOptions>
|
||||
{
|
||||
public void Configure(RazorPagesOptions options)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
// Support for [TempData] on properties
|
||||
options.ConfigureFilter(page => new PageSaveTempDataPropertyFilterFactory());
|
||||
|
||||
// Always require an antiforgery token on post
|
||||
options.ConfigureFilter(new AutoValidateAntiforgeryTokenAttribute());
|
||||
|
||||
options.RootDirectory = "/Pages";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
/// </summary>
|
||||
public class RazorPagesOptions
|
||||
{
|
||||
private string _root = "/";
|
||||
private string _root = "/Pages";
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="IPageApplicationModelConvention"/> instances that will be applied to
|
||||
|
|
@ -22,6 +22,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
|
||||
/// <summary>
|
||||
/// Application relative path used as the root of discovery for Razor Page files.
|
||||
/// Defaults to the <c>/Pages</c> directory under application root.
|
||||
/// </summary>
|
||||
public string RootDirectory
|
||||
{
|
||||
|
|
|
|||
|
|
@ -186,8 +186,9 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
|||
// Arrange
|
||||
var options = new MvcOptions();
|
||||
var applicationModelProvider = new TestPageApplicationModelProvider(CreateModel());
|
||||
var filterProvider = new PageFilterApplicationModelProvider();
|
||||
var provider = new PageActionDescriptorProvider(
|
||||
new[] { applicationModelProvider },
|
||||
new IPageApplicationModelProvider[] { applicationModelProvider, filterProvider },
|
||||
GetAccessor(options),
|
||||
GetRazorPagesOptions());
|
||||
var context = new ActionDescriptorProviderContext();
|
||||
|
|
@ -222,8 +223,9 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
|||
options.Filters.Add(filter1);
|
||||
options.Filters.Add(filter2);
|
||||
var applicationModelProvider = new TestPageApplicationModelProvider(CreateModel());
|
||||
var filterProvider = new PageFilterApplicationModelProvider();
|
||||
var provider = new PageActionDescriptorProvider(
|
||||
new[] { applicationModelProvider },
|
||||
new IPageApplicationModelProvider[] { applicationModelProvider, filterProvider },
|
||||
GetAccessor(options),
|
||||
GetRazorPagesOptions());
|
||||
var context = new ActionDescriptorProviderContext();
|
||||
|
|
@ -275,8 +277,9 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
|||
var razorOptions = GetRazorPagesOptions();
|
||||
razorOptions.Value.Conventions.Add(convention.Object);
|
||||
var applicationModelProvider = new TestPageApplicationModelProvider(CreateModel());
|
||||
var filterProvider = new PageFilterApplicationModelProvider();
|
||||
var provider = new PageActionDescriptorProvider(
|
||||
new[] { applicationModelProvider },
|
||||
new IPageApplicationModelProvider[] { applicationModelProvider, filterProvider },
|
||||
GetAccessor(options),
|
||||
razorOptions);
|
||||
var context = new ActionDescriptorProviderContext();
|
||||
|
|
@ -337,7 +340,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
|||
|
||||
private static IOptions<RazorPagesOptions> GetRazorPagesOptions()
|
||||
{
|
||||
return new OptionsManager<RazorPagesOptions>(new[] { new RazorPagesOptionsSetup() });
|
||||
return new TestOptionsManager<RazorPagesOptions>();
|
||||
}
|
||||
|
||||
private static RazorProjectItem GetProjectItem(string basePath, string path, string content)
|
||||
|
|
@ -359,7 +362,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
|||
_models = models ?? Array.Empty<PageApplicationModel>();
|
||||
}
|
||||
|
||||
public int Order => 0;
|
||||
public int Order => -1000;
|
||||
|
||||
public void OnProvidersExecuted(PageApplicationModelProviderContext context)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -31,16 +31,51 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
result =>
|
||||
{
|
||||
Assert.Equal("/Pages/About.cshtml", result.RelativePath);
|
||||
Assert.Equal("/Pages/About", result.ViewEnginePath);
|
||||
Assert.Equal("/About", result.ViewEnginePath);
|
||||
Assert.Collection(result.Selectors,
|
||||
selector => Assert.Equal("Pages/About", selector.AttributeRouteModel.Template));
|
||||
selector => Assert.Equal("About", selector.AttributeRouteModel.Template));
|
||||
},
|
||||
result =>
|
||||
{
|
||||
Assert.Equal("/Pages/Home.cshtml", result.RelativePath);
|
||||
Assert.Equal("/Pages/Home", result.ViewEnginePath);
|
||||
Assert.Equal("/Home", result.ViewEnginePath);
|
||||
Assert.Collection(result.Selectors,
|
||||
selector => Assert.Equal("Pages/Home/some-prefix", selector.AttributeRouteModel.Template));
|
||||
selector => Assert.Equal("Home/some-prefix", selector.AttributeRouteModel.Template));
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OnProvidersExecuting_AddsMultipleSelectorsForIndexPage_WithIndexAtRoot()
|
||||
{
|
||||
// Arrange
|
||||
var info = new[]
|
||||
{
|
||||
new CompiledPageInfo("/Pages/Index.cshtml", typeof(object), routePrefix: string.Empty),
|
||||
new CompiledPageInfo("/Pages/Admin/Index.cshtml", typeof(object), "some-template"),
|
||||
};
|
||||
var provider = new TestCompiledPageApplicationModelProvider(info, new RazorPagesOptions { RootDirectory = "/" });
|
||||
var context = new PageApplicationModelProviderContext();
|
||||
|
||||
// Act
|
||||
provider.OnProvidersExecuting(context);
|
||||
|
||||
// Assert
|
||||
Assert.Collection(context.Results,
|
||||
result =>
|
||||
{
|
||||
Assert.Equal("/Pages/Index.cshtml", result.RelativePath);
|
||||
Assert.Equal("/Pages/Index", result.ViewEnginePath);
|
||||
Assert.Collection(result.Selectors,
|
||||
selector => Assert.Equal("Pages/Index", selector.AttributeRouteModel.Template),
|
||||
selector => Assert.Equal("Pages", selector.AttributeRouteModel.Template));
|
||||
},
|
||||
result =>
|
||||
{
|
||||
Assert.Equal("/Pages/Admin/Index.cshtml", result.RelativePath);
|
||||
Assert.Equal("/Pages/Admin/Index", result.ViewEnginePath);
|
||||
Assert.Collection(result.Selectors,
|
||||
selector => Assert.Equal("Pages/Admin/Index/some-template", selector.AttributeRouteModel.Template),
|
||||
selector => Assert.Equal("Pages/Admin/some-template", selector.AttributeRouteModel.Template));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -64,18 +99,18 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
result =>
|
||||
{
|
||||
Assert.Equal("/Pages/Index.cshtml", result.RelativePath);
|
||||
Assert.Equal("/Pages/Index", result.ViewEnginePath);
|
||||
Assert.Equal("/Index", result.ViewEnginePath);
|
||||
Assert.Collection(result.Selectors,
|
||||
selector => Assert.Equal("Pages/Index", selector.AttributeRouteModel.Template),
|
||||
selector => Assert.Equal("Pages", selector.AttributeRouteModel.Template));
|
||||
selector => Assert.Equal("Index", selector.AttributeRouteModel.Template),
|
||||
selector => Assert.Equal("", selector.AttributeRouteModel.Template));
|
||||
},
|
||||
result =>
|
||||
{
|
||||
Assert.Equal("/Pages/Admin/Index.cshtml", result.RelativePath);
|
||||
Assert.Equal("/Pages/Admin/Index", result.ViewEnginePath);
|
||||
Assert.Equal("/Admin/Index", result.ViewEnginePath);
|
||||
Assert.Collection(result.Selectors,
|
||||
selector => Assert.Equal("Pages/Admin/Index/some-template", selector.AttributeRouteModel.Template),
|
||||
selector => Assert.Equal("Pages/Admin/some-template", selector.AttributeRouteModel.Template));
|
||||
selector => Assert.Equal("Admin/Index/some-template", selector.AttributeRouteModel.Template),
|
||||
selector => Assert.Equal("Admin/some-template", selector.AttributeRouteModel.Template));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
var changeToken = changeProvider.GetChangeToken();
|
||||
|
||||
// Assert
|
||||
fileProvider.Verify(f => f.Watch("/**/*.cshtml"));
|
||||
fileProvider.Verify(f => f.Watch("/Pages/**/*.cshtml"));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
|
|||
|
|
@ -182,7 +182,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
loader.Object,
|
||||
CreateActionDescriptorCollection(descriptor),
|
||||
razorPageFactoryProvider: razorPageFactoryProvider.Object,
|
||||
razorProject: defaultRazorProject);
|
||||
razorProject: defaultRazorProject,
|
||||
razorPagesOptions: new RazorPagesOptions { RootDirectory = "/" });
|
||||
|
||||
var context = new ActionInvokerProviderContext(new ActionContext()
|
||||
{
|
||||
|
|
@ -346,7 +347,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
pageProvider: null,
|
||||
modelProvider: null,
|
||||
razorPageFactoryProvider: razorPageFactoryProvider,
|
||||
razorProject: razorProject);
|
||||
razorProject: razorProject,
|
||||
razorPagesOptions: new RazorPagesOptions { RootDirectory = "/" });
|
||||
|
||||
var compiledDescriptor = CreateCompiledPageActionDescriptor(descriptor);
|
||||
|
||||
|
|
@ -458,7 +460,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
|||
pageProvider: null,
|
||||
modelProvider: null,
|
||||
razorPageFactoryProvider: pageFactory.Object,
|
||||
razorProject: razorProject);
|
||||
razorProject: razorProject,
|
||||
razorPagesOptions: new RazorPagesOptions { RootDirectory = "/" });
|
||||
|
||||
var compiledDescriptor = CreateCompiledPageActionDescriptor(descriptor);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
// 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.ApplicationModels;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
||||
{
|
||||
public class PageFilterApplicationModelProviderTest
|
||||
{
|
||||
[Fact]
|
||||
public void OnProvidersExecuting_AddsFiltersToModels()
|
||||
{
|
||||
// Arrange
|
||||
var applicationModel1 = new PageApplicationModel("/Home.cshtml", "/Home.cshtml");
|
||||
var applicationModel2 = new PageApplicationModel("/About.cshtml", "/About.cshtml");
|
||||
var modelProvider = new PageFilterApplicationModelProvider();
|
||||
var context = new PageApplicationModelProviderContext
|
||||
{
|
||||
Results =
|
||||
{
|
||||
applicationModel1,
|
||||
applicationModel2,
|
||||
}
|
||||
};
|
||||
|
||||
// Act
|
||||
modelProvider.OnProvidersExecuting(context);
|
||||
|
||||
// Assert
|
||||
Assert.Collection(applicationModel1.Filters,
|
||||
filter => Assert.IsType<PageSaveTempDataPropertyFilterFactory>(filter),
|
||||
filter => Assert.IsType<AutoValidateAntiforgeryTokenAttribute>(filter));
|
||||
|
||||
Assert.Collection(applicationModel2.Filters,
|
||||
filter => Assert.IsType<PageSaveTempDataPropertyFilterFactory>(filter),
|
||||
filter => Assert.IsType<AutoValidateAntiforgeryTokenAttribute>(filter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +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 Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
|
||||
{
|
||||
public class RazorPagesOptionsSetupTest
|
||||
{
|
||||
[Fact]
|
||||
public void Configure_AddsGlobalFilters()
|
||||
{
|
||||
// Arrange
|
||||
var options = new RazorPagesOptions();
|
||||
var setup = new RazorPagesOptionsSetup();
|
||||
var applicationModel = new PageApplicationModel("/Home.cshtml", "/Home.cshtml");
|
||||
|
||||
// Act
|
||||
setup.Configure(options);
|
||||
foreach (var convention in options.Conventions)
|
||||
{
|
||||
convention.Apply(applicationModel);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.Collection(applicationModel.Filters,
|
||||
filter => Assert.IsType<PageSaveTempDataPropertyFilterFactory>(filter),
|
||||
filter => Assert.IsType<AutoValidateAntiforgeryTokenAttribute>(filter));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Configure_SetsRazorPagesRoot()
|
||||
{
|
||||
// Arrange
|
||||
var options = new RazorPagesOptions();
|
||||
var setup = new RazorPagesOptionsSetup();
|
||||
|
||||
// Act
|
||||
setup.Configure(options);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("/Pages", options.RootDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -364,13 +364,6 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
typeof(RazorPagesRazorViewEngineOptionsSetup),
|
||||
}
|
||||
},
|
||||
{
|
||||
typeof(IConfigureOptions<RazorPagesOptions>),
|
||||
new[]
|
||||
{
|
||||
typeof(RazorPagesOptionsSetup),
|
||||
}
|
||||
},
|
||||
{
|
||||
typeof(IActionConstraintProvider),
|
||||
new Type[]
|
||||
|
|
@ -433,6 +426,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
{
|
||||
typeof(CompiledPageApplicationModelProvider),
|
||||
typeof(RazorProjectPageApplicationModelProvider),
|
||||
typeof(PageFilterApplicationModelProvider),
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue