Remove FiltersWebSite

This commit is contained in:
Pranav K 2018-03-02 12:25:53 -08:00
parent aba35c673f
commit ae2d82c748
73 changed files with 205 additions and 2243 deletions

13
Mvc.sln
View File

@ -42,8 +42,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RazorWebSite", "test\WebSit
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FormatterWebSite", "test\WebSites\FormatterWebSite\FormatterWebSite.csproj", "{62735776-46FF-4170-9392-02E128A69B89}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FiltersWebSite", "test\WebSites\FiltersWebSite\FiltersWebSite.csproj", "{1976AC4A-FEA4-4587-A158-D9F79736D2B6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApiExplorerWebSite", "test\WebSites\ApiExplorerWebSite\ApiExplorerWebSite.csproj", "{61061528-071E-424E-965A-07BCC2F02672}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VersioningWebSite", "test\WebSites\VersioningWebSite\VersioningWebSite.csproj", "{C6304029-78C8-4604-99BE-2078DCA1DD36}"
@ -285,16 +283,6 @@ Global
{62735776-46FF-4170-9392-02E128A69B89}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{62735776-46FF-4170-9392-02E128A69B89}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{62735776-46FF-4170-9392-02E128A69B89}.Release|x86.ActiveCfg = Release|Any CPU
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Debug|x86.ActiveCfg = Debug|Any CPU
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Release|Any CPU.Build.0 = Release|Any CPU
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{1976AC4A-FEA4-4587-A158-D9F79736D2B6}.Release|x86.ActiveCfg = Release|Any CPU
{61061528-071E-424E-965A-07BCC2F02672}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{61061528-071E-424E-965A-07BCC2F02672}.Debug|Any CPU.Build.0 = Debug|Any CPU
{61061528-071E-424E-965A-07BCC2F02672}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
@ -878,7 +866,6 @@ Global
{5F945B82-FE5F-425C-956C-8BC2F2020254} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{B07CAF59-11ED-40E3-A5DB-E1178F84FA78} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{62735776-46FF-4170-9392-02E128A69B89} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{1976AC4A-FEA4-4587-A158-D9F79736D2B6} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{61061528-071E-424E-965A-07BCC2F02672} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{C6304029-78C8-4604-99BE-2078DCA1DD36} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{6DB9B8D0-80F7-4E70-BBB0-0B4C04D79A47} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}

View File

@ -473,24 +473,6 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
Assert.Equal("true", response);
}
[Fact]
public async Task AlwaysRunResultFilters_CanRunWhenResourceFiltersShortCircuit()
{
// Arrange
var url = "Filters/AlwaysRunResultFiltersCanRunWhenResourceFilterShortCircuit";
var request = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = new StringContent("Test", Encoding.UTF8, "application/json"),
};
// Act
var response = await Client.SendAsync(request);
// Assert
Assert.Equal(422, (int)response.StatusCode);
Assert.Equal("Can't process this!", await response.Content.ReadAsStringAsync());
}
[Fact]
public async Task ApplicationAssemblyPartIsListedAsFirstAssembly()
{

View File

@ -1,113 +1,28 @@
// 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.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using FiltersWebSite;
using Microsoft.AspNetCore.Mvc.Formatters.Xml;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
{
public class FiltersTest : IClassFixture<MvcTestFixture<FiltersWebSite.Startup>>
public class FiltersTest : IClassFixture<MvcTestFixture<BasicWebSite.Startup>>
{
public FiltersTest(MvcTestFixture<FiltersWebSite.Startup> fixture)
public FiltersTest(MvcTestFixture<BasicWebSite.Startup> fixture)
{
Client = fixture.Client;
}
public HttpClient Client { get; }
// A controller can only be an action filter and result filter, so we don't have entries
// for the other filter types implemented by the controller.
[Fact]
public async Task ListAllFilters()
{
// Arrange
var expected = new string[]
{
"Global Authorization Filter - OnAuthorization",
"On Controller Authorization Filter - OnAuthorization",
"Authorize Filter On Action - OnAuthorization",
"Global Resource Filter - OnResourceExecuting",
"Controller Resource Filter - OnResourceExecuting",
"Action Resource Filter - OnResourceExecuting",
"Controller Override - OnActionExecuting",
"Global Action Filter - OnActionExecuting",
"On Controller Action Filter - OnActionExecuting",
"On Action Action Filter - OnActionExecuting",
"Executing Action",
"On Action Action Filter - OnActionExecuted",
"On Controller Action Filter - OnActionExecuted",
"Global Action Filter - OnActionExecuted",
"Controller Override - OnActionExecuted",
"Controller Override - OnResultExecuting",
"Global Result Filter - OnResultExecuted",
"On Controller Result Filter - OnResultExecuting",
"On Action Result Filter - OnResultExecuting",
"On Action Result Filter - OnResultExecuted",
"On Controller Result Filter - OnResultExecuted",
"Global Result Filter - OnResultExecuted",
"Controller Override - OnResultExecuted",
"Action Resource Filter - OnResourceExecuted",
"Controller Resource Filter - OnResourceExecuted",
"Global Resource Filter - OnResourceExecuted",
};
// Act
var response = await Client.GetAsync("http://localhost/Products/GetPrice/5");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadAsStringAsync();
var filters = response.Headers.GetValues("filters").ToArray();
var i = 0;
foreach (var filter in filters)
{
Assert.Equal(expected[i++], filter);
}
Assert.Equal(expected.Length, filters.Length);
}
[Fact]
public async Task AnonymousUsersAreBlocked()
public async Task CanAuthorize_UsersByRole()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/Anonymous/GetHelloWorld");
// Assert
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
}
[Fact]
public async Task AllowsAnonymousUsersToAccessController()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/RandomNumber/GetRandomNumber");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("4", await response.Content.ReadAsStringAsync());
}
[Theory]
[InlineData("AdminRole")]
[InlineData("InteractiveUsers")]
[InlineData("ApiManagers")]
public async Task CanAuthorize(string testAction)
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/AuthorizeUser/" + testAction);
var response = await Client.GetAsync("AuthorizeUser/AdminRole");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
@ -115,10 +30,10 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
}
[Fact]
public async Task AllowAnonymousOverridesAuthorize()
public async Task CanAuthorize_UsersByPolicyRequirements()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/AuthorizeUser/AlwaysCanCallAllowAnonymous");
var response = await Client.GetAsync("AuthorizeUser/ApiManagers");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
@ -129,414 +44,12 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
public async Task ImpossiblePolicyFailsAuthorize()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/AuthorizeUser/Impossible");
var response = await Client.GetAsync("AuthorizeUser/Impossible");
// Assert
Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
}
[Fact]
public async Task ServiceFilterUsesRegisteredServicesAsFilter()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/RandomNumber/GetRandomNumber");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("4", await response.Content.ReadAsStringAsync());
}
[Fact]
public async Task ServiceFilterThrowsIfServiceIsNotRegistered()
{
// Arrange
var url = "http://localhost/RandomNumber/GetAuthorizedRandomNumber";
// Act
var response = await Client.GetAsync(url);
// Assert
var exception = response.GetServerException();
Assert.Equal(typeof(InvalidOperationException).FullName, exception.ExceptionType);
}
[Fact]
public async Task TypeFilterInitializesArguments()
{
// Arrange
var url = "http://localhost/RandomNumber/GetModifiedRandomNumber?randomNumber=10";
// Act
var response = await Client.GetAsync(url);
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("22", await response.Content.ReadAsStringAsync());
}
[Fact]
public async Task TypeFilterThrowsIfServicesAreNotRegistered()
{
// Arrange
var url = "http://localhost/RandomNumber/GetHalfOfModifiedRandomNumber?randomNumber=3";
// Act
var response = await Client.GetAsync(url);
// Assert
var exception = response.GetServerException();
Assert.Equal(typeof(InvalidOperationException).FullName, exception.ExceptionType);
}
[Fact]
public async Task ActionFilterOverridesActionExecuted()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/XmlSerializer/GetDummyClass?sampleInput=10");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
XmlAssert.Equal("<DummyClass xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SampleInt>10</SampleInt></DummyClass>",
await response.Content.ReadAsStringAsync());
}
[Fact]
public async Task ResultFilterOverridesOnResultExecuting()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/DummyClass/GetDummyClass");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
XmlAssert.Equal("<DummyClass xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SampleInt>120</SampleInt></DummyClass>",
await response.Content.ReadAsStringAsync());
}
[Fact]
public async Task ResultFilterOverridesOnResultExecuted()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/DummyClass/GetEmptyActionResult");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = response.Headers.GetValues("OnResultExecuted");
Assert.Equal(new string[] { "ResultExecutedSuccessfully" }, result);
}
// Verifies result filter is executed after action filter.
[Fact]
public async Task OrderOfExecutionOfFilters_WhenOrderAttribute_IsNotMentioned()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/Home/GetSampleString");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Result filter, Action Filter - OnActionExecuted, From Controller",
await response.Content.ReadAsStringAsync());
}
// Action filter handles the exception thrown in the action.
// Verifies if Result filter is executed after that.
[Fact]
public async Task ExceptionsHandledInActionFilters_WillNotShortCircuitResultFilters()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/Home/ThrowExceptionAndHandleInActionFilter");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Result filter, Hi from Action Filter", await response.Content.ReadAsStringAsync());
}
// Exception filter present on the Action handles the exception, followed by Global Exception filter.
// Verifies that Result filter is skipped.
[Fact]
public async Task ExceptionFilter_OnAction_ShortCircuitsResultFilters()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/Home/ThrowExcpetion");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal(
"GlobalExceptionFilter.OnException, Action Exception Filter",
await response.Content.ReadAsStringAsync());
}
// No Exception filter is present on Action, Controller.
// Verifies if Global exception filter handles the exception.
[Fact]
public async Task GlobalExceptionFilter_HandlesAnException()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/Exception/GetError?error=RandomError");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("GlobalExceptionFilter.OnException", await response.Content.ReadAsStringAsync());
}
// Action, Controller, and a Global Exception filters are present.
// Verifies they are executed in the above mentioned order.
[Fact]
public async Task ExceptionFilter_Scope()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/ExceptionOrder/GetError");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal(
"GlobalExceptionFilter.OnException, " +
"ControllerExceptionFilter.OnException, " +
"Action Exception Filter",
await response.Content.ReadAsStringAsync());
}
// Action, Controller have an action filter.
// Verifies they are executed in the mentioned order.
[Fact]
public async Task ActionFilter_Scope()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/ActionFilter/GetHelloWorld");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal(
"Controller override - OnActionExecuted, " +
"GlobalActionFilter.OnActionExecuted, " +
"Controller Action filter - OnActionExecuted, " +
"Action Filter - OnActionExecuted, " +
"Hello World, " + // Return value from Action
"Action Filter - OnActionExecuting, " +
"Controller Action filter - OnActionExecuting, " +
"GlobalActionFilter.OnActionExecuting, " +
"Controller override - OnActionExecuting",
await response.Content.ReadAsStringAsync());
}
// Action, Controller have an result filter.
// Verifies that Controller Result filter is executed before Action filter.
[Fact]
public async Task ResultFilter_Scope()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/ResultFilter/GetHelloWorld");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal(
"Result filter, " +
"Controller Result filter, " +
"GlobalResultFilter.OnResultExecuting, " +
"Controller Override, " +
"Hello World", // Return value from Action
await response.Content.ReadAsStringAsync());
}
// Action has multiple TypeFilters with Order.
// Verifies if the filters are executed in the mentioned order.
[Fact]
public async Task FiltersWithOrder()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/RandomNumber/GetOrderedRandomNumber");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("88", await response.Content.ReadAsStringAsync());
}
// Action has multiple action filters with Order.
// Verifies they are executed in the mentioned order.
[Fact]
public async Task ActionFiltersWithOrder()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/Home/ActionFilterOrder");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal(
"Action Filter - OnActionExecuted, " +
"Controller Action filter - OnActionExecuted, " +
"Hello World", // Return value from Action
await response.Content.ReadAsStringAsync());
}
// Action has multiple result filters with Order.
// Verifies they are executed in the mentioned order.
[Fact]
public async Task ResultFiltersWithOrder()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/Home/ResultFilterOrder");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal(
"Result filter, Controller Result filter, Hello World",
await response.Content.ReadAsStringAsync());
}
// Action has an action filter which sets the Result.
// Verifies the Action was not executed
[Fact]
public async Task ActionFilterShortCircuitsAction()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/DummyClass/ActionNeverGetsExecuted");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("The Action was never executed", await response.Content.ReadAsStringAsync());
}
// Action has an Result filter which sets the Result.
// Verifies ObjectResult was not executed.
[Fact]
public async Task ResultFilterShortCircuitsResult()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/DummyClass/ResultNeverGetsExecuted");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("The Result was never executed", await response.Content.ReadAsStringAsync());
}
// Action has two Exception filters.
// Verifies that the second Exception Filter was not executed.
[Fact]
public async Task ExceptionFilterShortCircuitsAnotherExceptionFilter()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/Home/ThrowRandomExcpetion");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal(string.Empty, await response.Content.ReadAsStringAsync());
}
// Result Filter throws.
// Exception Filters don't get a chance to handle this.
[Fact]
public async Task ThrowingFilters_ResultFilter_NotHandledByGlobalExceptionFilter()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/Home/ThrowingResultFilter");
// Assert
var exception = response.GetServerException();
Assert.Equal(typeof(InvalidProgramException).FullName, exception.ExceptionType);
}
// Action Filter throws.
// Verifies the Global Exception Filter handles it.
[Fact]
public async Task ThrowingFilters_ActionFilter_HandledByGlobalExceptionFilter()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/Home/ThrowingActionFilter");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("GlobalExceptionFilter.OnException", await response.Content.ReadAsStringAsync());
}
// Authorization Filter throws.
// Exception Filters don't get a chance to handle this.
[Fact]
public async Task ThrowingFilters_AuthFilter_NotHandledByGlobalExceptionFilter()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/Home/ThrowingAuthorizationFilter");
// Assert
var exception = response.GetServerException();
Assert.Equal(typeof(InvalidProgramException).FullName, exception.ExceptionType);
}
// Exception Filter throws.
// Verifies the thrown exception is ignored.
[Fact]
public async Task ThrowingExceptionFilter_ExceptionFilter_NotHandledByGlobalExceptionFilter()
{
// Arrange & Act
var response = await Client.GetAsync("http://localhost/Home/ThrowingExceptionFilter");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Throwing Exception Filter", await response.Content.ReadAsStringAsync());
}
[Fact]
public async Task ResourceFilter_ShortCircuitsUsingObjectResult_UsesOptions()
{
// Arrange
var input = "{ sampleInt: 10 }";
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/ResourceFilter/Post");
request.Content = new StringContent(input, Encoding.UTF8, "application/json");
// Act
var response = await Client.SendAsync(request);
// Assert
// Uses formatters from options.
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
// Notice this has been formatted using StringOutputFormatter and not JsonOutputFormatter.
Assert.Equal("someValue", await response.Content.ReadAsStringAsync());
}
[Fact]
public async Task ResourceFilter_ShortCircuitsUsingObjectResult_WithJsonFormatter_ReturnsResponse()
{
// Arrange
var input = "{ sampleInt: 10 }";
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/ResourceFilter/Get");
request.Content = new StringContent(input, Encoding.UTF8, "application/json");
// Act
var response = await Client.SendAsync(request);
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("application/json", response.Content.Headers.ContentType.MediaType);
Assert.Equal("\"someValue\"", await response.Content.ReadAsStringAsync());
}
[Fact]
public async Task ResourceFilter_RemovingValueProviderFactoriesForAnAction_DoesNotAffectOtherActions()
{
// Request to an action which does NOT expect form value model binding
// Arrange & Act
var response = await Client.PostAsync(
"http://localhost/ResourceFilter/FormValueModelBinding_Disabled",
new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("SampleInt", "10") }));
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("text/plain", response.Content.Headers.ContentType.MediaType);
Assert.Equal("Data:0", await response.Content.ReadAsStringAsync());
// Request to an action which expects form value model binding
// Arrange & Act
response = await Client.PostAsync(
"http://localhost/ResourceFilter/FormValueModelBinding_Enabled",
new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("SampleInt", "10") }));
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("text/plain", response.Content.Headers.ContentType.MediaType);
Assert.Equal("Data:10", await response.Content.ReadAsStringAsync());
}
[Theory]
[InlineData("en-US", "en-US")]
[InlineData("fr", "fr")]
@ -546,7 +59,7 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
string expected)
{
// Arrange & Act
var response = await Client.GetAsync($"http://localhost/{culture}/MiddlewareFilterTest/CultureFromRouteData");
var response = await Client.GetAsync($"{culture}/Filters/MiddlewareFilterTest");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
@ -554,5 +67,51 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
$"CurrentCulture:{expected},CurrentUICulture:{expected}",
await response.Content.ReadAsStringAsync());
}
[Fact]
public async Task AlwaysRunResultFilters_CanRunWhenResourceFiltersShortCircuit()
{
// Arrange
var url = "Filters/AlwaysRunResultFiltersCanRunWhenResourceFilterShortCircuit";
var request = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = new StringContent("Test", Encoding.UTF8, "application/json"),
};
// Act
var response = await Client.SendAsync(request);
// Assert
Assert.Equal(422, (int)response.StatusCode);
Assert.Equal("Can't process this!", await response.Content.ReadAsStringAsync());
}
[Fact]
public async Task FiltersCanBeDeclaredGlobally()
{
// Arrange
var url = "Filters/TraceResult";
// Act
var response = await Client.GetStringAsync(url);
// Assert
Assert.Equal("This value was set by TraceResourceFilter", response);
}
[Fact]
public async Task ServiceFiltersWork()
{
// Arrange
var url = "Filters/ServiceFilterTest";
// Act
var response = await Client.GetAsync(url);
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Service filter content", await response.Content.ReadAsStringAsync());
Assert.Equal(new[] { "True" }, response.Headers.GetValues("X-ServiceActionFilter"));
}
}
}
}

View File

@ -1,48 +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 System.Net;
using System.Net.Http;
using FiltersWebSite;
using Xunit;
using Xunit.Sdk;
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
{
public static class HttpResponseMessageExceptions
{
public static ExceptionInfo GetServerException(this HttpResponseMessage response)
{
if (response.StatusCode != HttpStatusCode.InternalServerError)
{
throw new AssertActualExpectedException(
HttpStatusCode.InternalServerError,
response.StatusCode,
"A server-side exception should be returned as a 500.");
}
var headers = response.Headers;
IEnumerable<string> exceptionMessageHeader;
IEnumerable<string> exceptionTypeHeader;
if (!headers.TryGetValues(ErrorReporterMiddleware.ExceptionMessageHeader, out exceptionMessageHeader))
{
throw new XunitException(
"No value for the '" + ErrorReporterMiddleware.ExceptionMessageHeader + "' header.");
}
if (!headers.TryGetValues(ErrorReporterMiddleware.ExceptionTypeHeader, out exceptionTypeHeader))
{
throw new XunitException(
"No value for the '" + ErrorReporterMiddleware.ExceptionTypeHeader + "' header.");
}
return new ExceptionInfo()
{
ExceptionMessage = Assert.Single(exceptionMessageHeader),
ExceptionType = Assert.Single(exceptionTypeHeader),
};
}
}
}

View File

@ -25,7 +25,6 @@
<ProjectReference Include="..\WebSites\CorsWebSite\CorsWebSite.csproj" />
<ProjectReference Include="..\WebSites\ErrorPageMiddlewareWebSite\ErrorPageMiddlewareWebSite.csproj" />
<ProjectReference Include="..\WebSites\FilesWebSite\FilesWebSite.csproj" />
<ProjectReference Include="..\WebSites\FiltersWebSite\FiltersWebSite.csproj" />
<ProjectReference Include="..\WebSites\FormatterWebSite\FormatterWebSite.csproj" />
<ProjectReference Include="..\WebSites\HtmlGenerationWebSite\HtmlGenerationWebSite.csproj" />
<ProjectReference Include="..\Microsoft.AspNetCore.Mvc.TestCommon\Microsoft.AspNetCore.Mvc.TestCommon.csproj" />

View File

@ -10,11 +10,11 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace FiltersWebSite
namespace BasicWebSite
{
public class BasicAuthenticationHandler : AuthenticationHandler<BasicOptions>
public class BasicAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
public BasicAuthenticationHandler(IOptionsMonitor<BasicOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
public BasicAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
: base(options, logger, encoder, clock)
{ }
@ -22,15 +22,18 @@ namespace FiltersWebSite
{
var principal = new ClaimsPrincipal();
principal.AddIdentity(new ClaimsIdentity(
new Claim[] {
new Claim("Permission", "CanViewPage"),
new[]
{
new Claim("Manager", "yes"),
new Claim(ClaimTypes.Role, "Administrator"),
new Claim(ClaimTypes.NameIdentifier, "John")
},
Scheme.Name));
return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(principal,
new AuthenticationProperties(), Scheme.Name)));
return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(
principal,
new AuthenticationProperties(),
Scheme.Name)));
}
}
}
}

View File

@ -8,6 +8,8 @@
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.Mvc\Microsoft.AspNetCore.Mvc.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.Mvc.Formatters.Xml\Microsoft.AspNetCore.Mvc.Formatters.Xml.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="$(MicrosoftAspNetCoreAuthenticationPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Localization.Routing" Version="$(MicrosoftAspNetCoreLocalizationRoutingPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(MicrosoftAspNetCoreServerIISIntegrationPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Session" Version="$(MicrosoftAspNetCoreSessionPackageVersion)" />

View File

@ -0,0 +1,34 @@
// 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.Security.Claims;
using Microsoft.Extensions.DependencyInjection;
namespace BasicWebSite
{
internal static class ConfigureAuthPoliciesExtensions
{
public static void ConfigureBaseWebSiteAuthPolicies(this IServiceCollection services)
{
services.AddAuthorization(options =>
{
// This policy cannot succeed since the claim is never added
options.AddPolicy("Impossible", policy =>
{
policy.AuthenticationSchemes.Add("Api");
policy.RequireClaim("Never");
});
options.AddPolicy("Api", policy =>
{
policy.AuthenticationSchemes.Add("Api");
policy.RequireClaim(ClaimTypes.NameIdentifier);
});
options.AddPolicy("Api-Manager", policy =>
{
policy.AuthenticationSchemes.Add("Api");
policy.Requirements.Add(Operations.Edit);
});
});
}
}
}

View File

@ -1,10 +1,11 @@
// 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;
using Microsoft.AspNetCore.Authorization;
namespace FiltersWebSite
namespace BasicWebSite
{
[Authorize("Api")]
public class AuthorizeUserController : Controller
@ -21,23 +22,10 @@ namespace FiltersWebSite
return "Hello World!";
}
[Authorize("Interactive")]
public string InteractiveUsers()
{
return "Hello World!";
}
[Authorize("Impossible")]
[AllowAnonymous]
public string AlwaysCanCallAllowAnonymous()
{
return "Hello World!";
}
[Authorize("Impossible")]
public string Impossible()
{
return "Hello World!";
throw new Exception("Shouldn't be invoked.");
}
}
}
}

View File

@ -2,12 +2,10 @@
// 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.Threading.Tasks;
using System.Globalization;
using BasicWebSite.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Serialization;
namespace BasicWebSite.Controllers
{
@ -18,5 +16,18 @@ namespace BasicWebSite.Controllers
[UnprocessableResultFilter]
public IActionResult AlwaysRunResultFiltersCanRunWhenResourceFilterShortCircuit([FromBody] Product product) =>
throw new Exception("Shouldn't be executed");
[ServiceFilter(typeof(ServiceActionFilter))]
public IActionResult ServiceFilterTest() => Content("Service filter content");
[TraceResultOutputFilter]
public IActionResult TraceResult() => new EmptyResult();
[Route("{culture}/[controller]/[action]")]
[MiddlewareFilter(typeof(LocalizationPipeline))]
public IActionResult MiddlewareFilterTest()
{
return Content($"CurrentCulture:{CultureInfo.CurrentCulture.Name},CurrentUICulture:{CultureInfo.CurrentUICulture.Name}");
}
}
}

View File

@ -0,0 +1,29 @@
// 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.Mvc.Filters;
using Microsoft.Extensions.Logging;
namespace BasicWebSite
{
public class ServiceActionFilter : IActionFilter
{
private readonly ILogger<ServiceActionFilter> _logger;
public ServiceActionFilter(ILogger<ServiceActionFilter> logger)
{
_logger = logger;
}
public void OnActionExecuted(ActionExecutedContext context)
{
}
public void OnActionExecuting(ActionExecutingContext context)
{
_logger.LogInformation($"Executing {nameof(ServiceActionFilter)}.");
context.HttpContext.Response.Headers["X-ServiceActionFilter"] = "True";
}
}
}

View File

@ -1,19 +1,19 @@
// 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.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
namespace FiltersWebSite
namespace BasicWebSite
{
public class ShortCircuitResultFilter : ResultFilterAttribute
public class TraceResultOutputFilter : ResultFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext context)
{
context.Result = new ContentResult
{
Content = "The Result was never executed"
};
var trace = context.HttpContext.Items[nameof(TraceResourceFilter)];
context.Result = new ObjectResult(trace);
}
}
}
}

View File

@ -0,0 +1,21 @@
// 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.Mvc.Filters;
namespace BasicWebSite
{
public class TraceResourceFilter : IResourceFilter
{
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
public void OnResourceExecuting(ResourceExecutingContext context)
{
context.HttpContext.Items[nameof(TraceResourceFilter)] = $"This value was set by {nameof(TraceResourceFilter)}";
}
}
}

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Globalization;
@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc.Localization;
using Microsoft.AspNetCore.Localization.Routing;
namespace FiltersWebSite
namespace BasicWebSite
{
public class LocalizationPipeline
{

View File

@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
namespace FiltersWebSite
namespace BasicWebSite
{
public class ManagerHandler : AuthorizationHandler<OperationAuthorizationRequirement>
{

View File

@ -3,12 +3,10 @@
using Microsoft.AspNetCore.Authorization.Infrastructure;
namespace FiltersWebSite
namespace BasicWebSite
{
public static class Operations
{
public static OperationAuthorizationRequirement Edit = new OperationAuthorizationRequirement { Name = "Edit" };
public static OperationAuthorizationRequirement Create = new OperationAuthorizationRequirement { Name = "Create" };
public static OperationAuthorizationRequirement Delete = new OperationAuthorizationRequirement { Name = "Delete" };
}
}

View File

@ -2,6 +2,9 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Linq;
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
@ -14,8 +17,17 @@ namespace BasicWebSite
// Set up application services
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication()
.AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>("Api", _ => { });
services.AddTransient<IAuthorizationHandler, ManagerHandler>();
services
.AddMvc(options => options.Conventions.Add(new ApplicationDescription("This is a basic website.")))
.AddMvc(options =>
{
options.Conventions.Add(new ApplicationDescription("This is a basic website."));
// Filter that records a value in HttpContext.Items
options.Filters.Add(new TraceResourceFilter());
})
.AddXmlDataContractSerializerFormatters();
services.Configure<ApiBehaviorOptions>(options =>
@ -34,11 +46,16 @@ namespace BasicWebSite
};
});
services.ConfigureBaseWebSiteAuthPolicies();
services.AddTransient<IAuthorizationHandler, ManagerHandler>();
services.AddLogging();
services.AddSingleton<IActionDescriptorProvider, ActionDescriptorCreationCounter>();
services.AddHttpContextAccessor();
services.AddSingleton<ContactsRepository>();
services.AddScoped<RequestIdService>();
services.AddTransient<ServiceActionFilter>();
}
public void Configure(IApplicationBuilder app)

View File

@ -14,6 +14,7 @@ namespace BasicWebSite
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.ConfigureBaseWebSiteAuthPolicies();
}
public void Configure(IApplicationBuilder app)

View File

@ -16,6 +16,8 @@ namespace BasicWebSite
{
o.CheckConsentNeeded = httpContext => true;
});
services.ConfigureBaseWebSiteAuthPolicies();
}
public void Configure(IApplicationBuilder app)

View File

@ -15,6 +15,8 @@ namespace BasicWebSite
.AddMvc()
.AddSessionStateTempDataProvider();
services.AddSession();
services.ConfigureBaseWebSiteAuthPolicies();
}
public void Configure(IApplicationBuilder app)

View File

@ -1,16 +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.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Options;
namespace FiltersWebSite
{
public class BasicOptions : AuthenticationSchemeOptions
{
}
}

View File

@ -1,55 +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.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FiltersWebSite
{
[ControllerActionFilter]
public class ActionFilterController : Controller
{
[ChangeContentActionFilter]
public IActionResult GetHelloWorld(IList<ContentResult> fromGlobalActionFilter)
{
// Should have got content from Global Action Filter followed by Controller Override.
if (fromGlobalActionFilter != null)
{
ContentResult combinedResult = null;
var resultsFromActionFilters = fromGlobalActionFilter as List<ContentResult>;
foreach (var result in resultsFromActionFilters)
{
combinedResult = Helpers.GetContentResult(combinedResult, result.Content);
}
return Helpers.GetContentResult(combinedResult, "Hello World");
}
return null;
}
public override void OnActionExecuting(ActionExecutingContext context)
{
object obj;
List<ContentResult> filters;
if (context.ActionArguments.TryGetValue("fromGlobalActionFilter", out obj))
{
filters = (List<ContentResult>)obj;
}
else
{
filters = new List<ContentResult>();
context.ActionArguments.Add("fromGlobalActionFilter", filters);
}
filters.Add(Helpers.GetContentResult(context.Result, "Controller override - OnActionExecuting"));
}
public override void OnActionExecuted(ActionExecutedContext context)
{
context.Result = Helpers.GetContentResult(context.Result, "Controller override - OnActionExecuted");
}
}
}

View File

@ -1,16 +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;
namespace FiltersWebSite
{
[BlockAnonymous]
public class AnonymousController : Controller
{
public string GetHelloWorld()
{
return "Hello World!";
}
}
}

View File

@ -1,46 +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.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace FiltersWebSite
{
public class DummyClassController : Controller
{
[ModifyResultsFilter]
public DummyClass GetDummyClass()
{
return new DummyClass()
{
SampleInt = 10
};
}
[AddHeader]
public IActionResult GetEmptyActionResult()
{
return new TestActionResult();
}
[ShortCircuitActionFilter]
public string ActionNeverGetsExecuted()
{
return "Hello World!";
}
[ShortCircuitResultFilter]
public IActionResult ResultNeverGetsExecuted()
{
return new ObjectResult("Returned in Object Result");
}
}
public class TestActionResult : IActionResult
{
public Task ExecuteResultAsync(ActionContext context)
{
return Task.FromResult(true);
}
}
}

View File

@ -1,16 +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;
namespace FiltersWebSite
{
public class ExceptionController : Controller
{
public string GetError(string error)
{
throw new InvalidOperationException(error);
}
}
}

View File

@ -1,18 +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;
namespace FiltersWebSite
{
[ControllerExceptionFilter]
public class ExceptionOrderController : Controller
{
[HandleInvalidOperationExceptionFilter]
public string GetError(string error)
{
throw new InvalidOperationException(error);
}
}
}

View File

@ -1,86 +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;
namespace FiltersWebSite.Controllers
{
public class HomeController
{
[ChangeContentActionFilter]
[ChangeContentResultFilter]
public IActionResult GetSampleString()
{
return new ContentResult()
{
Content = "From Controller"
};
}
[ThrowingResultFilter]
[HandleInvalidOperationExceptionFilter]
public IActionResult ThrowExcpetion()
{
throw new InvalidOperationException("Controller threw.");
}
[HandleExceptionActionFilter]
[ChangeContentResultFilter]
public IActionResult ThrowExceptionAndHandleInActionFilter()
{
throw new InvalidOperationException("Controller threw.");
}
[ControllerActionFilter(Order = 2)]
[ChangeContentActionFilter(Order = 1)]
public IActionResult ActionFilterOrder()
{
return new ContentResult()
{
Content = "Hello World"
};
}
[ControllerResultFilter(Order = 1)]
[ChangeContentResultFilter(Order = 2)]
public IActionResult ResultFilterOrder()
{
return new ContentResult()
{
Content = "Hello World"
};
}
[ThrowingResultFilter]
public string ThrowingResultFilter()
{
return "Throwing Result Filter";
}
[ThrowingActionFilter]
public string ThrowingActionFilter()
{
return "Throwing Action Filter";
}
[ThrowingExceptionFilter]
public string ThrowingExceptionFilter()
{
return "Throwing Exception Filter";
}
[ThrowingAuthorizationFilter]
public string ThrowingAuthorizationFilter()
{
return "Throwing Authorization Filter";
}
[HandleInvalidOperationExceptionFilter]
[ShortCircuitExceptionFilter(Order=12)]
public IActionResult ThrowRandomExcpetion()
{
throw new InvalidOperationException("Controller threw.");
}
}
}

View File

@ -1,18 +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.Globalization;
using Microsoft.AspNetCore.Mvc;
namespace FiltersWebSite
{
public class MiddlewareFilterTestController : Controller
{
[Route("{culture}/[controller]/[action]")]
[MiddlewareFilter(typeof(LocalizationPipeline))]
public IActionResult CultureFromRouteData()
{
return Content($"CurrentCulture:{CultureInfo.CurrentCulture.Name},CurrentUICulture:{CultureInfo.CurrentUICulture.Name}");
}
}
}

View File

@ -1,50 +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.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FiltersWebSite
{
// This controller will list the filters that are configured for each action in a header.
// This exercises the merging of filters with the global filters collection.
[ControllerResultFilter]
[ControllerActionFilter]
[ControllerAuthorizationFilter]
[TracingResourceFilter("Controller Resource Filter")]
public class ProductsController : Controller, IResultFilter
{
[PassThroughResultFilter]
[PassThroughActionFilter]
[AuthorizeUser]
[TracingResourceFilter("Action Resource Filter")]
public IActionResult GetPrice(int id)
{
Response.Headers.Append("filters", "Executing Action");
// This skips the ExecuteResultAsync in ActionResult. Thus result is not set.
// Hence we can see all the OnResultExecuted functions in the response.
return new TestActionResult();
}
public override void OnActionExecuting(ActionExecutingContext context)
{
context.HttpContext.Response.Headers.Append("filters", "Controller Override - OnActionExecuting");
}
public override void OnActionExecuted(ActionExecutedContext context)
{
context.HttpContext.Response.Headers.Append("filters", "Controller Override - OnActionExecuted");
}
public void OnResultExecuted(ResultExecutedContext context)
{
context.HttpContext.Response.Headers.Append("filters", "Controller Override - OnResultExecuted");
}
public void OnResultExecuting(ResultExecutingContext context)
{
context.HttpContext.Response.Headers.Append("filters", "Controller Override - OnResultExecuting");
}
}
}

View File

@ -1,50 +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.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace FiltersWebSite
{
[AllowAnonymous]
[HandleInvalidOperationExceptionFilter]
public class RandomNumberController : Controller
{
[ServiceFilter(typeof(RandomNumberFilter))]
public int GetRandomNumber()
{
return 2;
}
[ServiceFilter(typeof(AuthorizeUserAttribute))]
public int GetAuthorizedRandomNumber()
{
return 2;
}
[TypeFilter(typeof(RandomNumberProvider))]
public int GetModifiedRandomNumber(int randomNumber)
{
return randomNumber / 2;
}
[TypeFilter(typeof(ModifiedRandomNumberProvider))]
public int GetHalfOfModifiedRandomNumber(int randomNumber)
{
return randomNumber / 2;
}
[TypeFilter(typeof(RandomNumberModifier), Order = 2)]
[TypeFilter(typeof(RandomNumberProvider), Order = 1)]
public int GetOrderedRandomNumber(int randomNumber)
{
return randomNumber;
}
public string ThrowException()
{
throw new InvalidOperationException();
}
}
}

View File

@ -1,84 +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.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace FiltersWebSite.Controllers
{
[Route("ResourceFilter/[action]")]
public class ResourceFilterController : Controller
{
[HttpPost]
[ShortCircuitWithFormatter]
public string Get()
{
return "NeverGetsExecuted";
}
[HttpPost]
[ShortCircuit]
public string Post()
{
return "NeverGetsExecuted";
}
[HttpPost]
public IActionResult FormValueModelBinding_Enabled(DummyClass dc)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
return Ok("Data:" + dc?.SampleInt);
}
[HttpPost]
[DisableFormValueModelBinding]
public IActionResult FormValueModelBinding_Disabled(DummyClass dc)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
return Ok("Data:" + dc?.SampleInt);
}
private class ShortCircuitWithFormatterAttribute : Attribute, IResourceFilter
{
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
public void OnResourceExecuting(ResourceExecutingContext context)
{
var mvcOptions = context.HttpContext.RequestServices.GetRequiredService<IOptions<MvcOptions>>();
var formatter = mvcOptions.Value.OutputFormatters.OfType<JsonOutputFormatter>().First();
var result = new ObjectResult("someValue");
result.Formatters.Add(formatter);
context.Result = result;
}
}
private class ShortCircuitAttribute : Attribute, IResourceFilter
{
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
public void OnResourceExecuting(ResourceExecutingContext context)
{
// ShortCircuit.
context.Result = new ObjectResult("someValue");
}
}
}
}

View File

@ -1,27 +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;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FiltersWebSite
{
[ControllerResultFilter]
public class ResultFilterController : Controller, IResultFilter
{
[ChangeContentResultFilter]
public IActionResult GetHelloWorld()
{
return Helpers.GetContentResult(null, "Hello World");
}
public void OnResultExecuted(ResultExecutedContext context)
{
}
public void OnResultExecuting(ResultExecutingContext context)
{
context.Result = Helpers.GetContentResult(context.Result, "Controller Override");
}
}
}

View File

@ -1,16 +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;
namespace FiltersWebSite
{
[SerializationActionFilter]
public class XmlSerializerController : Controller
{
public DummyClass GetDummyClass(int sampleInput)
{
return new DummyClass { SampleInt = sampleInput };
}
}
}

View File

@ -1,50 +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.Threading.Tasks;
using Microsoft.AspNetCore.Http;
namespace FiltersWebSite
{
/// <summary>
/// A middleware that reports errors via header values. Useful for tests that want to verify
/// an exception that goes unhandled by the MVC part of the stack.
/// </summary>
public class ErrorReporterMiddleware
{
public static readonly string ExceptionMessageHeader = "ExceptionMessage";
public static readonly string ExceptionTypeHeader = "ExceptionType";
private readonly RequestDelegate _next;
public ErrorReporterMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception exception)
{
if (context.Response.HasStarted)
{
throw;
}
else
{
context.Response.StatusCode = 500;
var escapedMessage = exception.Message.Replace('\r', '_').Replace('\n', '_');
context.Response.Headers.Add(ExceptionTypeHeader, new string[] { exception.GetType().FullName });
context.Response.Headers.Add(ExceptionMessageHeader, new string[] { escapedMessage });
}
}
}
}
}

View File

@ -1,18 +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.Filters;
namespace FiltersWebSite
{
public class AddHeaderAttribute : ResultFilterAttribute
{
public override void OnResultExecuted(ResultExecutedContext context)
{
context.HttpContext.Response.Headers.Add(
"OnResultExecuted", new string[] { "ResultExecutedSuccessfully" });
base.OnResultExecuted(context);
}
}
}

View File

@ -1,34 +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.Reflection;
using System.Security.Claims;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FiltersWebSite
{
public class AuthorizeUserAttribute : Attribute, IAuthorizationFilter
{
public virtual void OnAuthorization(AuthorizationFilterContext context)
{
var controllerActionDescriptor = (ControllerActionDescriptor)context.ActionDescriptor;
if (controllerActionDescriptor.MethodInfo ==
typeof(ProductsController).GetMethod(nameof(ProductsController.GetPrice)))
{
context.HttpContext.Response.Headers.Append("filters",
"Authorize Filter On Action - OnAuthorization");
}
context.HttpContext.User = new ClaimsPrincipal(
new ClaimsIdentity(
new Claim[] {
new Claim("Permission", "CanViewPage"),
new Claim(ClaimTypes.Role, "Administrator"),
new Claim(ClaimTypes.NameIdentifier, "John")},
"Basic"));
}
}
}

View File

@ -1,42 +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.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FiltersWebSite
{
public class BlockAnonymous : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
if (!HasAllowAnonymous(context))
{
var user = context.HttpContext.User;
var userIsAnonymous =
user == null ||
user.Identity == null ||
!user.Identity.IsAuthenticated;
if (userIsAnonymous)
{
context.Result = new UnauthorizedResult();
}
}
}
private bool HasAllowAnonymous(AuthorizationFilterContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
return context.Filters.Any(item => item is IAllowAnonymousFilter);
}
}
}

View File

@ -1,30 +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.Reflection;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FiltersWebSite
{
public class ChangeContentActionFilter : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext context)
{
context.Result = Helpers.GetContentResult(context.Result, "Action Filter - OnActionExecuted");
}
public override void OnActionExecuting(ActionExecutingContext context)
{
var controllerActionDescriptor = (ControllerActionDescriptor)context.ActionDescriptor;
if (controllerActionDescriptor.MethodInfo ==
typeof(ActionFilterController).GetMethod(nameof(ActionFilterController.GetHelloWorld)))
{
(context.ActionArguments["fromGlobalActionFilter"] as List<ContentResult>).
Add(Helpers.GetContentResult(context.Result, "Action Filter - OnActionExecuting"));
}
}
}
}

View File

@ -1,15 +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.Filters;
namespace FiltersWebSite
{
public class ChangeContentResultFilter : ResultFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext context)
{
context.Result = Helpers.GetContentResult(context.Result, "Result filter");
}
}
}

View File

@ -1,48 +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.Reflection;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FiltersWebSite
{
public class ControllerActionFilter : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext context)
{
var controllerActionDescriptor = (ControllerActionDescriptor)context.ActionDescriptor;
if (controllerActionDescriptor.MethodInfo ==
typeof(ProductsController).GetMethod(nameof(ProductsController.GetPrice)))
{
context.HttpContext.Response.Headers.Append("filters",
"On Controller Action Filter - OnActionExecuted");
}
else
{
context.Result = Helpers.GetContentResult(context.Result, "Controller Action filter - OnActionExecuted");
}
}
public override void OnActionExecuting(ActionExecutingContext context)
{
var controllerActionDescriptor = (ControllerActionDescriptor)context.ActionDescriptor;
if (controllerActionDescriptor.MethodInfo ==
typeof(ProductsController).GetMethod(nameof(ProductsController.GetPrice)))
{
context.HttpContext.Response.Headers.Append("filters",
"On Controller Action Filter - OnActionExecuting");
}
if (controllerActionDescriptor.MethodInfo ==
typeof(ActionFilterController).GetMethod(nameof(ActionFilterController.GetHelloWorld)))
{
(context.ActionArguments["fromGlobalActionFilter"] as List<ContentResult>)
.Add(Helpers.GetContentResult(context.Result, "Controller Action filter - OnActionExecuting"));
}
}
}
}

View File

@ -1,16 +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.Http;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FiltersWebSite
{
public class ControllerAuthorizationFilter : AuthorizeUserAttribute
{
public override void OnAuthorization(AuthorizationFilterContext context)
{
context.HttpContext.Response.Headers.Append("filters", "On Controller Authorization Filter - OnAuthorization");
}
}
}

View File

@ -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;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FiltersWebSite
{
public class ControllerExceptionFilter : ExceptionFilterAttribute
{
public override void OnException(ExceptionContext context)
{
if (context.Exception.GetType() == typeof(InvalidOperationException))
{
context.Result = Helpers.GetContentResult(context.Result, "ControllerExceptionFilter.OnException");
}
}
}
}

View File

@ -1,39 +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.Reflection;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FiltersWebSite
{
public class ControllerResultFilter : ResultFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext context)
{
var controllerActionDescriptor = (ControllerActionDescriptor)context.ActionDescriptor;
if (controllerActionDescriptor.MethodInfo ==
typeof(ProductsController).GetMethod(nameof(ProductsController.GetPrice)))
{
context.HttpContext.Response.Headers.Append("filters",
"On Controller Result Filter - OnResultExecuting");
}
else
{
context.Result = Helpers.GetContentResult(context.Result, "Controller Result filter");
}
}
public override void OnResultExecuted(ResultExecutedContext context)
{
var controllerActionDescriptor = (ControllerActionDescriptor)context.ActionDescriptor;
if (controllerActionDescriptor.MethodInfo ==
typeof(ProductsController).GetMethod(nameof(ProductsController.GetPrice)))
{
context.HttpContext.Response.Headers.Append("filters",
"On Controller Result Filter - OnResultExecuted");
}
}
}
}

View File

@ -1,38 +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.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
namespace FiltersWebSite
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
var formValueProviderFactory = context.ValueProviderFactories
.OfType<FormValueProviderFactory>()
.FirstOrDefault();
if (formValueProviderFactory != null)
{
context.ValueProviderFactories.Remove(formValueProviderFactory);
}
var jqueryFormValueProviderFactory = context.ValueProviderFactories
.OfType<JQueryFormValueProviderFactory>()
.FirstOrDefault();
if (jqueryFormValueProviderFactory != null)
{
context.ValueProviderFactories.Remove(jqueryFormValueProviderFactory);
}
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
}
}

View File

@ -1,50 +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 System.Reflection;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FiltersWebSite
{
public class GlobalActionFilter : IActionFilter
{
public void OnActionExecuted(ActionExecutedContext context)
{
var controllerActionDescriptor = (ControllerActionDescriptor)context.ActionDescriptor;
if (controllerActionDescriptor.MethodInfo ==
typeof(ActionFilterController).GetMethod(nameof(ActionFilterController.GetHelloWorld)))
{
context.Result = Helpers.GetContentResult(context.Result, "GlobalActionFilter.OnActionExecuted");
}
if (controllerActionDescriptor.MethodInfo ==
typeof(ProductsController).GetMethod(nameof(ProductsController.GetPrice)))
{
context.HttpContext.Response.Headers.Append("filters",
"Global Action Filter - OnActionExecuted");
}
}
public void OnActionExecuting(ActionExecutingContext context)
{
var controllerActionDescriptor = (ControllerActionDescriptor)context.ActionDescriptor;
if (controllerActionDescriptor.MethodInfo ==
typeof(ActionFilterController).GetMethod(nameof(ActionFilterController.GetHelloWorld)))
{
(context.ActionArguments["fromGlobalActionFilter"] as List<ContentResult>)
.Add(Helpers.GetContentResult(null, "GlobalActionFilter.OnActionExecuting"));
}
if (controllerActionDescriptor.MethodInfo ==
typeof(ProductsController).GetMethod(nameof(ProductsController.GetPrice)))
{
context.HttpContext.Response.Headers.Append("filters",
"Global Action Filter - OnActionExecuting");
}
}
}
}

View File

@ -1,25 +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.Reflection;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FiltersWebSite
{
public class GlobalAuthorizationFilter : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
var controllerActionDescriptor = (ControllerActionDescriptor)context.ActionDescriptor;
if (controllerActionDescriptor.MethodInfo ==
typeof(ProductsController).GetMethod(nameof(ProductsController.GetPrice)))
{
context.HttpContext.Response.Headers.Append("filters",
"Global Authorization Filter - OnAuthorization");
}
}
}
}

View File

@ -1,15 +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.Filters;
namespace FiltersWebSite
{
public class GlobalExceptionFilter : IExceptionFilter
{
public void OnException(ExceptionContext context)
{
context.Result = Helpers.GetContentResult(context.Result, "GlobalExceptionFilter.OnException");
}
}
}

View File

@ -1,41 +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.Reflection;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FiltersWebSite
{
public class GlobalResultFilter : IResultFilter
{
public void OnResultExecuted(ResultExecutedContext context)
{
var controllerActionDescriptor = (ControllerActionDescriptor)context.ActionDescriptor;
if (controllerActionDescriptor.MethodInfo ==
typeof(ProductsController).GetMethod(nameof(ProductsController.GetPrice)))
{
context.HttpContext.Response.Headers.Append("filters",
"Global Result Filter - OnResultExecuted");
}
}
public void OnResultExecuting(ResultExecutingContext context)
{
var controllerActionDescriptor = (ControllerActionDescriptor)context.ActionDescriptor;
if (controllerActionDescriptor.MethodInfo ==
typeof(ResultFilterController).GetMethod(nameof(ResultFilterController.GetHelloWorld)))
{
context.Result = Helpers.GetContentResult(context.Result, "GlobalResultFilter.OnResultExecuting");
}
if (controllerActionDescriptor.MethodInfo ==
typeof(ProductsController).GetMethod(nameof(ProductsController.GetPrice)))
{
context.HttpContext.Response.Headers.Append("filters",
"Global Result Filter - OnResultExecuted");
}
}
}
}

View File

@ -1,20 +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.Filters;
namespace FiltersWebSite
{
public class HandleExceptionActionFilter : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext context)
{
if (context.Exception != null)
{
context.Result = Helpers.GetContentResult(null, "Hi from Action Filter");
context.Exception = null;
}
}
}
}

View File

@ -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;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FiltersWebSite
{
public class HandleInvalidOperationExceptionFilter : ExceptionFilterAttribute
{
public override void OnException(ExceptionContext context)
{
if (context.Exception.GetType() == typeof(InvalidOperationException))
{
context.Result = Helpers.GetContentResult(context.Result, "Action Exception Filter");
}
}
}
}

View File

@ -1,26 +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.Filters;
namespace FiltersWebSite
{
public class ModifiedRandomNumberProvider : IActionFilter
{
private DummyService _dummyService;
public ModifiedRandomNumberProvider(DummyService dummyService)
{
_dummyService = dummyService;
}
public void OnActionExecuted(ActionExecutedContext context)
{
}
public void OnActionExecuting(ActionExecutingContext context)
{
context.ActionArguments["randomNumber"] = _dummyService.RandomNumber;
}
}
}

View File

@ -1,23 +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;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Formatters;
namespace FiltersWebSite
{
public class ModifyResultsFilterAttribute : ResultFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext context)
{
var objResult = context.Result as ObjectResult;
var dummyClass = objResult.Value as DummyClass;
dummyClass.SampleInt = 120;
objResult.Formatters.Add(new XmlSerializerOutputFormatter());
base.OnResultExecuting(context);
}
}
}

View File

@ -1,21 +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.Http;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FiltersWebSite
{
public class PassThroughActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
context.HttpContext.Response.Headers.Append("filters", "On Action Action Filter - OnActionExecuting");
}
public override void OnActionExecuted(ActionExecutedContext context)
{
context.HttpContext.Response.Headers.Append("filters", "On Action Action Filter - OnActionExecuted");
}
}
}

View File

@ -1,35 +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.Reflection;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FiltersWebSite
{
public class PassThroughResultFilter : ResultFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext context)
{
var controllerActionDescriptor = (ControllerActionDescriptor)context.ActionDescriptor;
if (controllerActionDescriptor.MethodInfo ==
typeof(ProductsController).GetMethod(nameof(ProductsController.GetPrice)))
{
context.HttpContext.Response.Headers.Append("filters",
"On Action Result Filter - OnResultExecuting");
}
}
public override void OnResultExecuted(ResultExecutedContext context)
{
var controllerActionDescriptor = (ControllerActionDescriptor)context.ActionDescriptor;
if (controllerActionDescriptor.MethodInfo ==
typeof(ProductsController).GetMethod(nameof(ProductsController.GetPrice)))
{
context.HttpContext.Response.Headers.Append("filters",
"On Action Result Filter - OnResultExecuted");
}
}
}
}

View File

@ -1,25 +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;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Net.Http.Headers;
namespace FiltersWebSite
{
public class RandomNumberFilter : IActionFilter
{
public void OnActionExecuted(ActionExecutedContext context)
{
context.Result = new ContentResult()
{
Content = "4",
ContentType = "text/plain"
};
}
public void OnActionExecuting(ActionExecutingContext context)
{
}
}
}

View File

@ -1,27 +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.Filters;
namespace FiltersWebSite
{
public class RandomNumberModifier : IActionFilter
{
private RandomNumberService _random;
public RandomNumberModifier(RandomNumberService random)
{
_random = random;
}
public void OnActionExecuted(ActionExecutedContext context)
{
}
public void OnActionExecuting(ActionExecutingContext context)
{
var paramterValue = (int)context.ActionArguments["randomNumber"];
context.ActionArguments["randomNumber"] = paramterValue + _random.GetRandamNumber();
}
}
}

View File

@ -1,26 +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.Filters;
namespace FiltersWebSite
{
public class RandomNumberProvider : IActionFilter
{
private RandomNumberService _random;
public RandomNumberProvider(RandomNumberService random)
{
_random = random;
}
public void OnActionExecuted(ActionExecutedContext context)
{
}
public void OnActionExecuting(ActionExecutingContext context)
{
context.ActionArguments["randomNumber"] = _random.GetRandamNumber();
}
}
}

View File

@ -1,23 +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;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Formatters;
namespace FiltersWebSite
{
public class SerializationActionFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext context)
{
var result = context.Result as ObjectResult;
if (result != null)
{
result.Formatters.Add(new XmlSerializerOutputFormatter());
}
base.OnActionExecuted(context);
}
}
}

View File

@ -1,21 +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;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Net.Http.Headers;
namespace FiltersWebSite
{
public class ShortCircuitActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
context.Result = new ContentResult
{
Content = "The Action was never executed",
ContentType = "text/plain"
};
}
}
}

View File

@ -1,15 +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.Filters;
namespace FiltersWebSite
{
public class ShortCircuitExceptionFilter : ExceptionFilterAttribute
{
public override void OnException(ExceptionContext context)
{
context.ExceptionHandled = true;
}
}
}

View File

@ -1,95 +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.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FiltersWebSite
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class TestSyncResourceFilter : Attribute, IResourceFilter, IOrderedFilter
{
public enum Action
{
PassThrough,
ThrowException,
Shortcircuit
}
public readonly string ExceptionMessage = $"Error!! in {nameof(TestSyncResourceFilter)}";
public readonly string ShortcircuitMessage = $"Shortcircuited by {nameof(TestSyncResourceFilter)}";
public Action FilterAction { get; set; }
public int Order { get; set; }
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
public void OnResourceExecuting(ResourceExecutingContext context)
{
if (FilterAction == Action.PassThrough)
{
return;
}
else if (FilterAction == Action.ThrowException)
{
throw new InvalidOperationException(ExceptionMessage);
}
else
{
context.Result = new ContentResult()
{
Content = ShortcircuitMessage,
StatusCode = 400,
ContentType = "text/abcd"
};
}
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class TestAsyncResourceFilter : Attribute, IAsyncResourceFilter, IOrderedFilter
{
public enum Action
{
PassThrough,
ThrowException,
Shortcircuit
}
public readonly string ExceptionMessage = $"Error!! in {nameof(TestAsyncResourceFilter)}";
public readonly string ShortcircuitMessage = $"Shortcircuited by {nameof(TestAsyncResourceFilter)}";
public Action FilterAction { get; set; }
public int Order { get; set; }
public Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
{
if (FilterAction == Action.PassThrough)
{
return next();
}
else if (FilterAction == Action.ThrowException)
{
throw new InvalidOperationException(ExceptionMessage);
}
else
{
context.Result = new ContentResult()
{
Content = ShortcircuitMessage,
StatusCode = 400,
ContentType = "text/abcd"
};
return Task.FromResult(true);
}
}
}
}

View File

@ -1,16 +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.Filters;
namespace FiltersWebSite
{
public class ThrowingActionFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
throw new InvalidProgramException("Action Filter threw");
}
}
}

View File

@ -1,16 +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.Filters;
namespace FiltersWebSite
{
public class ThrowingAuthorizationFilter : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
throw new InvalidProgramException("Authorization Filter Threw");
}
}
}

View File

@ -1,16 +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.Filters;
namespace FiltersWebSite
{
public class ThrowingExceptionFilter : ExceptionFilterAttribute
{
public override void OnException(ExceptionContext context)
{
throw new InvalidProgramException("Exception Filter threw");
}
}
}

View File

@ -1,16 +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.Filters;
namespace FiltersWebSite
{
public class ThrowingResultFilter : ResultFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext context)
{
throw new InvalidProgramException("Result Filter threw.");
}
}
}

View File

@ -1,36 +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.Http;
using Microsoft.AspNetCore.Mvc.Filters;
namespace FiltersWebSite
{
public class TracingResourceFilter : Attribute, IResourceFilter
{
public TracingResourceFilter(string name)
{
Name = name;
}
public string Name { get; }
public void OnResourceExecuted(ResourceExecutedContext context)
{
if (!context.HttpContext.Response.HasStarted)
{
context.HttpContext.Response.Headers.Append(
"filters",
Name + " - OnResourceExecuted");
}
}
public void OnResourceExecuting(ResourceExecutingContext context)
{
context.HttpContext.Response.Headers.Append(
"filters",
Name + " - OnResourceExecuting");
}
}
}

View File

@ -1,17 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFrameworks>$(StandardTestWebsiteTfms)</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.Mvc\Microsoft.AspNetCore.Mvc.csproj" />
<ProjectReference Include="..\..\..\src\Microsoft.AspNetCore.Mvc.Formatters.Xml\Microsoft.AspNetCore.Mvc.Formatters.Xml.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="$(MicrosoftAspNetCoreAuthenticationPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Localization.Routing" Version="$(MicrosoftAspNetCoreLocalizationRoutingPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.IISIntegration" Version="$(MicrosoftAspNetCoreServerIISIntegrationPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="$(MicrosoftAspNetCoreServerKestrelPackageVersion)" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="$(MicrosoftAspNetCoreStaticFilesPackageVersion)" />
</ItemGroup>
</Project>

View File

@ -1,28 +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;
using Microsoft.Net.Http.Headers;
namespace FiltersWebSite
{
public static class Helpers
{
public static ContentResult GetContentResult(object result, string message)
{
var actualResult = result as ContentResult;
var content = message;
if (actualResult != null)
{
content += ", " + actualResult.Content;
}
return new ContentResult()
{
Content = content,
ContentType = "text/plain",
};
}
}
}

View File

@ -1,10 +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.
namespace FiltersWebSite
{
public class DummyClass
{
public int SampleInt { get; set; }
}
}

View File

@ -1,16 +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.
namespace FiltersWebSite
{
public class DummyService
{
public int RandomNumber
{
get
{
return 4;
}
}
}
}

View File

@ -1,13 +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.
namespace FiltersWebSite
{
public class RandomNumberService
{
public int GetRandamNumber()
{
return 44;
}
}
}

View File

@ -1,82 +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.IO;
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
namespace FiltersWebSite
{
public class Startup
{
// Set up application services
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication()
.AddScheme<BasicOptions, BasicAuthenticationHandler>("Interactive", _ => { })
.AddScheme<BasicOptions, BasicAuthenticationHandler>("Api", _ => { });
services.AddMvc();
services.AddAuthorization(options =>
{
// This policy cannot succeed since the claim is never added
options.AddPolicy("Impossible", policy =>
{
policy.AuthenticationSchemes.Add("Interactive");
policy.RequireClaim("Never");
});
options.AddPolicy("Api", policy =>
{
policy.AuthenticationSchemes.Add("Api");
policy.RequireClaim(ClaimTypes.NameIdentifier);
});
options.AddPolicy("Api-Manager", policy =>
{
policy.AuthenticationSchemes.Add("Api");
policy.Requirements.Add(Operations.Edit);
});
options.AddPolicy("Interactive", policy =>
{
policy.AuthenticationSchemes.Add("Interactive");
policy.RequireClaim(ClaimTypes.NameIdentifier)
.RequireClaim("Permission", "CanViewPage");
});
});
services.AddSingleton<RandomNumberFilter>();
services.AddSingleton<RandomNumberService>();
services.AddTransient<IAuthorizationHandler, ManagerHandler>();
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new GlobalExceptionFilter());
options.Filters.Add(new GlobalActionFilter());
options.Filters.Add(new GlobalResultFilter());
options.Filters.Add(new GlobalAuthorizationFilter());
options.Filters.Add(new TracingResourceFilter("Global Resource Filter"));
});
}
public void Configure(IApplicationBuilder app)
{
app.UseMiddleware<ErrorReporterMiddleware>();
app.UseMvcWithDefaultRoute();
}
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.UseKestrel()
.UseIISIntegration()
.Build();
host.Run();
}
}
}

View File

@ -1,5 +0,0 @@
FiltersWebSite
===
This web site illustrates how to use filters to customize request and response. It shows how filters can be
used at a global, controller or action level and how they can be extended.