diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/FiltersTest.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/FiltersTest.cs index b505f3f5a2..18bd1f49d8 100644 --- a/test/Microsoft.AspNet.Mvc.FunctionalTests/FiltersTest.cs +++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/FiltersTest.cs @@ -55,5 +55,154 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests }, filters); } + + [Fact] + public async Task AnonymousUsersAreBlocked() + { + // Arrange + var server = TestServer.Create(_services, _app); + var client = server.CreateClient(); + + // Act + var response = await client.GetAsync("http://localhost/Anonymous/GetHelloWorld"); + + // Assert + Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); + } + + [Fact] + public async Task CanAuthorizeParticularUsers() + { + // Arrange + var server = TestServer.Create(_services, _app); + var client = server.CreateClient(); + + // Act + var response = await client.GetAsync("http://localhost/AuthorizeUser/ReturnHelloWorldOnlyForAuthorizedUser"); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal("Hello World!", await response.Content.ReadAsStringAsync()); + } + + [Fact] + public async Task ExceptionFilterHandlesAnException() + { + // Arrange + var server = TestServer.Create(_services, _app); + var client = server.CreateClient(); + + // 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()); + } + + [Fact] + public async Task ServiceFilterUsesRegisteredServicesAsFilter() + { + // Arrange + var server = TestServer.Create(_services, _app); + var client = server.CreateClient(); + + // 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 server = TestServer.Create(_services, _app); + var client = server.CreateClient(); + var url = "http://localhost/RandomNumber/GetAuthorizedRandomNumber"; + + // Act & Assert + await Assert.ThrowsAsync(() => client.GetAsync(url)); + } + + [Fact] + public async Task TypeFilterInitializesArguments() + { + // Arrange + var server = TestServer.Create(_services, _app); + var client = server.CreateClient(); + 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 server = TestServer.Create(_services, _app); + var client = server.CreateClient(); + var url = "http://localhost/RandomNumber/GetHalfOfModifiedRandomNumber?randomNumber=3"; + + // Act & Assert + await Assert.ThrowsAsync(() => client.GetAsync(url)); + } + + [Fact] + public async Task ActionFilterOverridesActionExecuted() + { + // Arrange + var server = TestServer.Create(_services, _app); + var client = server.CreateClient(); + + // Act + var response = await client.GetAsync("http://localhost/XmlSerializer/GetDummyClass?sampleInput=10"); + + //Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal("10", + await response.Content.ReadAsStringAsync()); + } + + [Fact] + public async Task ResultFilterOverridesOnResultExecuting() + { + // Arrange + var server = TestServer.Create(_services, _app); + var client = server.CreateClient(); + + // Act + var response = await client.GetAsync("http://localhost/DummyClass/GetDummyClass"); + + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal("120", + await response.Content.ReadAsStringAsync()); + } + + [Fact] + public async Task ResultFilterOverridesOnResultExecuted() + { + // Arrange + var server = TestServer.Create(_services, _app); + var client = server.CreateClient(); + + // 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); + } } } \ No newline at end of file diff --git a/test/WebSites/FiltersWebSite/Controllers/AnonymousController.cs b/test/WebSites/FiltersWebSite/Controllers/AnonymousController.cs new file mode 100644 index 0000000000..f6469f8ba1 --- /dev/null +++ b/test/WebSites/FiltersWebSite/Controllers/AnonymousController.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.Mvc; + +namespace FiltersWebSite +{ + [BlockAnonymous] + public class AnonymousController : Controller + { + public string GetHelloWorld() + { + return "Hello World!"; + } + } +} \ No newline at end of file diff --git a/test/WebSites/FiltersWebSite/Controllers/AuthorizeUserController.cs b/test/WebSites/FiltersWebSite/Controllers/AuthorizeUserController.cs new file mode 100644 index 0000000000..637d6a0301 --- /dev/null +++ b/test/WebSites/FiltersWebSite/Controllers/AuthorizeUserController.cs @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.Mvc; + +namespace FiltersWebSite +{ + [AuthorizeUser] + public class AuthorizeUserController : Controller + { + [Authorize("Permission", "CanViewPage")] + public string ReturnHelloWorldOnlyForAuthorizedUser() + { + return "Hello World!"; + } + } +} \ No newline at end of file diff --git a/test/WebSites/FiltersWebSite/Controllers/DummyClassController.cs b/test/WebSites/FiltersWebSite/Controllers/DummyClassController.cs new file mode 100644 index 0000000000..4ba63649a1 --- /dev/null +++ b/test/WebSites/FiltersWebSite/Controllers/DummyClassController.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Open Technologies, Inc. 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.AspNet.Mvc; + +namespace FiltersWebSite +{ + public class DummyClassController : Controller + { + [ModifyResultsFilter] + public DummyClass GetDummyClass() + { + return new DummyClass() + { + SampleInt = 10 + }; + } + + [AddHeader] + public IActionResult GetEmptyActionResult() + { + return new TestActionResult(); + } + } + + public class TestActionResult : IActionResult + { + public Task ExecuteResultAsync(ActionContext context) + { + return Task.FromResult(true); + } + } +} \ No newline at end of file diff --git a/test/WebSites/FiltersWebSite/Controllers/ExceptionController.cs b/test/WebSites/FiltersWebSite/Controllers/ExceptionController.cs new file mode 100644 index 0000000000..54ba1ba4e5 --- /dev/null +++ b/test/WebSites/FiltersWebSite/Controllers/ExceptionController.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Open Technologies, Inc. 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.AspNet.Mvc; + +namespace FiltersWebSite +{ + public class ExceptionController : Controller + { + public string GetError(string error) + { + throw new InvalidOperationException(error); + } + } +} \ No newline at end of file diff --git a/test/WebSites/FiltersWebSite/Controllers/RandomNumberController.cs b/test/WebSites/FiltersWebSite/Controllers/RandomNumberController.cs new file mode 100644 index 0000000000..af56b58328 --- /dev/null +++ b/test/WebSites/FiltersWebSite/Controllers/RandomNumberController.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.Mvc; + +namespace FiltersWebSite +{ + 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; + } + } +} \ No newline at end of file diff --git a/test/WebSites/FiltersWebSite/Controllers/XmlSerializerController.cs b/test/WebSites/FiltersWebSite/Controllers/XmlSerializerController.cs new file mode 100644 index 0000000000..d99e417e22 --- /dev/null +++ b/test/WebSites/FiltersWebSite/Controllers/XmlSerializerController.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.Mvc; + +namespace FiltersWebSite +{ + [SerializationActionFilter] + public class XmlSerializerController : Controller + { + public DummyClass GetDummyClass(int sampleInput) + { + return new DummyClass { SampleInt = sampleInput }; + } + } +} \ No newline at end of file diff --git a/test/WebSites/FiltersWebSite/Filters/AddHeaderAttribute.cs b/test/WebSites/FiltersWebSite/Filters/AddHeaderAttribute.cs new file mode 100644 index 0000000000..8032f57565 --- /dev/null +++ b/test/WebSites/FiltersWebSite/Filters/AddHeaderAttribute.cs @@ -0,0 +1,19 @@ +// Copyright(c) Microsoft Open Technologies, Inc.All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Text; +using Microsoft.AspNet.Mvc; + +namespace FiltersWebSite +{ + public class AddHeaderAttribute : ResultFilterAttribute + { + public override void OnResultExecuted(ResultExecutedContext context) + { + context.HttpContext.Response.Headers.Add( + "OnResultExecuted", new string[] { "ResultExecutedSuccessfully" }); + + base.OnResultExecuted(context); + } + } +} \ No newline at end of file diff --git a/test/WebSites/FiltersWebSite/Filters/AuthorizeUserAttribute.cs b/test/WebSites/FiltersWebSite/Filters/AuthorizeUserAttribute.cs new file mode 100644 index 0000000000..3c374fe648 --- /dev/null +++ b/test/WebSites/FiltersWebSite/Filters/AuthorizeUserAttribute.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.Mvc; +using System.Security.Claims; + +namespace FiltersWebSite +{ + public class AuthorizeUserAttribute : AuthorizationFilterAttribute + { + public override void OnAuthorization(AuthorizationContext context) + { + context.HttpContext.User = new ClaimsPrincipal( + new ClaimsIdentity( + new Claim[] { + new Claim("Permission", "CanViewPage"), + new Claim(ClaimTypes.Role, "Administrator"), + new Claim(ClaimTypes.NameIdentifier, "John")}, + "Basic")); + } + } +} diff --git a/test/WebSites/FiltersWebSite/Filters/BlockAnonymous.cs b/test/WebSites/FiltersWebSite/Filters/BlockAnonymous.cs new file mode 100644 index 0000000000..e07f191e6e --- /dev/null +++ b/test/WebSites/FiltersWebSite/Filters/BlockAnonymous.cs @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.Mvc; + +namespace FiltersWebSite +{ + public class BlockAnonymous : AuthorizationFilterAttribute + { + public override void OnAuthorization(AuthorizationContext context) + { + if (!HasAllowAnonymous(context)) + { + var user = context.HttpContext.User; + var userIsAnonymous = + user == null || + user.Identity == null || + !user.Identity.IsAuthenticated; + + if (userIsAnonymous) + { + base.Fail(context); + } + } + } + } +} \ No newline at end of file diff --git a/test/WebSites/FiltersWebSite/Filters/FakeRandomNumberProvider.cs b/test/WebSites/FiltersWebSite/Filters/FakeRandomNumberProvider.cs new file mode 100644 index 0000000000..1d54a2660e --- /dev/null +++ b/test/WebSites/FiltersWebSite/Filters/FakeRandomNumberProvider.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.Mvc; + +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; + } + } +} \ No newline at end of file diff --git a/test/WebSites/FiltersWebSite/Filters/ModifyResultsFilterAttribute.cs b/test/WebSites/FiltersWebSite/Filters/ModifyResultsFilterAttribute.cs new file mode 100644 index 0000000000..04323a7c5a --- /dev/null +++ b/test/WebSites/FiltersWebSite/Filters/ModifyResultsFilterAttribute.cs @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.Mvc; + +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); + } + } +} \ No newline at end of file diff --git a/test/WebSites/FiltersWebSite/Filters/RandomNumberFilter.cs b/test/WebSites/FiltersWebSite/Filters/RandomNumberFilter.cs new file mode 100644 index 0000000000..2a6f6009dd --- /dev/null +++ b/test/WebSites/FiltersWebSite/Filters/RandomNumberFilter.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.Mvc; + +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) + { + } + } +} \ No newline at end of file diff --git a/test/WebSites/FiltersWebSite/Filters/RandomNumberProvider.cs b/test/WebSites/FiltersWebSite/Filters/RandomNumberProvider.cs new file mode 100644 index 0000000000..8979f03d59 --- /dev/null +++ b/test/WebSites/FiltersWebSite/Filters/RandomNumberProvider.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.Mvc; + +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(); + } + } +} \ No newline at end of file diff --git a/test/WebSites/FiltersWebSite/Filters/SerializationActionFilterAttribute.cs b/test/WebSites/FiltersWebSite/Filters/SerializationActionFilterAttribute.cs new file mode 100644 index 0000000000..5a3c67dbc9 --- /dev/null +++ b/test/WebSites/FiltersWebSite/Filters/SerializationActionFilterAttribute.cs @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNet.Mvc; + +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); + } + } +} \ No newline at end of file diff --git a/test/WebSites/FiltersWebSite/Models/DummyClass.cs b/test/WebSites/FiltersWebSite/Models/DummyClass.cs new file mode 100644 index 0000000000..fc8f7c2ff3 --- /dev/null +++ b/test/WebSites/FiltersWebSite/Models/DummyClass.cs @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Open Technologies, Inc. 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; } + } +} \ No newline at end of file diff --git a/test/WebSites/FiltersWebSite/Services/DummyService.cs b/test/WebSites/FiltersWebSite/Services/DummyService.cs new file mode 100644 index 0000000000..27e3e59961 --- /dev/null +++ b/test/WebSites/FiltersWebSite/Services/DummyService.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Open Technologies, Inc. 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; + } + } + } +} \ No newline at end of file diff --git a/test/WebSites/FiltersWebSite/Services/RandomNumberService.cs b/test/WebSites/FiltersWebSite/Services/RandomNumberService.cs new file mode 100644 index 0000000000..d6dd15f228 --- /dev/null +++ b/test/WebSites/FiltersWebSite/Services/RandomNumberService.cs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Open Technologies, Inc. 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; + } + } +} \ No newline at end of file diff --git a/test/WebSites/FiltersWebSite/Startup.cs b/test/WebSites/FiltersWebSite/Startup.cs index 29cf03c2ad..90a39ef075 100644 --- a/test/WebSites/FiltersWebSite/Startup.cs +++ b/test/WebSites/FiltersWebSite/Startup.cs @@ -18,6 +18,8 @@ namespace FiltersWebSite app.UseServices(services => { services.AddMvc(configuration); + services.AddSingleton(); + services.AddSingleton(); services.Configure(options => {