diff --git a/.gitignore b/.gitignore index e38f0aa101..d5d42e3255 100644 --- a/.gitignore +++ b/.gitignore @@ -37,7 +37,6 @@ node_modules *launchSettings.json *.orig .vscode/ -global.json BenchmarkDotNet.Artifacts/ .idea/ msbuild.binlog diff --git a/NuGet.config b/NuGet.config index e32bddfd51..cec9479a72 100644 --- a/NuGet.config +++ b/NuGet.config @@ -2,6 +2,11 @@ - + + diff --git a/build/dependencies.props b/build/dependencies.props index 31522a7de6..f0f745d122 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -17,7 +17,6 @@ 2.1.1.1 2.1.1 3.0.0-alpha1-10549 - 3.0.0-alpha1-20180919.1 3.0.0-alpha1-10549 3.0.0-alpha1-10549 3.0.0-alpha1-10549 diff --git a/global.json b/global.json new file mode 100644 index 0000000000..b5a5299b58 --- /dev/null +++ b/global.json @@ -0,0 +1,8 @@ +{ + "sdk": { + "version": "2.2.100-preview2-009404" + }, + "msbuild-sdks": { + "Internal.AspNetCore.Sdk": "2.2.0-preview2-20181003.2" + } +} diff --git a/korebuild-lock.txt b/korebuild-lock.txt index d66a13bdc7..f01f6571b0 100644 --- a/korebuild-lock.txt +++ b/korebuild-lock.txt @@ -1,2 +1,2 @@ -version:3.0.0-alpha1-20180919.1 -commithash:3066ae0a230870ea07e3f132605b5e5493f8bbd4 +version:3.0.0-alpha1-20181004.5 +commithash:8725f7194e9976f75f90f56afc0fba6116ac597c diff --git a/src/Directory.Build.props b/src/Directory.Build.props index ab4e538839..a111c45919 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -2,7 +2,6 @@ - diff --git a/src/Microsoft.AspNetCore.Mvc.Abstractions/Microsoft.AspNetCore.Mvc.Abstractions.csproj b/src/Microsoft.AspNetCore.Mvc.Abstractions/Microsoft.AspNetCore.Mvc.Abstractions.csproj index bea1675a90..34f0f5e6a1 100644 --- a/src/Microsoft.AspNetCore.Mvc.Abstractions/Microsoft.AspNetCore.Mvc.Abstractions.csproj +++ b/src/Microsoft.AspNetCore.Mvc.Abstractions/Microsoft.AspNetCore.Mvc.Abstractions.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core MVC abstractions and interfaces for action invocation and dispatching, authorization, action filters, formatters, model binding, routing, validation, and more. diff --git a/src/Microsoft.AspNetCore.Mvc.Analyzers/Microsoft.AspNetCore.Mvc.Analyzers.csproj b/src/Microsoft.AspNetCore.Mvc.Analyzers/Microsoft.AspNetCore.Mvc.Analyzers.csproj index 3030951867..7e796c0673 100644 --- a/src/Microsoft.AspNetCore.Mvc.Analyzers/Microsoft.AspNetCore.Mvc.Analyzers.csproj +++ b/src/Microsoft.AspNetCore.Mvc.Analyzers/Microsoft.AspNetCore.Mvc.Analyzers.csproj @@ -1,4 +1,4 @@ - + CSharp Analyzers for ASP.NET Core MVC. aspnetcore;aspnetcoremvc diff --git a/src/Microsoft.AspNetCore.Mvc.Api.Analyzers/Microsoft.AspNetCore.Mvc.Api.Analyzers.csproj b/src/Microsoft.AspNetCore.Mvc.Api.Analyzers/Microsoft.AspNetCore.Mvc.Api.Analyzers.csproj index 50b645a854..97ec69ad41 100644 --- a/src/Microsoft.AspNetCore.Mvc.Api.Analyzers/Microsoft.AspNetCore.Mvc.Api.Analyzers.csproj +++ b/src/Microsoft.AspNetCore.Mvc.Api.Analyzers/Microsoft.AspNetCore.Mvc.Api.Analyzers.csproj @@ -1,4 +1,4 @@ - + CSharp Analyzers for ASP.NET Core MVC. aspnetcore;aspnetcoremvc diff --git a/src/Microsoft.AspNetCore.Mvc.ApiExplorer/Microsoft.AspNetCore.Mvc.ApiExplorer.csproj b/src/Microsoft.AspNetCore.Mvc.ApiExplorer/Microsoft.AspNetCore.Mvc.ApiExplorer.csproj index 5ccb12bef4..308a2f225b 100644 --- a/src/Microsoft.AspNetCore.Mvc.ApiExplorer/Microsoft.AspNetCore.Mvc.ApiExplorer.csproj +++ b/src/Microsoft.AspNetCore.Mvc.ApiExplorer/Microsoft.AspNetCore.Mvc.ApiExplorer.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core MVC API explorer functionality for discovering metadata such as the list of controllers and actions, and their URLs and allowed HTTP methods. diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Microsoft.AspNetCore.Mvc.Core.csproj b/src/Microsoft.AspNetCore.Mvc.Core/Microsoft.AspNetCore.Mvc.Core.csproj index 0698b3fd85..7a21b34e45 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Microsoft.AspNetCore.Mvc.Core.csproj +++ b/src/Microsoft.AspNetCore.Mvc.Core/Microsoft.AspNetCore.Mvc.Core.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core MVC core components. Contains common action result types, attribute routing, application model conventions, API explorer, application parts, filters, formatters, model binding, and more. diff --git a/src/Microsoft.AspNetCore.Mvc.Cors/Microsoft.AspNetCore.Mvc.Cors.csproj b/src/Microsoft.AspNetCore.Mvc.Cors/Microsoft.AspNetCore.Mvc.Cors.csproj index f6056e62e5..379eca0738 100644 --- a/src/Microsoft.AspNetCore.Mvc.Cors/Microsoft.AspNetCore.Mvc.Cors.csproj +++ b/src/Microsoft.AspNetCore.Mvc.Cors/Microsoft.AspNetCore.Mvc.Cors.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core MVC cross-origin resource sharing (CORS) features. diff --git a/src/Microsoft.AspNetCore.Mvc.DataAnnotations/Microsoft.AspNetCore.Mvc.DataAnnotations.csproj b/src/Microsoft.AspNetCore.Mvc.DataAnnotations/Microsoft.AspNetCore.Mvc.DataAnnotations.csproj index 776a31be2d..33df42b291 100644 --- a/src/Microsoft.AspNetCore.Mvc.DataAnnotations/Microsoft.AspNetCore.Mvc.DataAnnotations.csproj +++ b/src/Microsoft.AspNetCore.Mvc.DataAnnotations/Microsoft.AspNetCore.Mvc.DataAnnotations.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core MVC metadata and validation system using System.ComponentModel.DataAnnotations. diff --git a/src/Microsoft.AspNetCore.Mvc.Formatters.Json/Microsoft.AspNetCore.Mvc.Formatters.Json.csproj b/src/Microsoft.AspNetCore.Mvc.Formatters.Json/Microsoft.AspNetCore.Mvc.Formatters.Json.csproj index 608e370257..45749b70ec 100644 --- a/src/Microsoft.AspNetCore.Mvc.Formatters.Json/Microsoft.AspNetCore.Mvc.Formatters.Json.csproj +++ b/src/Microsoft.AspNetCore.Mvc.Formatters.Json/Microsoft.AspNetCore.Mvc.Formatters.Json.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core MVC formatters for JSON input and output and for JSON PATCH input using Json.NET. diff --git a/src/Microsoft.AspNetCore.Mvc.Formatters.Xml/Microsoft.AspNetCore.Mvc.Formatters.Xml.csproj b/src/Microsoft.AspNetCore.Mvc.Formatters.Xml/Microsoft.AspNetCore.Mvc.Formatters.Xml.csproj index 6458ed6838..18dcb55e3a 100644 --- a/src/Microsoft.AspNetCore.Mvc.Formatters.Xml/Microsoft.AspNetCore.Mvc.Formatters.Xml.csproj +++ b/src/Microsoft.AspNetCore.Mvc.Formatters.Xml/Microsoft.AspNetCore.Mvc.Formatters.Xml.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core MVC formatters for XML input and output using DataContractSerializer and XmlSerializer. diff --git a/src/Microsoft.AspNetCore.Mvc.Localization/Microsoft.AspNetCore.Mvc.Localization.csproj b/src/Microsoft.AspNetCore.Mvc.Localization/Microsoft.AspNetCore.Mvc.Localization.csproj index 2105530c41..a20bb199aa 100644 --- a/src/Microsoft.AspNetCore.Mvc.Localization/Microsoft.AspNetCore.Mvc.Localization.csproj +++ b/src/Microsoft.AspNetCore.Mvc.Localization/Microsoft.AspNetCore.Mvc.Localization.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core MVC features that enable globalization and localization of applications. diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Microsoft.AspNetCore.Mvc.Razor.csproj b/src/Microsoft.AspNetCore.Mvc.Razor/Microsoft.AspNetCore.Mvc.Razor.csproj index b63e6156e9..4bef4f811f 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor/Microsoft.AspNetCore.Mvc.Razor.csproj +++ b/src/Microsoft.AspNetCore.Mvc.Razor/Microsoft.AspNetCore.Mvc.Razor.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core MVC Razor view engine for CSHTML files. diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/DefaultPageApplicationModelProvider.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/DefaultPageApplicationModelProvider.cs similarity index 92% rename from src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/DefaultPageApplicationModelProvider.cs rename to src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/DefaultPageApplicationModelProvider.cs index cc6a02af02..b486d40e8c 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/DefaultPageApplicationModelProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/DefaultPageApplicationModelProvider.cs @@ -3,36 +3,43 @@ using System; using System.Reflection; -using Microsoft.AspNetCore.Mvc.ApplicationModels; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.Razor; +using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure; +using Microsoft.AspNetCore.Mvc.RazorPages.Internal; using Microsoft.Extensions.Internal; using Microsoft.Extensions.Options; +using Resources = Microsoft.AspNetCore.Mvc.RazorPages.Resources; -namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal +namespace Microsoft.AspNetCore.Mvc.ApplicationModels { - public class DefaultPageApplicationModelProvider : IPageApplicationModelProvider + internal class DefaultPageApplicationModelProvider : IPageApplicationModelProvider { private const string ModelPropertyName = "Model"; private readonly PageHandlerPageFilter _pageHandlerPageFilter = new PageHandlerPageFilter(); private readonly PageHandlerResultFilter _pageHandlerResultFilter = new PageHandlerResultFilter(); private readonly IModelMetadataProvider _modelMetadataProvider; - private readonly MvcOptions _options; + private readonly MvcOptions _mvcOptions; + private readonly RazorPagesOptions _razorPagesOptions; private readonly Func _supportsAllRequests; private readonly Func _supportsNonGetRequests; - + private readonly HandleOptionsRequestsPageFilter _handleOptionsRequestsFilter; public DefaultPageApplicationModelProvider( IModelMetadataProvider modelMetadataProvider, - IOptions options) + IOptions options, + IOptions razorPagesOptions) { _modelMetadataProvider = modelMetadataProvider; - _options = options.Value; + _mvcOptions = options.Value; + _razorPagesOptions = razorPagesOptions.Value; _supportsAllRequests = _ => true; - _supportsNonGetRequests = context => !string.Equals(context.HttpContext.Request.Method, "GET", StringComparison.OrdinalIgnoreCase); + _supportsNonGetRequests = context => !HttpMethods.IsGet(context.HttpContext.Request.Method); + _handleOptionsRequestsFilter = new HandleOptionsRequestsPageFilter(); } /// @@ -175,6 +182,11 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal { pageModel.Filters.Add(_pageHandlerResultFilter); } + + if (_razorPagesOptions.AllowDefaultHandlingForOptionsRequests) + { + pageModel.Filters.Add(_handleOptionsRequestsFilter); + } } /// @@ -237,7 +249,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal var attributes = parameter.GetCustomAttributes(inherit: true); BindingInfo bindingInfo; - if (_options.AllowValidatingTopLevelNodes && _modelMetadataProvider is ModelMetadataProvider modelMetadataProviderBase) + if (_mvcOptions.AllowValidatingTopLevelNodes && _modelMetadataProvider is ModelMetadataProvider modelMetadataProviderBase) { var modelMetadata = modelMetadataProviderBase.GetMetadataForParameter(parameter); bindingInfo = BindingInfo.GetBindingInfo(attributes, modelMetadata); diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/HandleOptionsRequestsPageFilter.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/HandleOptionsRequestsPageFilter.cs new file mode 100644 index 0000000000..0c9221e507 --- /dev/null +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/HandleOptionsRequestsPageFilter.cs @@ -0,0 +1,55 @@ +// 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.Http; +using Microsoft.AspNetCore.Mvc.Filters; + +namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure +{ + /// + /// A filter that handles OPTIONS requests page when no handler method is available. + /// + /// a) MVC treats no handler being selected no differently than a page having no handler, both execute the + /// page. + /// b) A common model for programming Razor Pages is to initialize content required by a page in the + /// OnGet handler. Executing a page without running the handler may result in runtime exceptions - + /// e.g. null ref or out of bounds exception if you expected a property or collection to be initialized. + /// + /// + /// Some web crawlers use OPTIONS request when probing servers. In the absence of an uncommon OnOptions + /// handler, executing the page will likely result in runtime errors as described in earlier. This filter + /// attempts to avoid this pit of failure by handling OPTIONS requests and returning a 200 if no handler is selected. + /// + /// + internal sealed class HandleOptionsRequestsPageFilter : IPageFilter, IOrderedFilter + { + /// + /// Ordered to run after filters with default order. + /// + public int Order => 1000; + + public void OnPageHandlerExecuted(PageHandlerExecutedContext context) + { + } + + public void OnPageHandlerExecuting(PageHandlerExecutingContext context) + { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (context.HandlerMethod == null && + context.Result == null && + HttpMethods.IsOptions(context.HttpContext.Request.Method)) + { + context.Result = new OkResult(); + } + } + + public void OnPageHandlerSelected(PageHandlerSelectedContext context) + { + } + } +} diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Microsoft.AspNetCore.Mvc.RazorPages.csproj b/src/Microsoft.AspNetCore.Mvc.RazorPages/Microsoft.AspNetCore.Mvc.RazorPages.csproj index ff5c61f35b..1655f9da77 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Microsoft.AspNetCore.Mvc.RazorPages.csproj +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/Microsoft.AspNetCore.Mvc.RazorPages.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core MVC Razor Pages. diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/RazorPagesOptions.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/RazorPagesOptions.cs index b3b0b15e11..38bd6f7988 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/RazorPagesOptions.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/RazorPagesOptions.cs @@ -16,6 +16,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages { private readonly CompatibilitySwitch _allowAreas; private readonly CompatibilitySwitch _allowMappingHeadRequestsToGetHandler; + private readonly CompatibilitySwitch _allowsDefaultHandlingForOptionsRequests; private readonly ICompatibilitySwitch[] _switches; private string _root = "/Pages"; @@ -24,11 +25,13 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages { _allowAreas = new CompatibilitySwitch(nameof(AllowAreas)); _allowMappingHeadRequestsToGetHandler = new CompatibilitySwitch(nameof(AllowMappingHeadRequestsToGetHandler)); + _allowsDefaultHandlingForOptionsRequests = new CompatibilitySwitch(nameof(AllowDefaultHandlingForOptionsRequests)); _switches = new ICompatibilitySwitch[] { _allowAreas, _allowMappingHeadRequestsToGetHandler, + _allowsDefaultHandlingForOptionsRequests, }; } @@ -134,6 +137,45 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages set => _allowMappingHeadRequestsToGetHandler.Value = value; } + /// + /// Gets or sets a value that determines if HTTP requests with the OPTIONS method are handled by default, if + /// no handler is available. + /// + /// + /// The default value is if the version is + /// or later; otherwise. + /// + /// + /// + /// Razor Pages uses the current request's HTTP method to select a handler method. When no handler is available or selected, + /// the page is immediately executed. This may cause runtime errors if the page relies on the handler method to execute + /// and initialize some state. This setting attempts to avoid this class of error for HTTP OPTIONS requests by + /// returning a 200 OK response. + /// + /// + /// This property is associated with a compatibility switch and can provide a different behavior depending on + /// the configured compatibility version for the application. See for + /// guidance and examples of setting the application's compatibility version. + /// + /// + /// Configuring the desired of the value compatibility switch by calling this property's setter will take precedence + /// over the value implied by the application's . + /// + /// + /// If the application's compatibility version is set to then + /// this setting will have value true unless explicitly configured. + /// + /// + /// If the application's compatibility version is set to or + /// lower then this setting will have value true unless explicitly configured. + /// + /// + public bool AllowDefaultHandlingForOptionsRequests + { + get => _allowsDefaultHandlingForOptionsRequests.Value; + set => _allowsDefaultHandlingForOptionsRequests.Value = value; + } + IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_switches).GetEnumerator(); diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/RazorPagesOptionsConfigureCompatibilityOptions.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/RazorPagesOptionsConfigureCompatibilityOptions.cs index 8f5d21d8bc..49596d55b2 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/RazorPagesOptionsConfigureCompatibilityOptions.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/RazorPagesOptionsConfigureCompatibilityOptions.cs @@ -29,6 +29,11 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages values[nameof(RazorPagesOptions.AllowMappingHeadRequestsToGetHandler)] = true; } + if (Version >= CompatibilityVersion.Version_2_2) + { + values[nameof(RazorPagesOptions.AllowDefaultHandlingForOptionsRequests)] = true; + } + return values; } } diff --git a/src/Microsoft.AspNetCore.Mvc.TagHelpers/Microsoft.AspNetCore.Mvc.TagHelpers.csproj b/src/Microsoft.AspNetCore.Mvc.TagHelpers/Microsoft.AspNetCore.Mvc.TagHelpers.csproj index 23fce08ef7..5bd518d2f0 100644 --- a/src/Microsoft.AspNetCore.Mvc.TagHelpers/Microsoft.AspNetCore.Mvc.TagHelpers.csproj +++ b/src/Microsoft.AspNetCore.Mvc.TagHelpers/Microsoft.AspNetCore.Mvc.TagHelpers.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core MVC default tag helpers. Contains tag helpers for anchor tags, HTML input elements, caching, scripts, links (for CSS), and more. diff --git a/src/Microsoft.AspNetCore.Mvc.Testing/Microsoft.AspNetCore.Mvc.Testing.csproj b/src/Microsoft.AspNetCore.Mvc.Testing/Microsoft.AspNetCore.Mvc.Testing.csproj index cf0a443e19..058ec2af63 100644 --- a/src/Microsoft.AspNetCore.Mvc.Testing/Microsoft.AspNetCore.Mvc.Testing.csproj +++ b/src/Microsoft.AspNetCore.Mvc.Testing/Microsoft.AspNetCore.Mvc.Testing.csproj @@ -1,4 +1,4 @@ - + Support for writing functional tests for MVC applications. diff --git a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Microsoft.AspNetCore.Mvc.ViewFeatures.csproj b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Microsoft.AspNetCore.Mvc.ViewFeatures.csproj index 79ef166f49..878ac41bd4 100644 --- a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Microsoft.AspNetCore.Mvc.ViewFeatures.csproj +++ b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Microsoft.AspNetCore.Mvc.ViewFeatures.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core MVC view rendering features. Contains common types used in most MVC applications as well as view rendering features such as view engines, views, view components, and HTML helpers. diff --git a/src/Microsoft.AspNetCore.Mvc.WebApiCompatShim/Microsoft.AspNetCore.Mvc.WebApiCompatShim.csproj b/src/Microsoft.AspNetCore.Mvc.WebApiCompatShim/Microsoft.AspNetCore.Mvc.WebApiCompatShim.csproj index ab1d11a599..72cb71f8c2 100644 --- a/src/Microsoft.AspNetCore.Mvc.WebApiCompatShim/Microsoft.AspNetCore.Mvc.WebApiCompatShim.csproj +++ b/src/Microsoft.AspNetCore.Mvc.WebApiCompatShim/Microsoft.AspNetCore.Mvc.WebApiCompatShim.csproj @@ -1,4 +1,4 @@ - + Provides compatibility in ASP.NET Core MVC with ASP.NET Web API 2 to simplify migration of existing Web API implementations. diff --git a/src/Microsoft.AspNetCore.Mvc/Microsoft.AspNetCore.Mvc.csproj b/src/Microsoft.AspNetCore.Mvc/Microsoft.AspNetCore.Mvc.csproj index 9e57ee217c..9b21543c20 100644 --- a/src/Microsoft.AspNetCore.Mvc/Microsoft.AspNetCore.Mvc.csproj +++ b/src/Microsoft.AspNetCore.Mvc/Microsoft.AspNetCore.Mvc.csproj @@ -1,4 +1,4 @@ - + ASP.NET Core MVC is a web framework that gives you a powerful, patterns-based way to build dynamic websites and web APIs. ASP.NET Core MVC enables a clean separation of concerns and gives you full control over markup. diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 96765456ba..ff13641a43 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -14,7 +14,6 @@ - diff --git a/test/Microsoft.AspNetCore.Mvc.Abstractions.Test/Microsoft.AspNetCore.Mvc.Abstractions.Test.csproj b/test/Microsoft.AspNetCore.Mvc.Abstractions.Test/Microsoft.AspNetCore.Mvc.Abstractions.Test.csproj index 210346c189..a02016bd2e 100644 --- a/test/Microsoft.AspNetCore.Mvc.Abstractions.Test/Microsoft.AspNetCore.Mvc.Abstractions.Test.csproj +++ b/test/Microsoft.AspNetCore.Mvc.Abstractions.Test/Microsoft.AspNetCore.Mvc.Abstractions.Test.csproj @@ -1,4 +1,4 @@ - + $(StandardTestTfms) diff --git a/test/Microsoft.AspNetCore.Mvc.ApiExplorer.Test/Microsoft.AspNetCore.Mvc.ApiExplorer.Test.csproj b/test/Microsoft.AspNetCore.Mvc.ApiExplorer.Test/Microsoft.AspNetCore.Mvc.ApiExplorer.Test.csproj index 3debef1228..b1ca115faa 100644 --- a/test/Microsoft.AspNetCore.Mvc.ApiExplorer.Test/Microsoft.AspNetCore.Mvc.ApiExplorer.Test.csproj +++ b/test/Microsoft.AspNetCore.Mvc.ApiExplorer.Test/Microsoft.AspNetCore.Mvc.ApiExplorer.Test.csproj @@ -1,4 +1,4 @@ - + $(StandardTestTfms) diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Microsoft.AspNetCore.Mvc.Core.Test.csproj b/test/Microsoft.AspNetCore.Mvc.Core.Test/Microsoft.AspNetCore.Mvc.Core.Test.csproj index aef0c4c3c4..f030903427 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Microsoft.AspNetCore.Mvc.Core.Test.csproj +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Microsoft.AspNetCore.Mvc.Core.Test.csproj @@ -1,4 +1,4 @@ - + $(StandardTestTfms) diff --git a/test/Microsoft.AspNetCore.Mvc.Core.TestCommon/Microsoft.AspNetCore.Mvc.Core.TestCommon.csproj b/test/Microsoft.AspNetCore.Mvc.Core.TestCommon/Microsoft.AspNetCore.Mvc.Core.TestCommon.csproj index 44d8da1323..053be86a52 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.TestCommon/Microsoft.AspNetCore.Mvc.Core.TestCommon.csproj +++ b/test/Microsoft.AspNetCore.Mvc.Core.TestCommon/Microsoft.AspNetCore.Mvc.Core.TestCommon.csproj @@ -1,4 +1,4 @@ - + $(StandardTestTfms) diff --git a/test/Microsoft.AspNetCore.Mvc.Cors.Test/Microsoft.AspNetCore.Mvc.Cors.Test.csproj b/test/Microsoft.AspNetCore.Mvc.Cors.Test/Microsoft.AspNetCore.Mvc.Cors.Test.csproj index 684e4dfcef..59269389e9 100644 --- a/test/Microsoft.AspNetCore.Mvc.Cors.Test/Microsoft.AspNetCore.Mvc.Cors.Test.csproj +++ b/test/Microsoft.AspNetCore.Mvc.Cors.Test/Microsoft.AspNetCore.Mvc.Cors.Test.csproj @@ -1,4 +1,4 @@ - + $(StandardTestTfms) diff --git a/test/Microsoft.AspNetCore.Mvc.DataAnnotations.Test/Microsoft.AspNetCore.Mvc.DataAnnotations.Test.csproj b/test/Microsoft.AspNetCore.Mvc.DataAnnotations.Test/Microsoft.AspNetCore.Mvc.DataAnnotations.Test.csproj index b6673fbd95..14f4f05b2f 100644 --- a/test/Microsoft.AspNetCore.Mvc.DataAnnotations.Test/Microsoft.AspNetCore.Mvc.DataAnnotations.Test.csproj +++ b/test/Microsoft.AspNetCore.Mvc.DataAnnotations.Test/Microsoft.AspNetCore.Mvc.DataAnnotations.Test.csproj @@ -1,4 +1,4 @@ - + $(StandardTestTfms) diff --git a/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test.csproj b/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test.csproj index 4b93e7b0a3..6536b2ef40 100644 --- a/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test.csproj +++ b/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test.csproj @@ -1,4 +1,4 @@ - + $(StandardTestTfms) diff --git a/test/Microsoft.AspNetCore.Mvc.Formatters.Xml.Test/Microsoft.AspNetCore.Mvc.Formatters.Xml.Test.csproj b/test/Microsoft.AspNetCore.Mvc.Formatters.Xml.Test/Microsoft.AspNetCore.Mvc.Formatters.Xml.Test.csproj index b6673fbd95..14f4f05b2f 100644 --- a/test/Microsoft.AspNetCore.Mvc.Formatters.Xml.Test/Microsoft.AspNetCore.Mvc.Formatters.Xml.Test.csproj +++ b/test/Microsoft.AspNetCore.Mvc.Formatters.Xml.Test/Microsoft.AspNetCore.Mvc.Formatters.Xml.Test.csproj @@ -1,4 +1,4 @@ - + $(StandardTestTfms) diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/Microsoft.AspNetCore.Mvc.FunctionalTests.csproj b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/Microsoft.AspNetCore.Mvc.FunctionalTests.csproj index 3573b91863..d93286ee67 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/Microsoft.AspNetCore.Mvc.FunctionalTests.csproj +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/Microsoft.AspNetCore.Mvc.FunctionalTests.csproj @@ -1,4 +1,4 @@ - + diff --git a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesTest.cs b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesTest.cs index 8aca9a9bcf..ab9c81bfad 100644 --- a/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.FunctionalTests/RazorPagesTest.cs @@ -1431,6 +1431,54 @@ Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary`1[AspNetCore.InjectedPa Assert.Equal("ViewData: Bar", content); } + [Fact] + public async Task OptionsRequest_WithoutHandler_Returns200_WithoutExecutingPage() + { + // Arrange + var request = new HttpRequestMessage(HttpMethod.Options, "http://localhost/HelloWorld"); + + // Act + var response = await Client.SendAsync(request); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + var content = await response.Content.ReadAsStringAsync(); + Assert.Empty(content.Trim()); + } + + [Fact] + public async Task PageWithOptionsHandler_ExecutesGetRequest() + { + // Arrange + var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/HelloWorldWithOptionsHandler"); + + // Act + var response = await Client.SendAsync(request); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + var content = await response.Content.ReadAsStringAsync(); + Assert.Equal("Hello from OnGet!", content.Trim()); + } + + [Fact] + public async Task PageWithOptionsHandler_ExecutesOptionsRequest() + { + // Arrange + var request = new HttpRequestMessage(HttpMethod.Options, "http://localhost/HelloWorldWithOptionsHandler"); + + // Act + var response = await Client.SendAsync(request); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + var content = await response.Content.ReadAsStringAsync(); + Assert.Equal("Hello from OnOptions!", content.Trim()); + } + private async Task AddAntiforgeryHeaders(HttpRequestMessage request) { var getResponse = await Client.GetAsync(request.RequestUri); diff --git a/test/Microsoft.AspNetCore.Mvc.IntegrationTests/Microsoft.AspNetCore.Mvc.IntegrationTests.csproj b/test/Microsoft.AspNetCore.Mvc.IntegrationTests/Microsoft.AspNetCore.Mvc.IntegrationTests.csproj index 875d606d3e..be6dd3242f 100644 --- a/test/Microsoft.AspNetCore.Mvc.IntegrationTests/Microsoft.AspNetCore.Mvc.IntegrationTests.csproj +++ b/test/Microsoft.AspNetCore.Mvc.IntegrationTests/Microsoft.AspNetCore.Mvc.IntegrationTests.csproj @@ -1,4 +1,4 @@ - + $(StandardTestTfms) diff --git a/test/Microsoft.AspNetCore.Mvc.Localization.Test/Microsoft.AspNetCore.Mvc.Localization.Test.csproj b/test/Microsoft.AspNetCore.Mvc.Localization.Test/Microsoft.AspNetCore.Mvc.Localization.Test.csproj index faf5a9a84a..28b41219a9 100644 --- a/test/Microsoft.AspNetCore.Mvc.Localization.Test/Microsoft.AspNetCore.Mvc.Localization.Test.csproj +++ b/test/Microsoft.AspNetCore.Mvc.Localization.Test/Microsoft.AspNetCore.Mvc.Localization.Test.csproj @@ -1,4 +1,4 @@ - + $(StandardTestTfms) diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Microsoft.AspNetCore.Mvc.Razor.Test.csproj b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Microsoft.AspNetCore.Mvc.Razor.Test.csproj index 2cee7fa108..4e4f07c50f 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Microsoft.AspNetCore.Mvc.Razor.Test.csproj +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Microsoft.AspNetCore.Mvc.Razor.Test.csproj @@ -1,4 +1,4 @@ - + $(StandardTestTfms) diff --git a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/DefaultPageApplicationModelProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/ApplicationModels/DefaultPageApplicationModelProviderTest.cs similarity index 95% rename from test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/DefaultPageApplicationModelProviderTest.cs rename to test/Microsoft.AspNetCore.Mvc.RazorPages.Test/ApplicationModels/DefaultPageApplicationModelProviderTest.cs index 2ad90a08a8..7661f32707 100644 --- a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/DefaultPageApplicationModelProviderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/ApplicationModels/DefaultPageApplicationModelProviderTest.cs @@ -6,15 +6,16 @@ using System.Linq; using System.Reflection; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc.ApplicationModels; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.Razor; +using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure; +using Microsoft.AspNetCore.Mvc.RazorPages.Internal; using Microsoft.Extensions.Options; using Xunit; -namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal +namespace Microsoft.AspNetCore.Mvc.ApplicationModels { public class DefaultPageApplicationModelProviderTest { @@ -887,7 +888,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal // Arrange var provider = new DefaultPageApplicationModelProvider( TestModelMetadataProvider.CreateDefaultProvider(), - Options.Create(new MvcOptions { AllowValidatingTopLevelNodes = false })); + Options.Create(new MvcOptions { AllowValidatingTopLevelNodes = false }), + Options.Create(new RazorPagesOptions())); var typeInfo = typeof(PageWithHandlerParameters).GetTypeInfo(); var expected = typeInfo.GetMethod(nameof(PageWithHandlerParameters.OnPost)); var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, new object[0]); @@ -921,11 +923,11 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal public void OnPost(string name, [ModelBinder(Name = "personId")] int id) { } } - // We're using PropertyHelper from Common to find the properties here, which implements + // We're using PropertyHelper from Common to find the properties here, which implements // out standard set of semantics for properties that the framework interacts with. - // - // One of the desirable consequences of that is we only find 'visible' properties. We're not - // retesting all of the details of PropertyHelper here, just the visibility part as a quick check + // + // One of the desirable consequences of that is we only find 'visible' properties. We're not + // retesting all of the details of PropertyHelper here, just the visibility part as a quick check // that we're using PropertyHelper as expected. [Fact] public void PopulateHandlerProperties_UsesPropertyHelpers_ToFindProperties() @@ -1071,6 +1073,41 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal public void OnGetUser() { } } + [Fact] + public void PopulateFilters_With21CompatBehavior_DoesNotAddDisallowOptionsRequestsPageFilter() + { + // Arrange + var provider = new DefaultPageApplicationModelProvider( + TestModelMetadataProvider.CreateDefaultProvider(), + Options.Create(new MvcOptions()), + Options.Create(new RazorPagesOptions())); + var typeInfo = typeof(object).GetTypeInfo(); + var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, typeInfo.GetCustomAttributes(inherit: true)); + + // Act + provider.PopulateFilters(pageModel); + + // Assert + Assert.Empty(pageModel.Filters); + } + + [Fact] + public void PopulateFilters_AddsDisallowOptionsRequestsPageFilter() + { + // Arrange + var provider = CreateProvider(); + var typeInfo = typeof(object).GetTypeInfo(); + var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, typeInfo.GetCustomAttributes(inherit: true)); + + // Act + provider.PopulateFilters(pageModel); + + // Assert + Assert.Collection( + pageModel.Filters, + filter => Assert.IsType(filter)); + } + [Fact] public void PopulateFilters_AddsIFilterMetadataAttributesToModel() { @@ -1085,7 +1122,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal // Assert Assert.Collection( pageModel.Filters, - filter => Assert.IsType(filter)); + filter => Assert.IsType(filter), + filter => Assert.IsType(filter)); } [PageModel] @@ -1109,7 +1147,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal // Assert Assert.Collection( pageModel.Filters, - filter => Assert.IsType(filter)); + filter => Assert.IsType(filter), + filter => Assert.IsType(filter)); } private class ModelImplementingAsyncPageFilter : IAsyncPageFilter @@ -1139,7 +1178,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal // Assert Assert.Collection( pageModel.Filters, - filter => Assert.IsType(filter)); + filter => Assert.IsType(filter), + filter => Assert.IsType(filter)); } private class ModelImplementingPageFilter : IPageFilter @@ -1175,7 +1215,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal Assert.Collection( pageModel.Filters, filter => Assert.IsType(filter), - filter => Assert.IsType(filter)); + filter => Assert.IsType(filter), + filter => Assert.IsType(filter)); } [ServiceFilter(typeof(IServiceProvider))] @@ -1185,7 +1226,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal { return new DefaultPageApplicationModelProvider( TestModelMetadataProvider.CreateDefaultProvider(), - Options.Create(new MvcOptions { AllowValidatingTopLevelNodes = true })); + Options.Create(new MvcOptions { AllowValidatingTopLevelNodes = true }), + Options.Create(new RazorPagesOptions { AllowDefaultHandlingForOptionsRequests = true })); } } } diff --git a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Infrastructure/DisallowOptionsRequestsPageFilterTest.cs b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Infrastructure/DisallowOptionsRequestsPageFilterTest.cs new file mode 100644 index 0000000000..a2be81c8c1 --- /dev/null +++ b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Infrastructure/DisallowOptionsRequestsPageFilterTest.cs @@ -0,0 +1,135 @@ +// 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.Http; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.AspNetCore.Routing; +using Xunit; + +namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure +{ + public class DisallowOptionsRequestsPageFilterTest + { + [Fact] + public void OnPageHandlerExecuting_DoesNothing_IfHandlerIsSelected() + { + // Arrange + var context = GetContext(new HandlerMethodDescriptor()); + var filter = new HandleOptionsRequestsPageFilter(); + + // Act + filter.OnPageHandlerExecuting(context); + + // Assert + Assert.Null(context.Result); + } + + [Fact] + public void OnPageHandlerExecuting_DoesNotOverwriteResult_IfHandlerIsSelected() + { + // Arrange + var expected = new PageResult(); + var context = GetContext(new HandlerMethodDescriptor()); + context.Result = expected; + var filter = new HandleOptionsRequestsPageFilter(); + + // Act + filter.OnPageHandlerExecuting(context); + + // Assert + Assert.Same(expected, context.Result); + } + + [Fact] + public void OnPageHandlerExecuting_DoesNothing_IfHandlerIsNotSelected_WhenRequestsIsNotOptions() + { + // Arrange + var context = GetContext(handlerMethodDescriptor: null); + context.HttpContext.Request.Method = "PUT"; + var filter = new HandleOptionsRequestsPageFilter(); + + // Act + filter.OnPageHandlerExecuting(context); + + // Assert + Assert.Null(context.Result); + } + + [Fact] + public void OnPageHandlerExecuting_DoesNotOverwriteResult_IfHandlerIsNotSelected_WhenRequestsIsNotOptions() + { + // Arrange + var expected = new PageResult(); + var context = GetContext(handlerMethodDescriptor: null); + context.HttpContext.Request.Method = "DELETE"; + context.Result = expected; + + var filter = new HandleOptionsRequestsPageFilter(); + + // Act + filter.OnPageHandlerExecuting(context); + + // Assert + Assert.Same(expected, context.Result); + } + + [Fact] + public void OnPageHandlerExecuting_DoesNothing_ForOptionsRequestWhenHandlerIsSelected() + { + // Arrange + var context = GetContext(new HandlerMethodDescriptor()); + context.HttpContext.Request.Method = "Options"; + + var filter = new HandleOptionsRequestsPageFilter(); + + // Act + filter.OnPageHandlerExecuting(context); + + // Assert + Assert.Null(context.Result); + } + + [Fact] + public void OnPageHandlerExecuting_DoesNotOverwriteResult_ForOptionsRequestWhenNoHandler() + { + // Arrange + var expected = new NotFoundResult(); + var context = GetContext(new HandlerMethodDescriptor()); + context.Result = expected; + context.HttpContext.Request.Method = "Options"; + + var filter = new HandleOptionsRequestsPageFilter(); + + // Act + filter.OnPageHandlerExecuting(context); + + // Assert + Assert.Same(expected, context.Result); + } + + [Fact] + public void OnPageHandlerExecuting_SetsResult_ForOptionsRequestWhenNoHandlerIsSelected() + { + // Arrange + var context = GetContext(handlerMethodDescriptor: null); + context.HttpContext.Request.Method = "Options"; + + var filter = new HandleOptionsRequestsPageFilter(); + + // Act + filter.OnPageHandlerExecuting(context); + + // Assert + Assert.IsType(context.Result); + } + + private static PageHandlerExecutingContext GetContext(HandlerMethodDescriptor handlerMethodDescriptor) + { + var actionContext = new ActionContext(new DefaultHttpContext(), new RouteData(), new PageActionDescriptor()); + var pageContext = new PageContext(actionContext); + return new PageHandlerExecutingContext(pageContext, Array.Empty(), handlerMethodDescriptor, new Dictionary(), new object()); + } + } +} diff --git a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/AuthorizationPageApplicationModelProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/AuthorizationPageApplicationModelProviderTest.cs index 008435da3c..559a653985 100644 --- a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/AuthorizationPageApplicationModelProviderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/AuthorizationPageApplicationModelProviderTest.cs @@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc.ApplicationModels; using Microsoft.AspNetCore.Mvc.Authorization; using Microsoft.AspNetCore.Mvc.ModelBinding; +using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure; using Microsoft.Extensions.Options; using Xunit; @@ -30,7 +31,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal // Assert Assert.Collection( context.PageApplicationModel.Filters, - f => Assert.IsType(f)); + f => Assert.IsType(f), + f => Assert.IsType(f)); } private class PageWithAuthorizeHandlers : Page @@ -63,6 +65,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal Assert.Collection( context.PageApplicationModel.Filters, f => Assert.IsType(f), + f => Assert.IsType(f), f => Assert.IsType(f)); } @@ -102,6 +105,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal Assert.Collection( context.PageApplicationModel.Filters, f => Assert.IsType(f), + f => Assert.IsType(f), f => authorizeFilter = Assert.IsType(f)); // Basic + Basic2 + Derived authorize @@ -143,6 +147,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal Assert.Collection( context.PageApplicationModel.Filters, f => Assert.IsType(f), + f => Assert.IsType(f), f => Assert.IsType(f)); } @@ -163,7 +168,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal { var defaultProvider = new DefaultPageApplicationModelProvider( TestModelMetadataProvider.CreateDefaultProvider(), - Options.Create(new MvcOptions { AllowValidatingTopLevelNodes = true })); + Options.Create(new MvcOptions { AllowValidatingTopLevelNodes = true }), + Options.Create(new RazorPagesOptions { AllowDefaultHandlingForOptionsRequests = true })); var context = new PageApplicationModelProviderContext(new PageActionDescriptor(), typeInfo); defaultProvider.OnProvidersExecuting(context); return context; diff --git a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/ResponseCacheFilterApplicationModelProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/ResponseCacheFilterApplicationModelProviderTest.cs index cf6acab03f..6b08977e2d 100644 --- a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/ResponseCacheFilterApplicationModelProviderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Internal/ResponseCacheFilterApplicationModelProviderTest.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc.ApplicationModels; using Microsoft.AspNetCore.Mvc.ModelBinding; +using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Moq; @@ -31,7 +32,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal // Assert Assert.Collection( context.PageApplicationModel.Filters, - f => Assert.IsType(f)); + f => Assert.IsType(f), + f => Assert.IsType(f)); } private class PageWithoutResponseCache : Page @@ -66,6 +68,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal context.PageApplicationModel.Filters, f => { }, f => Assert.IsType(f), + f => Assert.IsType(f), f => { var filter = Assert.IsType(f); @@ -112,6 +115,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal context.PageApplicationModel.Filters, f => { }, f => Assert.IsType(f), + f => Assert.IsType(f), f => { var filter = Assert.IsType(f); @@ -139,7 +143,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal { var defaultProvider = new DefaultPageApplicationModelProvider( TestModelMetadataProvider.CreateDefaultProvider(), - Options.Create(new MvcOptions())); + Options.Create(new MvcOptions()), + Options.Create(new RazorPagesOptions { AllowDefaultHandlingForOptionsRequests = true })); var context = new PageApplicationModelProviderContext(new PageActionDescriptor(), typeInfo); defaultProvider.OnProvidersExecuting(context); return context; diff --git a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Microsoft.AspNetCore.Mvc.RazorPages.Test.csproj b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Microsoft.AspNetCore.Mvc.RazorPages.Test.csproj index 64835957ec..967a8c3ef4 100644 --- a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Microsoft.AspNetCore.Mvc.RazorPages.Test.csproj +++ b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/Microsoft.AspNetCore.Mvc.RazorPages.Test.csproj @@ -1,4 +1,4 @@ - + $(StandardTestTfms) diff --git a/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/Microsoft.AspNetCore.Mvc.TagHelpers.Test.csproj b/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/Microsoft.AspNetCore.Mvc.TagHelpers.Test.csproj index b9c56ca6de..fd04152330 100644 --- a/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/Microsoft.AspNetCore.Mvc.TagHelpers.Test.csproj +++ b/test/Microsoft.AspNetCore.Mvc.TagHelpers.Test/Microsoft.AspNetCore.Mvc.TagHelpers.Test.csproj @@ -1,4 +1,4 @@ - + $(StandardTestTfms) diff --git a/test/Microsoft.AspNetCore.Mvc.Test/IntegrationTest/CompatibilitySwitchIntegrationTest.cs b/test/Microsoft.AspNetCore.Mvc.Test/IntegrationTest/CompatibilitySwitchIntegrationTest.cs index 2281f4d602..409605d730 100644 --- a/test/Microsoft.AspNetCore.Mvc.Test/IntegrationTest/CompatibilitySwitchIntegrationTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Test/IntegrationTest/CompatibilitySwitchIntegrationTest.cs @@ -49,6 +49,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTest Assert.True(apiBehaviorOptions.SuppressUseValidationProblemDetailsForInvalidModelStateResponses); Assert.True(apiBehaviorOptions.SuppressMapClientErrors); Assert.True(razorViewEngineOptions.AllowRecompilingViewsOnFileChange); + Assert.False(razorPagesOptions.AllowDefaultHandlingForOptionsRequests); } [Fact] @@ -80,6 +81,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTest Assert.True(apiBehaviorOptions.SuppressUseValidationProblemDetailsForInvalidModelStateResponses); Assert.True(apiBehaviorOptions.SuppressMapClientErrors); Assert.True(razorViewEngineOptions.AllowRecompilingViewsOnFileChange); + Assert.False(razorPagesOptions.AllowDefaultHandlingForOptionsRequests); } [Fact] @@ -111,6 +113,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTest Assert.False(apiBehaviorOptions.SuppressUseValidationProblemDetailsForInvalidModelStateResponses); Assert.False(apiBehaviorOptions.SuppressMapClientErrors); Assert.False(razorViewEngineOptions.AllowRecompilingViewsOnFileChange); + Assert.True(razorPagesOptions.AllowDefaultHandlingForOptionsRequests); } [Fact] @@ -142,6 +145,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTest Assert.False(apiBehaviorOptions.SuppressUseValidationProblemDetailsForInvalidModelStateResponses); Assert.False(apiBehaviorOptions.SuppressMapClientErrors); Assert.False(razorViewEngineOptions.AllowRecompilingViewsOnFileChange); + Assert.True(razorPagesOptions.AllowDefaultHandlingForOptionsRequests); } // This just does the minimum needed to be able to resolve these options. diff --git a/test/Microsoft.AspNetCore.Mvc.Test/Microsoft.AspNetCore.Mvc.Test.csproj b/test/Microsoft.AspNetCore.Mvc.Test/Microsoft.AspNetCore.Mvc.Test.csproj index 6e674cf924..d0fbd363f4 100644 --- a/test/Microsoft.AspNetCore.Mvc.Test/Microsoft.AspNetCore.Mvc.Test.csproj +++ b/test/Microsoft.AspNetCore.Mvc.Test/Microsoft.AspNetCore.Mvc.Test.csproj @@ -1,4 +1,4 @@ - + $(StandardTestTfms) diff --git a/test/Microsoft.AspNetCore.Mvc.TestDiagnosticListener/Microsoft.AspNetCore.Mvc.TestDiagnosticListener.csproj b/test/Microsoft.AspNetCore.Mvc.TestDiagnosticListener/Microsoft.AspNetCore.Mvc.TestDiagnosticListener.csproj index 23a77e17a1..9ce101241e 100644 --- a/test/Microsoft.AspNetCore.Mvc.TestDiagnosticListener/Microsoft.AspNetCore.Mvc.TestDiagnosticListener.csproj +++ b/test/Microsoft.AspNetCore.Mvc.TestDiagnosticListener/Microsoft.AspNetCore.Mvc.TestDiagnosticListener.csproj @@ -1,4 +1,4 @@ - + $(StandardTestTfms) diff --git a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test.csproj b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test.csproj index eb45ca869d..1c7b9e362e 100644 --- a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test.csproj +++ b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test.csproj @@ -1,4 +1,4 @@ - + $(StandardTestTfms) diff --git a/test/Microsoft.AspNetCore.Mvc.Views.TestCommon/Microsoft.AspNetCore.Mvc.Views.TestCommon.csproj b/test/Microsoft.AspNetCore.Mvc.Views.TestCommon/Microsoft.AspNetCore.Mvc.Views.TestCommon.csproj index f098adae0f..4cf0e46940 100644 --- a/test/Microsoft.AspNetCore.Mvc.Views.TestCommon/Microsoft.AspNetCore.Mvc.Views.TestCommon.csproj +++ b/test/Microsoft.AspNetCore.Mvc.Views.TestCommon/Microsoft.AspNetCore.Mvc.Views.TestCommon.csproj @@ -1,4 +1,4 @@ - + $(StandardTestTfms) diff --git a/test/Microsoft.AspNetCore.Mvc.WebApiCompatShimTest/Microsoft.AspNetCore.Mvc.WebApiCompatShimTest.csproj b/test/Microsoft.AspNetCore.Mvc.WebApiCompatShimTest/Microsoft.AspNetCore.Mvc.WebApiCompatShimTest.csproj index 888ee8f077..42bdfc7899 100644 --- a/test/Microsoft.AspNetCore.Mvc.WebApiCompatShimTest/Microsoft.AspNetCore.Mvc.WebApiCompatShimTest.csproj +++ b/test/Microsoft.AspNetCore.Mvc.WebApiCompatShimTest/Microsoft.AspNetCore.Mvc.WebApiCompatShimTest.csproj @@ -1,4 +1,4 @@ - + $(StandardTestTfms) diff --git a/test/Mvc.Analyzers.Test/Mvc.Analyzers.Test.csproj b/test/Mvc.Analyzers.Test/Mvc.Analyzers.Test.csproj index 275232d4ab..48a2919472 100644 --- a/test/Mvc.Analyzers.Test/Mvc.Analyzers.Test.csproj +++ b/test/Mvc.Analyzers.Test/Mvc.Analyzers.Test.csproj @@ -1,4 +1,4 @@ - + $(StandardTestTfms) diff --git a/test/Mvc.Api.Analyzers.Test/Mvc.Api.Analyzers.Test.csproj b/test/Mvc.Api.Analyzers.Test/Mvc.Api.Analyzers.Test.csproj index 76dffea5a6..8e9ee75ed7 100644 --- a/test/Mvc.Api.Analyzers.Test/Mvc.Api.Analyzers.Test.csproj +++ b/test/Mvc.Api.Analyzers.Test/Mvc.Api.Analyzers.Test.csproj @@ -1,4 +1,4 @@ - + $(StandardTestTfms) diff --git a/test/WebSites/RazorPagesWebSite/HelloWorldWithOptionsHandler.cshtml b/test/WebSites/RazorPagesWebSite/HelloWorldWithOptionsHandler.cshtml new file mode 100644 index 0000000000..9ee557a98e --- /dev/null +++ b/test/WebSites/RazorPagesWebSite/HelloWorldWithOptionsHandler.cshtml @@ -0,0 +1,17 @@ +@page + +@functions { + public string Source { get; set; } + + public void OnGet() + { + Source = "OnGet"; + } + + public void OnOptions(string message) + { + Source = "OnOptions"; + } +} + +Hello from @Source! \ No newline at end of file