From c56b64fc41ab4bff02e0843805a98a46612d8df4 Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Thu, 13 Apr 2017 14:26:56 -0700 Subject: [PATCH] Add factory methods --- .../Internal/RedirectToPageResultExecutor.cs | 14 +- .../Page.cs | 889 +++++++++- .../PageModel.cs | 907 ++++++++++- .../RedirectToPageResult.cs | 54 +- .../PageModelTest.cs | 1417 ++++++++++++++++ .../PageTest.cs | 1431 ++++++++++++++++- 6 files changed, 4698 insertions(+), 14 deletions(-) diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/RedirectToPageResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/RedirectToPageResultExecutor.cs index 8a7494cdb9..8ff19456af 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/RedirectToPageResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/Internal/RedirectToPageResultExecutor.cs @@ -2,8 +2,10 @@ // 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.Routing; using Microsoft.Extensions.Logging; +using Microsoft.Net.Http.Headers; namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal { @@ -44,7 +46,17 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal } _logger.RedirectToPageResultExecuting(result.PageName); - context.HttpContext.Response.Redirect(destinationUrl, result.Permanent); + + if (result.PreserveMethod) + { + context.HttpContext.Response.StatusCode = result.Permanent ? + StatusCodes.Status308PermanentRedirect : StatusCodes.Status307TemporaryRedirect; + context.HttpContext.Response.Headers[HeaderNames.Location] = destinationUrl; + } + else + { + context.HttpContext.Response.Redirect(destinationUrl, result.Permanent); + } } } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Page.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/Page.cs index aa00bf48c2..3ad708a7b1 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Page.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/Page.cs @@ -3,12 +3,17 @@ using System; using System.Diagnostics; +using System.IO; +using System.Security.Claims; +using System.Text; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Authentication; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Net.Http.Headers; namespace Microsoft.AspNetCore.Mvc.RazorPages { @@ -123,12 +128,348 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } } + #region Factory methods + /// + /// Creates a . + /// + /// The created for the response. + /// + /// The behavior of this method depends on the in use. + /// and + /// are among likely status results. + /// + public virtual ChallengeResult Challenge() + => new ChallengeResult(); + + /// + /// Creates a with the specified authentication schemes. + /// + /// The authentication schemes to challenge. + /// The created for the response. + /// + /// The behavior of this method depends on the in use. + /// and + /// are among likely status results. + /// + public virtual ChallengeResult Challenge(params string[] authenticationSchemes) + => new ChallengeResult(authenticationSchemes); + + /// + /// Creates a with the specified . + /// + /// used to perform the authentication + /// challenge. + /// The created for the response. + /// + /// The behavior of this method depends on the in use. + /// and + /// are among likely status results. + /// + public virtual ChallengeResult Challenge(AuthenticationProperties properties) + => new ChallengeResult(properties); + + /// + /// Creates a with the specified specified authentication schemes and + /// . + /// + /// used to perform the authentication + /// challenge. + /// The authentication schemes to challenge. + /// The created for the response. + /// + /// The behavior of this method depends on the in use. + /// and + /// are among likely status results. + /// + public virtual ChallengeResult Challenge( + AuthenticationProperties properties, + params string[] authenticationSchemes) + => new ChallengeResult(authenticationSchemes, properties); + + /// + /// Creates a object with by specifying a + /// string. + /// + /// The content to write to the response. + /// The created object for the response. + public virtual ContentResult Content(string content) + => Content(content, (MediaTypeHeaderValue)null); + + /// + /// Creates a object with by specifying a + /// string and a content type. + /// + /// The content to write to the response. + /// The content type (MIME type). + /// The created object for the response. + public virtual ContentResult Content(string content, string contentType) + => Content(content, MediaTypeHeaderValue.Parse(contentType)); + + /// + /// Creates a object with by specifying a + /// string, a , and . + /// + /// The content to write to the response. + /// The content type (MIME type). + /// The content encoding. + /// The created object for the response. + /// + /// If encoding is provided by both the 'charset' and the parameters, then + /// the parameter is chosen as the final encoding. + /// + public virtual ContentResult Content(string content, string contentType, Encoding contentEncoding) + { + var mediaTypeHeaderValue = MediaTypeHeaderValue.Parse(contentType); + mediaTypeHeaderValue.Encoding = contentEncoding ?? mediaTypeHeaderValue.Encoding; + return Content(content, mediaTypeHeaderValue); + } + + /// + /// Creates a object with by specifying a + /// string and a . + /// + /// The content to write to the response. + /// The content type (MIME type). + /// The created object for the response. + public virtual ContentResult Content(string content, MediaTypeHeaderValue contentType) + { + return new ContentResult + { + Content = content, + ContentType = contentType?.ToString() + }; + } + + /// + /// Creates a ( by default). + /// + /// The created for the response. + /// + /// Some authentication schemes, such as cookies, will convert to + /// a redirect to show a login page. + /// + public virtual ForbidResult Forbid() + => new ForbidResult(); + + /// + /// Creates a ( by default) with the + /// specified authentication schemes. + /// + /// The authentication schemes to challenge. + /// The created for the response. + /// + /// Some authentication schemes, such as cookies, will convert to + /// a redirect to show a login page. + /// + public virtual ForbidResult Forbid(params string[] authenticationSchemes) + => new ForbidResult(authenticationSchemes); + + /// + /// Creates a ( by default) with the + /// specified . + /// + /// used to perform the authentication + /// challenge. + /// The created for the response. + /// + /// Some authentication schemes, such as cookies, will convert to + /// a redirect to show a login page. + /// + public virtual ForbidResult Forbid(AuthenticationProperties properties) + => new ForbidResult(properties); + + /// + /// Creates a ( by default) with the + /// specified specified authentication schemes and . + /// + /// used to perform the authentication + /// challenge. + /// The authentication schemes to challenge. + /// The created for the response. + /// + /// Some authentication schemes, such as cookies, will convert to + /// a redirect to show a login page. + /// + public virtual ForbidResult Forbid(AuthenticationProperties properties, params string[] authenticationSchemes) + => new ForbidResult(authenticationSchemes, properties); + + /// + /// Returns a file with the specified as content + /// () and the specified as the Content-Type. + /// + /// The file contents. + /// The Content-Type of the file. + /// The created for the response. + public virtual FileContentResult File(byte[] fileContents, string contentType) + => File(fileContents, contentType, fileDownloadName: null); + + /// + /// Returns a file with the specified as content (), the + /// specified as the Content-Type and the + /// specified as the suggested file name. + /// + /// The file contents. + /// The Content-Type of the file. + /// The suggested file name. + /// The created for the response. + public virtual FileContentResult File(byte[] fileContents, string contentType, string fileDownloadName) + => new FileContentResult(fileContents, contentType) { FileDownloadName = fileDownloadName }; + + /// + /// Returns a file in the specified () + /// with the specified as the Content-Type. + /// + /// The with the contents of the file. + /// The Content-Type of the file. + /// The created for the response. + public virtual FileStreamResult File(Stream fileStream, string contentType) + => File(fileStream, contentType, fileDownloadName: null); + + /// + /// Returns a file in the specified () with the + /// specified as the Content-Type and the + /// specified as the suggested file name. + /// + /// The with the contents of the file. + /// The Content-Type of the file. + /// The suggested file name. + /// The created for the response. + public virtual FileStreamResult File(Stream fileStream, string contentType, string fileDownloadName) + => new FileStreamResult(fileStream, contentType) { FileDownloadName = fileDownloadName }; + + /// + /// Returns the file specified by () with the + /// specified as the Content-Type. + /// + /// The virtual path of the file to be returned. + /// The Content-Type of the file. + /// The created for the response. + public virtual VirtualFileResult File(string virtualPath, string contentType) + => File(virtualPath, contentType, fileDownloadName: null); + + /// + /// Returns the file specified by () with the + /// specified as the Content-Type and the + /// specified as the suggested file name. + /// + /// The virtual path of the file to be returned. + /// The Content-Type of the file. + /// The suggested file name. + /// The created for the response. + public virtual VirtualFileResult File(string virtualPath, string contentType, string fileDownloadName) + => new VirtualFileResult(virtualPath, contentType) { FileDownloadName = fileDownloadName }; + + /// + /// Returns the file specified by () with the + /// specified as the Content-Type. + /// + /// The physical path of the file to be returned. + /// The Content-Type of the file. + /// The created for the response. + public virtual PhysicalFileResult PhysicalFile(string physicalPath, string contentType) + => PhysicalFile(physicalPath, contentType, fileDownloadName: null); + + /// + /// Returns the file specified by () with the + /// specified as the Content-Type and the + /// specified as the suggested file name. + /// + /// The physical path of the file to be returned. + /// The Content-Type of the file. + /// The suggested file name. + /// The created for the response. + public virtual PhysicalFileResult PhysicalFile( + string physicalPath, + string contentType, + string fileDownloadName) + => new PhysicalFileResult(physicalPath, contentType) { FileDownloadName = fileDownloadName }; + + /// + /// Creates a object that redirects + /// () to the specified local . + /// + /// The local URL to redirect to. + /// The created for the response. + public virtual LocalRedirectResult LocalRedirect(string localUrl) + { + if (string.IsNullOrEmpty(localUrl)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(localUrl)); + } + + return new LocalRedirectResult(localUrl); + } + + /// + /// Creates a object with set to + /// true () using the specified . + /// + /// The local URL to redirect to. + /// The created for the response. + public virtual LocalRedirectResult LocalRedirectPermanent(string localUrl) + { + if (string.IsNullOrEmpty(localUrl)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(localUrl)); + } + + return new LocalRedirectResult(localUrl, permanent: true); + } + + /// + /// Creates a object with set to + /// false and set to true + /// () using the specified . + /// + /// The local URL to redirect to. + /// The created for the response. + public virtual LocalRedirectResult LocalRedirectPreserveMethod(string localUrl) + { + if (string.IsNullOrEmpty(localUrl)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(localUrl)); + } + + return new LocalRedirectResult(localUrl: localUrl, permanent: false, preserveMethod: true); + } + + /// + /// Creates a object with set to + /// true and set to true + /// () using the specified . + /// + /// The local URL to redirect to. + /// The created for the response. + public virtual LocalRedirectResult LocalRedirectPermanentPreserveMethod(string localUrl) + { + if (string.IsNullOrEmpty(localUrl)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(localUrl)); + } + + return new LocalRedirectResult(localUrl: localUrl, permanent: true, preserveMethod: true); + } + + /// + /// Creates an that produces a response. + /// + /// The created for the response. + public virtual NotFoundResult NotFound() + => new NotFoundResult(); + + /// + /// Creates an that produces a response. + /// + /// The created for the response. + public virtual NotFoundObjectResult NotFound(object value) + => new NotFoundObjectResult(value); + /// /// Creates a object that redirects to the specified . /// /// The URL to redirect to. /// The created for the response. - protected RedirectResult Redirect(string url) + public virtual RedirectResult Redirect(string url) { if (string.IsNullOrEmpty(url)) { @@ -138,6 +479,442 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages return new RedirectResult(url); } + /// + /// Creates a object with set to true + /// () using the specified . + /// + /// The URL to redirect to. + /// The created for the response. + public virtual RedirectResult RedirectPermanent(string url) + { + if (string.IsNullOrEmpty(url)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(url)); + } + + return new RedirectResult(url, permanent: true); + } + + /// + /// Creates a object with set to false + /// and set to true () + /// using the specified . + /// + /// The URL to redirect to. + /// The created for the response. + public virtual RedirectResult RedirectPreserveMethod(string url) + { + if (string.IsNullOrEmpty(url)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(url)); + } + + return new RedirectResult(url: url, permanent: false, preserveMethod: true); + } + + /// + /// Creates a object with set to true + /// and set to true () + /// using the specified . + /// + /// The URL to redirect to. + /// The created for the response. + public virtual RedirectResult RedirectPermanentPreserveMethod(string url) + { + if (string.IsNullOrEmpty(url)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(url)); + } + + return new RedirectResult(url: url, permanent: true, preserveMethod: true); + } + + /// + /// Redirects () to the specified action using the . + /// + /// The name of the action. + /// The created for the response. + public virtual RedirectToActionResult RedirectToAction(string actionName) + => RedirectToAction(actionName, routeValues: null); + + /// + /// Redirects () to the specified action using the + /// and . + /// + /// The name of the action. + /// The parameters for a route. + /// The created for the response. + public virtual RedirectToActionResult RedirectToAction(string actionName, object routeValues) + => RedirectToAction(actionName, controllerName: null, routeValues: routeValues); + + /// + /// Redirects () to the specified action using the + /// and the . + /// + /// The name of the action. + /// The name of the controller. + /// The created for the response. + public virtual RedirectToActionResult RedirectToAction(string actionName, string controllerName) + => RedirectToAction(actionName, controllerName, routeValues: null); + + /// + /// Redirects () to the specified action using the specified + /// , , and . + /// + /// The name of the action. + /// The name of the controller. + /// The parameters for a route. + /// The created for the response. + public virtual RedirectToActionResult RedirectToAction( + string actionName, + string controllerName, + object routeValues) + => RedirectToAction(actionName, controllerName, routeValues, fragment: null); + + /// + /// Redirects () to the specified action using the specified + /// , , and . + /// + /// The name of the action. + /// The name of the controller. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToActionResult RedirectToAction( + string actionName, + string controllerName, + string fragment) + => RedirectToAction(actionName, controllerName, routeValues: null, fragment: fragment); + + /// + /// Redirects () to the specified action using the specified , + /// , , and . + /// + /// The name of the action. + /// The name of the controller. + /// The parameters for a route. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToActionResult RedirectToAction( + string actionName, + string controllerName, + object routeValues, + string fragment) + => new RedirectToActionResult(actionName, controllerName, routeValues, fragment); + + /// + /// Redirects () to the specified action with + /// set to false and + /// set to true, using the specified , , + /// , and . + /// + /// The name of the action. + /// The name of the controller. + /// The route data to use for generating the URL. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToActionResult RedirectToActionPreserveMethod( + string actionName = null, + string controllerName = null, + object routeValues = null, + string fragment = null) + { + return new RedirectToActionResult( + actionName: actionName, + controllerName: controllerName, + routeValues: routeValues, + permanent: false, + preserveMethod: true, + fragment: fragment); + } + + /// + /// Redirects () to the specified action with + /// set to true using the specified . + /// + /// The name of the action. + /// The created for the response. + public virtual RedirectToActionResult RedirectToActionPermanent(string actionName) + { + return RedirectToActionPermanent(actionName, routeValues: null); + } + + /// + /// Redirects () to the specified action with + /// set to true using the specified + /// and . + /// + /// The name of the action. + /// The parameters for a route. + /// The created for the response. + public virtual RedirectToActionResult RedirectToActionPermanent(string actionName, object routeValues) + { + return RedirectToActionPermanent(actionName, controllerName: null, routeValues: routeValues); + } + + /// + /// Redirects () to the specified action with + /// set to true using the specified + /// and . + /// + /// The name of the action. + /// The name of the controller. + /// The created for the response. + public virtual RedirectToActionResult RedirectToActionPermanent(string actionName, string controllerName) + { + return RedirectToActionPermanent(actionName, controllerName, routeValues: null); + } + + /// + /// Redirects () to the specified action with + /// set to true using the specified , + /// , and . + /// + /// The name of the action. + /// The name of the controller. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToActionResult RedirectToActionPermanent( + string actionName, + string controllerName, + string fragment) + { + return RedirectToActionPermanent(actionName, controllerName, routeValues: null, fragment: fragment); + } + + /// + /// Redirects () to the specified action with + /// set to true using the specified , + /// , and . + /// + /// The name of the action. + /// The name of the controller. + /// The parameters for a route. + /// The created for the response. + public virtual RedirectToActionResult RedirectToActionPermanent( + string actionName, + string controllerName, + object routeValues) + { + return RedirectToActionPermanent(actionName, controllerName, routeValues, fragment: null); + } + + /// + /// Redirects () to the specified action with + /// set to true using the specified , + /// , , and . + /// + /// The name of the action. + /// The name of the controller. + /// The parameters for a route. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToActionResult RedirectToActionPermanent( + string actionName, + string controllerName, + object routeValues, + string fragment) + { + return new RedirectToActionResult( + actionName, + controllerName, + routeValues, + permanent: true, + fragment: fragment); + } + + /// + /// Redirects () to the specified action with + /// set to true and + /// set to true, using the specified , , + /// , and . + /// + /// The name of the action. + /// The name of the controller. + /// The route data to use for generating the URL. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToActionResult RedirectToActionPermanentPreserveMethod( + string actionName = null, + string controllerName = null, + object routeValues = null, + string fragment = null) + { + return new RedirectToActionResult( + actionName: actionName, + controllerName: controllerName, + routeValues: routeValues, + permanent: true, + preserveMethod: true, + fragment: fragment); + } + + /// + /// Redirects () to the specified route using the specified . + /// + /// The name of the route. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoute(string routeName) + { + return RedirectToRoute(routeName, routeValues: null); + } + + /// + /// Redirects () to the specified route using the specified . + /// + /// The parameters for a route. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoute(object routeValues) + { + return RedirectToRoute(routeName: null, routeValues: routeValues); + } + + /// + /// Redirects () to the specified route using the specified + /// and . + /// + /// The name of the route. + /// The parameters for a route. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoute(string routeName, object routeValues) + { + return RedirectToRoute(routeName, routeValues, fragment: null); + } + + /// + /// Redirects () to the specified route using the specified + /// and . + /// + /// The name of the route. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoute(string routeName, string fragment) + { + return RedirectToRoute(routeName, routeValues: null, fragment: fragment); + } + + /// + /// Redirects () to the specified route using the specified + /// , , and . + /// + /// The name of the route. + /// The parameters for a route. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoute( + string routeName, + object routeValues, + string fragment) + { + return new RedirectToRouteResult(routeName, routeValues, fragment); + } + + /// + /// Redirects () to the specified route with + /// set to false and + /// set to true, using the specified , , and . + /// + /// The name of the route. + /// The route data to use for generating the URL. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoutePreserveMethod( + string routeName = null, + object routeValues = null, + string fragment = null) + { + return new RedirectToRouteResult( + routeName: routeName, + routeValues: routeValues, + permanent: false, + preserveMethod: true, + fragment: fragment); + } + + /// + /// Redirects () to the specified route with + /// set to true using the specified . + /// + /// The name of the route. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoutePermanent(string routeName) + { + return RedirectToRoutePermanent(routeName, routeValues: null); + } + + /// + /// Redirects () to the specified route with + /// set to true using the specified . + /// + /// The parameters for a route. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoutePermanent(object routeValues) + { + return RedirectToRoutePermanent(routeName: null, routeValues: routeValues); + } + + /// + /// Redirects () to the specified route with + /// set to true using the specified + /// and . + /// + /// The name of the route. + /// The parameters for a route. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoutePermanent(string routeName, object routeValues) + { + return RedirectToRoutePermanent(routeName, routeValues, fragment: null); + } + + /// + /// Redirects () to the specified route with + /// set to true using the specified + /// and . + /// + /// The name of the route. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoutePermanent(string routeName, string fragment) + { + return RedirectToRoutePermanent(routeName, routeValues: null, fragment: fragment); + } + + /// + /// Redirects () to the specified route with + /// set to true using the specified , + /// , and . + /// + /// The name of the route. + /// The parameters for a route. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoutePermanent( + string routeName, + object routeValues, + string fragment) + => new RedirectToRouteResult(routeName, routeValues, permanent: true, fragment: fragment); + + /// + /// Redirects () to the specified route with + /// set to true and + /// set to true, using the specified , , and . + /// + /// The name of the route. + /// The route data to use for generating the URL. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoutePermanentPreserveMethod( + string routeName = null, + object routeValues = null, + string fragment = null) + { + return new RedirectToRouteResult( + routeName: routeName, + routeValues: routeValues, + permanent: true, + preserveMethod: true, + fragment: fragment); + } + /// /// Redirects () to the current page. /// @@ -231,6 +1008,115 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages protected RedirectToPageResult RedirectToPagePermanent(string pageName, object routeValues, string fragment) => new RedirectToPageResult(pageName, routeValues, permanent: true, fragment: fragment); + /// + /// Redirects () to the specified page with + /// set to false and + /// set to true, using the specified , , and . + /// + /// The name of the page. + /// The route data to use for generating the URL. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToPageResult RedirectToPagePreserveMethod( + string pageName = null, + object routeValues = null, + string fragment = null) + { + return new RedirectToPageResult( + pageName: pageName, + routeValues: routeValues, + permanent: false, + preserveMethod: true, + fragment: fragment); + } + + /// + /// Redirects () to the specified route with + /// set to true and + /// set to true, using the specified , , and . + /// + /// The name of the page. + /// The route data to use for generating the URL. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToPageResult RedirectToPagePermanentPreserveMethod( + string pageName = null, + object routeValues = null, + string fragment = null) + { + return new RedirectToPageResult( + pageName: pageName, + routeValues: routeValues, + permanent: true, + preserveMethod: true, + fragment: fragment); + } + + /// + /// Creates a with the specified authentication scheme. + /// + /// The containing the user claims. + /// The authentication scheme to use for the sign-in operation. + /// The created for the response. + public virtual SignInResult SignIn(ClaimsPrincipal principal, string authenticationScheme) + => new SignInResult(authenticationScheme, principal); + + /// + /// Creates a with the specified specified authentication scheme and + /// . + /// + /// The containing the user claims. + /// used to perform the sign-in operation. + /// The authentication scheme to use for the sign-in operation. + /// The created for the response. + public virtual SignInResult SignIn( + ClaimsPrincipal principal, + AuthenticationProperties properties, + string authenticationScheme) + => new SignInResult(authenticationScheme, principal, properties); + + /// + /// Creates a with the specified authentication schemes. + /// + /// The authentication schemes to use for the sign-out operation. + /// The created for the response. + public virtual SignOutResult SignOut(params string[] authenticationSchemes) + => new SignOutResult(authenticationSchemes); + + /// + /// Creates a with the specified specified authentication schemes and + /// . + /// + /// used to perform the sign-out operation. + /// The authentication scheme to use for the sign-out operation. + /// The created for the response. + public virtual SignOutResult SignOut(AuthenticationProperties properties, params string[] authenticationSchemes) + => new SignOutResult(authenticationSchemes, properties); + + /// + /// Creates a object by specifying a . + /// + /// The status code to set on the response. + /// The created object for the response. + public virtual StatusCodeResult StatusCode(int statusCode) + => new StatusCodeResult(statusCode); + + /// + /// Creates a object by specifying a and + /// + /// The status code to set on the response. + /// The value to set on the . + /// The created object for the response. + public virtual ObjectResult StatusCode(int statusCode, object value) + => new ObjectResult(value) { StatusCode = statusCode }; + + /// + /// Creates an that produces an response. + /// + /// The created for the response. + public virtual UnauthorizedResult Unauthorized() + => new UnauthorizedResult(); + /// /// Creates a object that renders this page as a view to the response. /// @@ -243,5 +1129,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages { return new PageViewResult(this); } + #endregion Factory methods } } diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/PageModel.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/PageModel.cs index 2fbe594945..dc8ab8b044 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/PageModel.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/PageModel.cs @@ -2,14 +2,19 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.IO; +using System.Security.Claims; +using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Authentication; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure; using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Net.Http.Headers; namespace Microsoft.AspNetCore.Mvc.RazorPages { @@ -141,7 +146,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } /// - /// Updates the specified instance using values from the controller's current + /// Updates the specified instance using values from the pageModel's current /// . /// /// The type of the model object. @@ -153,7 +158,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages } /// - /// Updates the specified instance using values from the controller's current + /// Updates the specified instance using values from the pageModel's current /// . /// /// The type of the model object. @@ -165,6 +170,342 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages return Binder.TryUpdateModelAsync(PageContext, model, name); } + #region Factory methods + /// + /// Creates a . + /// + /// The created for the response. + /// + /// The behavior of this method depends on the in use. + /// and + /// are among likely status results. + /// + public virtual ChallengeResult Challenge() + => new ChallengeResult(); + + /// + /// Creates a with the specified authentication schemes. + /// + /// The authentication schemes to challenge. + /// The created for the response. + /// + /// The behavior of this method depends on the in use. + /// and + /// are among likely status results. + /// + public virtual ChallengeResult Challenge(params string[] authenticationSchemes) + => new ChallengeResult(authenticationSchemes); + + /// + /// Creates a with the specified . + /// + /// used to perform the authentication + /// challenge. + /// The created for the response. + /// + /// The behavior of this method depends on the in use. + /// and + /// are among likely status results. + /// + public virtual ChallengeResult Challenge(AuthenticationProperties properties) + => new ChallengeResult(properties); + + /// + /// Creates a with the specified specified authentication schemes and + /// . + /// + /// used to perform the authentication + /// challenge. + /// The authentication schemes to challenge. + /// The created for the response. + /// + /// The behavior of this method depends on the in use. + /// and + /// are among likely status results. + /// + public virtual ChallengeResult Challenge( + AuthenticationProperties properties, + params string[] authenticationSchemes) + => new ChallengeResult(authenticationSchemes, properties); + + /// + /// Creates a object with by specifying a + /// string. + /// + /// The content to write to the response. + /// The created object for the response. + public virtual ContentResult Content(string content) + => Content(content, (MediaTypeHeaderValue)null); + + /// + /// Creates a object with by specifying a + /// string and a content type. + /// + /// The content to write to the response. + /// The content type (MIME type). + /// The created object for the response. + public virtual ContentResult Content(string content, string contentType) + => Content(content, MediaTypeHeaderValue.Parse(contentType)); + + /// + /// Creates a object with by specifying a + /// string, a , and . + /// + /// The content to write to the response. + /// The content type (MIME type). + /// The content encoding. + /// The created object for the response. + /// + /// If encoding is provided by both the 'charset' and the parameters, then + /// the parameter is chosen as the final encoding. + /// + public virtual ContentResult Content(string content, string contentType, Encoding contentEncoding) + { + var mediaTypeHeaderValue = MediaTypeHeaderValue.Parse(contentType); + mediaTypeHeaderValue.Encoding = contentEncoding ?? mediaTypeHeaderValue.Encoding; + return Content(content, mediaTypeHeaderValue); + } + + /// + /// Creates a object with by specifying a + /// string and a . + /// + /// The content to write to the response. + /// The content type (MIME type). + /// The created object for the response. + public virtual ContentResult Content(string content, MediaTypeHeaderValue contentType) + { + return new ContentResult + { + Content = content, + ContentType = contentType?.ToString() + }; + } + + /// + /// Creates a ( by default). + /// + /// The created for the response. + /// + /// Some authentication schemes, such as cookies, will convert to + /// a redirect to show a login page. + /// + public virtual ForbidResult Forbid() + => new ForbidResult(); + + /// + /// Creates a ( by default) with the + /// specified authentication schemes. + /// + /// The authentication schemes to challenge. + /// The created for the response. + /// + /// Some authentication schemes, such as cookies, will convert to + /// a redirect to show a login page. + /// + public virtual ForbidResult Forbid(params string[] authenticationSchemes) + => new ForbidResult(authenticationSchemes); + + /// + /// Creates a ( by default) with the + /// specified . + /// + /// used to perform the authentication + /// challenge. + /// The created for the response. + /// + /// Some authentication schemes, such as cookies, will convert to + /// a redirect to show a login page. + /// + public virtual ForbidResult Forbid(AuthenticationProperties properties) + => new ForbidResult(properties); + + /// + /// Creates a ( by default) with the + /// specified specified authentication schemes and . + /// + /// used to perform the authentication + /// challenge. + /// The authentication schemes to challenge. + /// The created for the response. + /// + /// Some authentication schemes, such as cookies, will convert to + /// a redirect to show a login page. + /// + public virtual ForbidResult Forbid(AuthenticationProperties properties, params string[] authenticationSchemes) + => new ForbidResult(authenticationSchemes, properties); + + /// + /// Returns a file with the specified as content + /// () and the specified as the Content-Type. + /// + /// The file contents. + /// The Content-Type of the file. + /// The created for the response. + public virtual FileContentResult File(byte[] fileContents, string contentType) + => File(fileContents, contentType, fileDownloadName: null); + + /// + /// Returns a file with the specified as content (), the + /// specified as the Content-Type and the + /// specified as the suggested file name. + /// + /// The file contents. + /// The Content-Type of the file. + /// The suggested file name. + /// The created for the response. + public virtual FileContentResult File(byte[] fileContents, string contentType, string fileDownloadName) + => new FileContentResult(fileContents, contentType) { FileDownloadName = fileDownloadName }; + + /// + /// Returns a file in the specified () + /// with the specified as the Content-Type. + /// + /// The with the contents of the file. + /// The Content-Type of the file. + /// The created for the response. + public virtual FileStreamResult File(Stream fileStream, string contentType) + => File(fileStream, contentType, fileDownloadName: null); + + /// + /// Returns a file in the specified () with the + /// specified as the Content-Type and the + /// specified as the suggested file name. + /// + /// The with the contents of the file. + /// The Content-Type of the file. + /// The suggested file name. + /// The created for the response. + public virtual FileStreamResult File(Stream fileStream, string contentType, string fileDownloadName) + => new FileStreamResult(fileStream, contentType) { FileDownloadName = fileDownloadName }; + + /// + /// Returns the file specified by () with the + /// specified as the Content-Type. + /// + /// The virtual path of the file to be returned. + /// The Content-Type of the file. + /// The created for the response. + public virtual VirtualFileResult File(string virtualPath, string contentType) + => File(virtualPath, contentType, fileDownloadName: null); + + /// + /// Returns the file specified by () with the + /// specified as the Content-Type and the + /// specified as the suggested file name. + /// + /// The virtual path of the file to be returned. + /// The Content-Type of the file. + /// The suggested file name. + /// The created for the response. + public virtual VirtualFileResult File(string virtualPath, string contentType, string fileDownloadName) + => new VirtualFileResult(virtualPath, contentType) { FileDownloadName = fileDownloadName }; + + /// + /// Creates a object that redirects + /// () to the specified local . + /// + /// The local URL to redirect to. + /// The created for the response. + public virtual LocalRedirectResult LocalRedirect(string localUrl) + { + if (string.IsNullOrEmpty(localUrl)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(localUrl)); + } + + return new LocalRedirectResult(localUrl); + } + + /// + /// Creates a object with set to + /// true () using the specified . + /// + /// The local URL to redirect to. + /// The created for the response. + public virtual LocalRedirectResult LocalRedirectPermanent(string localUrl) + { + if (string.IsNullOrEmpty(localUrl)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(localUrl)); + } + + return new LocalRedirectResult(localUrl, permanent: true); + } + + /// + /// Creates a object with set to + /// false and set to true + /// () using the specified . + /// + /// The local URL to redirect to. + /// The created for the response. + public virtual LocalRedirectResult LocalRedirectPreserveMethod(string localUrl) + { + if (string.IsNullOrEmpty(localUrl)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(localUrl)); + } + + return new LocalRedirectResult(localUrl: localUrl, permanent: false, preserveMethod: true); + } + + /// + /// Creates a object with set to + /// true and set to true + /// () using the specified . + /// + /// The local URL to redirect to. + /// The created for the response. + public virtual LocalRedirectResult LocalRedirectPermanentPreserveMethod(string localUrl) + { + if (string.IsNullOrEmpty(localUrl)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(localUrl)); + } + + return new LocalRedirectResult(localUrl: localUrl, permanent: true, preserveMethod: true); + } + + /// + /// Creates an that produces a response. + /// + /// The created for the response. + public virtual NotFoundResult NotFound() + => new NotFoundResult(); + + /// + /// Creates an that produces a response. + /// + /// The created for the response. + public virtual NotFoundObjectResult NotFound(object value) + => new NotFoundObjectResult(value); + + /// + /// Returns the file specified by () with the + /// specified as the Content-Type. + /// + /// The physical path of the file to be returned. + /// The Content-Type of the file. + /// The created for the response. + public virtual PhysicalFileResult PhysicalFile(string physicalPath, string contentType) + => PhysicalFile(physicalPath, contentType, fileDownloadName: null); + + /// + /// Returns the file specified by () with the + /// specified as the Content-Type and the + /// specified as the suggested file name. + /// + /// The physical path of the file to be returned. + /// The Content-Type of the file. + /// The suggested file name. + /// The created for the response. + public virtual PhysicalFileResult PhysicalFile( + string physicalPath, + string contentType, + string fileDownloadName) + => new PhysicalFileResult(physicalPath, contentType) { FileDownloadName = fileDownloadName }; + /// /// Creates a object that redirects () /// to the specified . @@ -173,14 +514,457 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// The created for the response. protected internal RedirectResult Redirect(string url) { + if (string.IsNullOrEmpty(url)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(url)); + } + return new RedirectResult(url); } + /// + /// Creates a object with set to true + /// () using the specified . + /// + /// The URL to redirect to. + /// The created for the response. + public virtual RedirectResult RedirectPermanent(string url) + { + if (string.IsNullOrEmpty(url)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(url)); + } + + return new RedirectResult(url, permanent: true); + } + + /// + /// Creates a object with set to false + /// and set to true () + /// using the specified . + /// + /// The URL to redirect to. + /// The created for the response. + public virtual RedirectResult RedirectPreserveMethod(string url) + { + if (string.IsNullOrEmpty(url)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(url)); + } + + return new RedirectResult(url: url, permanent: false, preserveMethod: true); + } + + /// + /// Creates a object with set to true + /// and set to true () + /// using the specified . + /// + /// The URL to redirect to. + /// The created for the response. + public virtual RedirectResult RedirectPermanentPreserveMethod(string url) + { + if (string.IsNullOrEmpty(url)) + { + throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(url)); + } + + return new RedirectResult(url: url, permanent: true, preserveMethod: true); + } + + /// + /// Redirects () to the specified action using the . + /// + /// The name of the action. + /// The created for the response. + public virtual RedirectToActionResult RedirectToAction(string actionName) + => RedirectToAction(actionName, routeValues: null); + + /// + /// Redirects () to the specified action using the + /// and . + /// + /// The name of the action. + /// The parameters for a route. + /// The created for the response. + public virtual RedirectToActionResult RedirectToAction(string actionName, object routeValues) + => RedirectToAction(actionName, controllerName: null, routeValues: routeValues); + + /// + /// Redirects () to the specified action using the + /// and the . + /// + /// The name of the action. + /// The name of the pageModel. + /// The created for the response. + public virtual RedirectToActionResult RedirectToAction(string actionName, string controllerName) + => RedirectToAction(actionName, controllerName, routeValues: null); + + /// + /// Redirects () to the specified action using the specified + /// , , and . + /// + /// The name of the action. + /// The name of the pageModel. + /// The parameters for a route. + /// The created for the response. + public virtual RedirectToActionResult RedirectToAction( + string actionName, + string controllerName, + object routeValues) + => RedirectToAction(actionName, controllerName, routeValues, fragment: null); + + /// + /// Redirects () to the specified action using the specified + /// , , and . + /// + /// The name of the action. + /// The name of the pageModel. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToActionResult RedirectToAction( + string actionName, + string controllerName, + string fragment) + => RedirectToAction(actionName, controllerName, routeValues: null, fragment: fragment); + + /// + /// Redirects () to the specified action using the specified , + /// , , and . + /// + /// The name of the action. + /// The name of the pageModel. + /// The parameters for a route. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToActionResult RedirectToAction( + string actionName, + string controllerName, + object routeValues, + string fragment) + { + return new RedirectToActionResult(actionName, controllerName, routeValues, fragment) + { + UrlHelper = Url, + }; + } + + /// + /// Redirects () to the specified action with + /// set to false and + /// set to true, using the specified , , + /// , and . + /// + /// The name of the action. + /// The name of the pageModel. + /// The route data to use for generating the URL. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToActionResult RedirectToActionPreserveMethod( + string actionName = null, + string controllerName = null, + object routeValues = null, + string fragment = null) + { + return new RedirectToActionResult( + actionName: actionName, + controllerName: controllerName, + routeValues: routeValues, + permanent: false, + preserveMethod: true, + fragment: fragment) + { + UrlHelper = Url, + }; + } + + /// + /// Redirects () to the specified action with + /// set to true using the specified . + /// + /// The name of the action. + /// The created for the response. + public virtual RedirectToActionResult RedirectToActionPermanent(string actionName) + => RedirectToActionPermanent(actionName, routeValues: null); + + /// + /// Redirects () to the specified action with + /// set to true using the specified + /// and . + /// + /// The name of the action. + /// The parameters for a route. + /// The created for the response. + public virtual RedirectToActionResult RedirectToActionPermanent(string actionName, object routeValues) + => RedirectToActionPermanent(actionName, controllerName: null, routeValues: routeValues); + + /// + /// Redirects () to the specified action with + /// set to true using the specified + /// and . + /// + /// The name of the action. + /// The name of the pageModel. + /// The created for the response. + public virtual RedirectToActionResult RedirectToActionPermanent(string actionName, string controllerName) + => RedirectToActionPermanent(actionName, controllerName, routeValues: null); + + /// + /// Redirects () to the specified action with + /// set to true using the specified , + /// , and . + /// + /// The name of the action. + /// The name of the pageModel. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToActionResult RedirectToActionPermanent( + string actionName, + string controllerName, + string fragment) + => RedirectToActionPermanent(actionName, controllerName, routeValues: null, fragment: fragment); + + /// + /// Redirects () to the specified action with + /// set to true using the specified , + /// , and . + /// + /// The name of the action. + /// The name of the pageModel. + /// The parameters for a route. + /// The created for the response. + public virtual RedirectToActionResult RedirectToActionPermanent( + string actionName, + string controllerName, + object routeValues) + => RedirectToActionPermanent(actionName, controllerName, routeValues, fragment: null); + + /// + /// Redirects () to the specified action with + /// set to true using the specified , + /// , , and . + /// + /// The name of the action. + /// The name of the pageModel. + /// The parameters for a route. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToActionResult RedirectToActionPermanent( + string actionName, + string controllerName, + object routeValues, + string fragment) + { + return new RedirectToActionResult( + actionName, + controllerName, + routeValues, + permanent: true, + fragment: fragment) + { + UrlHelper = Url, + }; + } + + /// + /// Redirects () to the specified action with + /// set to true and + /// set to true, using the specified , , + /// , and . + /// + /// The name of the action. + /// The name of the pageModel. + /// The route data to use for generating the URL. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToActionResult RedirectToActionPermanentPreserveMethod( + string actionName = null, + string controllerName = null, + object routeValues = null, + string fragment = null) + { + return new RedirectToActionResult( + actionName: actionName, + controllerName: controllerName, + routeValues: routeValues, + permanent: true, + preserveMethod: true, + fragment: fragment) + { + UrlHelper = Url, + }; + } + + /// + /// Redirects () to the specified route using the specified . + /// + /// The name of the route. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoute(string routeName) + => RedirectToRoute(routeName, routeValues: null); + + /// + /// Redirects () to the specified route using the specified . + /// + /// The parameters for a route. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoute(object routeValues) + => RedirectToRoute(routeName: null, routeValues: routeValues); + + /// + /// Redirects () to the specified route using the specified + /// and . + /// + /// The name of the route. + /// The parameters for a route. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoute(string routeName, object routeValues) + => RedirectToRoute(routeName, routeValues, fragment: null); + + /// + /// Redirects () to the specified route using the specified + /// and . + /// + /// The name of the route. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoute(string routeName, string fragment) + => RedirectToRoute(routeName, routeValues: null, fragment: fragment); + + /// + /// Redirects () to the specified route using the specified + /// , , and . + /// + /// The name of the route. + /// The parameters for a route. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoute( + string routeName, + object routeValues, + string fragment) + { + return new RedirectToRouteResult(routeName, routeValues, fragment) + { + UrlHelper = Url, + }; + } + + /// + /// Redirects () to the specified route with + /// set to false and + /// set to true, using the specified , , and . + /// + /// The name of the route. + /// The route data to use for generating the URL. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoutePreserveMethod( + string routeName = null, + object routeValues = null, + string fragment = null) + { + return new RedirectToRouteResult( + routeName: routeName, + routeValues: routeValues, + permanent: false, + preserveMethod: true, + fragment: fragment) + { + UrlHelper = Url, + }; + } + + /// + /// Redirects () to the specified route with + /// set to true using the specified . + /// + /// The name of the route. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoutePermanent(string routeName) + => RedirectToRoutePermanent(routeName, routeValues: null); + + /// + /// Redirects () to the specified route with + /// set to true using the specified . + /// + /// The parameters for a route. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoutePermanent(object routeValues) + => RedirectToRoutePermanent(routeName: null, routeValues: routeValues); + + /// + /// Redirects () to the specified route with + /// set to true using the specified + /// and . + /// + /// The name of the route. + /// The parameters for a route. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoutePermanent(string routeName, object routeValues) + => RedirectToRoutePermanent(routeName, routeValues, fragment: null); + + /// + /// Redirects () to the specified route with + /// set to true using the specified + /// and . + /// + /// The name of the route. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoutePermanent(string routeName, string fragment) + => RedirectToRoutePermanent(routeName, routeValues: null, fragment: fragment); + + /// + /// Redirects () to the specified route with + /// set to true using the specified , + /// , and . + /// + /// The name of the route. + /// The parameters for a route. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoutePermanent( + string routeName, + object routeValues, + string fragment) + { + return new RedirectToRouteResult(routeName, routeValues, permanent: true, fragment: fragment) + { + UrlHelper = Url, + }; + } + + /// + /// Redirects () to the specified route with + /// set to true and + /// set to true, using the specified , , and . + /// + /// The name of the route. + /// The route data to use for generating the URL. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToRouteResult RedirectToRoutePermanentPreserveMethod( + string routeName = null, + object routeValues = null, + string fragment = null) + { + return new RedirectToRouteResult( + routeName: routeName, + routeValues: routeValues, + permanent: true, + preserveMethod: true, + fragment: fragment) + { + UrlHelper = Url, + }; + } + /// /// Redirects () to the current page. /// /// The . - protected RedirectToPageResult RedirectToPage() + public virtual RedirectToPageResult RedirectToPage() => RedirectToPage(pageName: null); /// @@ -188,7 +972,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// /// The parameters for a route. /// The . - protected RedirectToPageResult RedirectToPage(object routeValues) + public virtual RedirectToPageResult RedirectToPage(object routeValues) => RedirectToPage(pageName: null, routeValues: routeValues); /// @@ -269,6 +1053,120 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages protected internal RedirectToPageResult RedirectToPagePermanent(string pageName, object routeValues, string fragment) => new RedirectToPageResult(pageName, routeValues, permanent: true, fragment: fragment); + /// + /// Redirects () to the specified page with + /// set to false and + /// set to true, using the specified , , and . + /// + /// The name of the page. + /// The route data to use for generating the URL. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToPageResult RedirectToPagePreserveMethod( + string pageName = null, + object routeValues = null, + string fragment = null) + { + return new RedirectToPageResult( + pageName: pageName, + routeValues: routeValues, + permanent: false, + preserveMethod: true, + fragment: fragment); + } + + /// + /// Redirects () to the specified route with + /// set to true and + /// set to true, using the specified , , and . + /// + /// The name of the page. + /// The route data to use for generating the URL. + /// The fragment to add to the URL. + /// The created for the response. + public virtual RedirectToPageResult RedirectToPagePermanentPreserveMethod( + string pageName = null, + object routeValues = null, + string fragment = null) + { + return new RedirectToPageResult( + pageName: pageName, + routeValues: routeValues, + permanent: true, + preserveMethod: true, + fragment: fragment); + } + + /// + /// Creates a with the specified authentication scheme. + /// + /// The containing the user claims. + /// The authentication scheme to use for the sign-in operation. + /// The created for the response. + public virtual SignInResult SignIn(ClaimsPrincipal principal, string authenticationScheme) + => new SignInResult(authenticationScheme, principal); + + /// + /// Creates a with the specified specified authentication scheme and + /// . + /// + /// The containing the user claims. + /// used to perform the sign-in operation. + /// The authentication scheme to use for the sign-in operation. + /// The created for the response. + public virtual SignInResult SignIn( + ClaimsPrincipal principal, + AuthenticationProperties properties, + string authenticationScheme) + => new SignInResult(authenticationScheme, principal, properties); + + /// + /// Creates a with the specified authentication schemes. + /// + /// The authentication schemes to use for the sign-out operation. + /// The created for the response. + public virtual SignOutResult SignOut(params string[] authenticationSchemes) + => new SignOutResult(authenticationSchemes); + + /// + /// Creates a with the specified specified authentication schemes and + /// . + /// + /// used to perform the sign-out operation. + /// The authentication scheme to use for the sign-out operation. + /// The created for the response. + public virtual SignOutResult SignOut(AuthenticationProperties properties, params string[] authenticationSchemes) + => new SignOutResult(authenticationSchemes, properties); + + /// + /// Creates a object by specifying a . + /// + /// The status code to set on the response. + /// The created object for the response. + public virtual StatusCodeResult StatusCode(int statusCode) + => new StatusCodeResult(statusCode); + + /// + /// Creates a object by specifying a and + /// + /// The status code to set on the response. + /// The value to set on the . + /// The created object for the response. + public virtual ObjectResult StatusCode(int statusCode, object value) + { + return new ObjectResult(value) + { + StatusCode = statusCode + }; + } + + /// + /// Creates an that produces an response. + /// + /// The created for the response. + public virtual UnauthorizedResult Unauthorized() + => new UnauthorizedResult(); + /// /// Creates a object that renders the page. /// @@ -277,5 +1175,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages { return new PageViewResult(Page); } + #endregion Factory methods } } \ No newline at end of file diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/RedirectToPageResult.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/RedirectToPageResult.cs index d808d1f44b..fcb29e81b5 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/RedirectToPageResult.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/RedirectToPageResult.cs @@ -41,8 +41,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// Initializes a new instance of the with the values /// provided. /// - /// The name of the route. - /// The parameters for the route. + /// The name of the page. + /// The parameters for the page. /// If set to true, makes the redirect permanent (301). Otherwise a temporary redirect is used (302). public RedirectToPageResult( string pageName, @@ -52,11 +52,27 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages { } + /// + /// Initializes a new instance of the with the values provided. + /// + /// The name of the page. + /// The parameters for the page. + /// If set to true, makes the redirect permanent (301). Otherwise a temporary redirect is used (302). + /// If set to true, make the temporary redirect (307) or permanent redirect (308) preserve the intial request method. + public RedirectToPageResult( + string pageName, + object routeValues, + bool permanent, + bool preserveMethod) + : this(pageName, routeValues, permanent, preserveMethod, fragment: null) + { + } + /// /// Initializes a new instance of the with the values /// provided. /// - /// The name of the route. + /// The name of the page. /// The parameters for the route. /// The fragment to add to the URL. public RedirectToPageResult( @@ -71,8 +87,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// Initializes a new instance of the with the values /// provided. /// - /// The name of the route. - /// The parameters for the route. + /// The name of the page. + /// The parameters for the page. /// If set to true, makes the redirect permanent (301). Otherwise a temporary redirect is used (302). /// The fragment to add to the URL. public RedirectToPageResult( @@ -87,6 +103,29 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages Fragment = fragment; } + /// + /// Initializes a new instance of the with the values + /// provided. + /// + /// The name of the page. + /// The parameters for the page. + /// If set to true, makes the redirect permanent (301). Otherwise a temporary redirect is used (302). + /// If set to true, make the temporary redirect (307) or permanent redirect (308) preserve the intial request method. + /// The fragment to add to the URL. + public RedirectToPageResult( + string pageName, + object routeValues, + bool permanent, + bool preserveMethod, + string fragment) + { + PageName = pageName; + RouteValues = routeValues == null ? null : new RouteValueDictionary(routeValues); + PreserveMethod = preserveMethod; + Permanent = permanent; + Fragment = fragment; + } + /// /// Gets or sets the used to generate URLs. /// @@ -107,6 +146,11 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages /// public bool Permanent { get; set; } + /// + /// Gets or sets an indication that the redirect preserves the initial request method. + /// + public bool PreserveMethod { get; set; } + /// /// Gets or sets the fragment to add to the URL. /// diff --git a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/PageModelTest.cs b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/PageModelTest.cs index 2307219ef3..e5019878b8 100644 --- a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/PageModelTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/PageModelTest.cs @@ -2,13 +2,19 @@ // 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.IO; +using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure; using Microsoft.AspNetCore.Mvc.Routing; +using Microsoft.AspNetCore.Mvc.TestCommon; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Routing; +using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.DependencyInjection; using Moq; using Xunit; @@ -17,6 +23,1381 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages { public class PageModelTest { + [Fact] + public void Redirect_WithParameterUrl_SetsRedirectResultSameUrl() + { + // Arrange + var pageModel = new TestPageModel(); + var url = "/test/url"; + + // Act + var result = pageModel.Redirect(url); + + // Assert + Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Same(url, result.Url); + } + + [Fact] + public void RedirectPermanent_WithParameterUrl_SetsRedirectResultPermanentAndSameUrl() + { + // Arrange + var pageModel = new TestPageModel(); + var url = "/test/url"; + + // Act + var result = pageModel.RedirectPermanent(url); + + // Assert + Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Same(url, result.Url); + } + + [Fact] + public void RedirectPermanent_WithParameterUrl_SetsRedirectResultPreserveMethodAndSameUrl() + { + // Arrange + var pageModel = new TestPageModel(); + var url = "/test/url"; + + // Act + var result = pageModel.RedirectPreserveMethod(url); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Same(url, result.Url); + } + + [Fact] + public void RedirectPermanent_WithParameterUrl_SetsRedirectResultPermanentPreserveMethodAndSameUrl() + { + // Arrange + var pageModel = new TestPageModel(); + var url = "/test/url"; + + // Act + var result = pageModel.RedirectPermanentPreserveMethod(url); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Same(url, result.Url); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void Redirect_WithParameter_NullOrEmptyUrl_Throws(string url) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act & Assert + ExceptionAssert.ThrowsArgument( + () => pageModel.Redirect(url: url), "url", "Value cannot be null or empty."); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void RedirectPreserveMethod_WithParameter_NullOrEmptyUrl_Throws(string url) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act & Assert + ExceptionAssert.ThrowsArgumentNullOrEmpty( + () => pageModel.RedirectPreserveMethod(url: url), "url"); + } + + [Fact] + public void LocalRedirect_WithParameterUrl_SetsLocalRedirectResultWithSameUrl() + { + // Arrange + var pageModel = new TestPageModel(); + var url = "/test/url"; + + // Act + var result = pageModel.LocalRedirect(url); + + // Assert + Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Same(url, result.Url); + } + + [Fact] + public void LocalRedirectPermanent_WithParameterUrl_SetsLocalRedirectResultPermanentWithSameUrl() + { + // Arrange + var pageModel = new TestPageModel(); + var url = "/test/url"; + + // Act + var result = pageModel.LocalRedirectPermanent(url); + + // Assert + Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Same(url, result.Url); + } + + [Fact] + public void LocalRedirectPermanent_WithParameterUrl_SetsLocalRedirectResultPreserveMethodWithSameUrl() + { + // Arrange + var pageModel = new TestPageModel(); + var url = "/test/url"; + + // Act + var result = pageModel.LocalRedirectPreserveMethod(url); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Same(url, result.Url); + } + + [Fact] + public void LocalRedirectPermanent_WithParameterUrl_SetsLocalRedirectResultPermanentPreservesMethodWithSameUrl() + { + // Arrange + var pageModel = new TestPageModel(); + var url = "/test/url"; + + // Act + var result = pageModel.LocalRedirectPermanentPreserveMethod(url); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Same(url, result.Url); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void LocalRedirect_WithParameter_NullOrEmptyUrl_Throws(string url) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act & Assert + ExceptionAssert.ThrowsArgumentNullOrEmpty( + () => pageModel.LocalRedirect(localUrl: url), "localUrl"); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void LocalRedirectPreserveMethod_WithParameter_NullOrEmptyUrl_Throws(string url) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act & Assert + ExceptionAssert.ThrowsArgumentNullOrEmpty( + () => pageModel.LocalRedirectPreserveMethod(localUrl: url), "localUrl"); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void LocalRedirectPermanentPreserveMethod_WithParameter_NullOrEmptyUrl_Throws(string url) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act & Assert + ExceptionAssert.ThrowsArgumentNullOrEmpty( + () => pageModel.LocalRedirectPermanentPreserveMethod(localUrl: url), "localUrl"); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void RedirectPermanent_WithParameter_NullOrEmptyUrl_Throws(string url) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act & Assert + ExceptionAssert.ThrowsArgumentNullOrEmpty( + () => pageModel.RedirectPermanent(url: url), "url"); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void RedirectPermanentPreserveMethod_WithParameter_NullOrEmptyUrl_Throws(string url) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act & Assert + ExceptionAssert.ThrowsArgumentNullOrEmpty( + () => pageModel.RedirectPermanentPreserveMethod(url: url), "url"); + } + + [Fact] + public void RedirectToAction_WithParameterActionName_SetsResultActionName() + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var resultTemporary = pageModel.RedirectToAction("SampleAction"); + + // Assert + Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Equal("SampleAction", resultTemporary.ActionName); + } + + [Fact] + public void RedirectToActionPreserveMethod_WithParameterActionName_SetsResultActionName() + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var resultTemporary = pageModel.RedirectToActionPreserveMethod(actionName: "SampleAction"); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Equal("SampleAction", resultTemporary.ActionName); + } + + [Fact] + public void RedirectToActionPermanent_WithParameterActionName_SetsResultActionNameAndPermanent() + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var resultPermanent = pageModel.RedirectToActionPermanent("SampleAction"); + + // Assert + Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Equal("SampleAction", resultPermanent.ActionName); + } + + [Fact] + public void RedirectToActionPermanentPreserveMethod_WithParameterActionName_SetsResultActionNameAndPermanent() + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var resultPermanent = pageModel.RedirectToActionPermanentPreserveMethod(actionName: "SampleAction"); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Equal("SampleAction", resultPermanent.ActionName); + } + + [Theory] + [InlineData("")] + [InlineData(null)] + [InlineData("SampleController")] + public void RedirectToAction_WithParameterActionAndControllerName_SetsEqualNames(string pageModelName) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var resultTemporary = pageModel.RedirectToAction("SampleAction", pageModelName); + + // Assert + Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Equal("SampleAction", resultTemporary.ActionName); + Assert.Equal(pageModelName, resultTemporary.ControllerName); + } + + [Theory] + [InlineData("")] + [InlineData(null)] + [InlineData("SampleController")] + public void RedirectToActionPreserveMethod_WithParameterActionAndControllerName_SetsEqualNames(string pageModelName) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var resultTemporary = pageModel.RedirectToActionPreserveMethod(actionName: "SampleAction", controllerName: pageModelName); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Equal("SampleAction", resultTemporary.ActionName); + Assert.Equal(pageModelName, resultTemporary.ControllerName); + } + + [Theory] + [InlineData("")] + [InlineData(null)] + [InlineData("SampleController")] + public void RedirectToActionPermanent_WithParameterActionAndControllerName_SetsEqualNames(string pageModelName) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var resultPermanent = pageModel.RedirectToActionPermanent("SampleAction", pageModelName); + + // Assert + Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Equal("SampleAction", resultPermanent.ActionName); + Assert.Equal(pageModelName, resultPermanent.ControllerName); + } + + [Theory] + [InlineData("")] + [InlineData(null)] + [InlineData("SampleController")] + public void RedirectToActionPermanentPreserveMethod_WithParameterActionAndControllerName_SetsEqualNames(string pageModelName) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var resultPermanent = pageModel.RedirectToActionPermanentPreserveMethod(actionName: "SampleAction", controllerName: pageModelName); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Equal("SampleAction", resultPermanent.ActionName); + Assert.Equal(pageModelName, resultPermanent.ControllerName); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToAction_WithParameterActionControllerRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var resultTemporary = pageModel.RedirectToAction("SampleAction", "SampleController", routeValues); + + // Assert + Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Equal("SampleAction", resultTemporary.ActionName); + Assert.Equal("SampleController", resultTemporary.ControllerName); + Assert.Equal(expected, resultTemporary.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPreserveMethod_WithParameterActionControllerRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var resultTemporary = pageModel.RedirectToActionPreserveMethod( + actionName: "SampleAction", + controllerName: "SampleController", + routeValues: routeValues); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Equal("SampleAction", resultTemporary.ActionName); + Assert.Equal("SampleController", resultTemporary.ControllerName); + Assert.Equal(expected, resultTemporary.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPermanent_WithParameterActionControllerRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var resultPermanent = pageModel.RedirectToActionPermanent( + "SampleAction", + "SampleController", + routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Equal("SampleAction", resultPermanent.ActionName); + Assert.Equal("SampleController", resultPermanent.ControllerName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPermanentPreserveMethod_WithParameterActionControllerRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var resultPermanent = pageModel.RedirectToActionPermanentPreserveMethod( + actionName: "SampleAction", + controllerName: "SampleController", + routeValues: routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Equal("SampleAction", resultPermanent.ActionName); + Assert.Equal("SampleController", resultPermanent.ControllerName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToAction_WithParameterActionAndRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var resultTemporary = pageModel.RedirectToAction(actionName: null, routeValues: routeValues); + + // Assert + Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Null(resultTemporary.ActionName); + Assert.Equal(expected, resultTemporary.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPreserveMethod_WithParameterActionAndRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var resultTemporary = pageModel.RedirectToActionPreserveMethod(actionName: null, routeValues: routeValues); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Null(resultTemporary.ActionName); + Assert.Equal(expected, resultTemporary.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToAction_WithParameterActionAndControllerAndRouteValuesAndFragment_SetsResultProperties( + object routeValues, + IEnumerable> expectedRouteValues) + { + // Arrange + var pageModel = new TestPageModel(); + var expectedAction = "Action"; + var expectedController = "Home"; + var expectedFragment = "test"; + + // Act + var result = pageModel.RedirectToAction("Action", "Home", routeValues, "test"); + + // Assert + Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Equal(expectedAction, result.ActionName); + Assert.Equal(expectedRouteValues, result.RouteValues); + Assert.Equal(expectedController, result.ControllerName); + Assert.Equal(expectedFragment, result.Fragment); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPreserveMethod_WithParameterActionAndControllerAndRouteValuesAndFragment_SetsResultProperties( + object routeValues, + IEnumerable> expectedRouteValues) + { + // Arrange + var pageModel = new TestPageModel(); + var expectedAction = "Action"; + var expectedController = "Home"; + var expectedFragment = "test"; + + // Act + var result = pageModel.RedirectToActionPreserveMethod("Action", "Home", routeValues, "test"); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Equal(expectedAction, result.ActionName); + Assert.Equal(expectedRouteValues, result.RouteValues); + Assert.Equal(expectedController, result.ControllerName); + Assert.Equal(expectedFragment, result.Fragment); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPermanent_WithParameterActionAndRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var resultPermanent = pageModel.RedirectToActionPermanent(null, routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Null(resultPermanent.ActionName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPermanentPreserveMethod_WithParameterActionAndRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var resultPermanent = pageModel.RedirectToActionPermanentPreserveMethod(actionName: null, routeValues: routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Null(resultPermanent.ActionName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPermanent_WithParameterActionAndControllerAndRouteValuesAndFragment_SetsResultProperties( + object routeValues, + IEnumerable> expectedRouteValues) + { + // Arrange + var pageModel = new TestPageModel(); + var expectedAction = "Action"; + var expectedController = "Home"; + var expectedFragment = "test"; + + // Act + var result = pageModel.RedirectToActionPermanent("Action", "Home", routeValues, fragment: "test"); + + // Assert + Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Equal(expectedAction, result.ActionName); + Assert.Equal(expectedRouteValues, result.RouteValues); + Assert.Equal(expectedController, result.ControllerName); + Assert.Equal(expectedFragment, result.Fragment); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPermanentPreserveMethod_WithParameterActionAndControllerAndRouteValuesAndFragment_SetsResultProperties( + object routeValues, + IEnumerable> expectedRouteValues) + { + // Arrange + var pageModel = new TestPageModel(); + var expectedAction = "Action"; + var expectedController = "Home"; + var expectedFragment = "test"; + + // Act + var result = pageModel.RedirectToActionPermanentPreserveMethod( + actionName: "Action", + controllerName: "Home", + routeValues: routeValues, + fragment: "test"); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Equal(expectedAction, result.ActionName); + Assert.Equal(expectedRouteValues, result.RouteValues); + Assert.Equal(expectedController, result.ControllerName); + Assert.Equal(expectedFragment, result.Fragment); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoute_WithParameterRouteValues_SetsResultEqualRouteValues( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var resultTemporary = pageModel.RedirectToRoute(routeValues); + + // Assert + Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Equal(expected, resultTemporary.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePreserveMethod_WithParameterRouteValues_SetsResultEqualRouteValues( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var resultTemporary = pageModel.RedirectToRoutePreserveMethod(routeValues: routeValues); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Equal(expected, resultTemporary.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoute_WithParameterRouteNameAndRouteValuesAndFragment_SetsResultProperties( + object routeValues, + IEnumerable> expectedRouteValues) + { + // Arrange + var pageModel = new TestPageModel(); + var expectedRoute = "TestRoute"; + var expectedFragment = "test"; + + // Act + var result = pageModel.RedirectToRoute("TestRoute", routeValues, "test"); + + // Assert + Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Equal(expectedRoute, result.RouteName); + Assert.Equal(expectedRouteValues, result.RouteValues); + Assert.Equal(expectedFragment, result.Fragment); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePreserveMethod_WithParameterRouteNameAndRouteValuesAndFragment_SetsResultProperties( + object routeValues, + IEnumerable> expectedRouteValues) + { + // Arrange + var pageModel = new TestPageModel(); + var expectedRoute = "TestRoute"; + var expectedFragment = "test"; + + // Act + var result = pageModel.RedirectToRoutePreserveMethod(routeName: "TestRoute", routeValues: routeValues, fragment: "test"); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Equal(expectedRoute, result.RouteName); + Assert.Equal(expectedRouteValues, result.RouteValues); + Assert.Equal(expectedFragment, result.Fragment); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePermanent_WithParameterRouteValues_SetsResultEqualRouteValuesAndPermanent( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var resultPermanent = pageModel.RedirectToRoutePermanent(routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePermanentPreserveMethod_WithParameterRouteValues_SetsResultEqualRouteValuesAndPermanent( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var resultPermanent = pageModel.RedirectToRoutePermanentPreserveMethod(routeValues: routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePermanent_WithParameterRouteNameAndRouteValuesAndFragment_SetsResultProperties( + object routeValues, + IEnumerable> expectedRouteValues) + { + // Arrange + var pageModel = new TestPageModel(); + var expectedRoute = "TestRoute"; + var expectedFragment = "test"; + + // Act + var result = pageModel.RedirectToRoutePermanent("TestRoute", routeValues, "test"); + + // Assert + Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Equal(expectedRoute, result.RouteName); + Assert.Equal(expectedRouteValues, result.RouteValues); + Assert.Equal(expectedFragment, result.Fragment); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePermanentPreserveMethod_WithParameterRouteNameAndRouteValuesAndFragment_SetsResultProperties( + object routeValues, + IEnumerable> expectedRouteValues) + { + // Arrange + var pageModel = new TestPageModel(); + var expectedRoute = "TestRoute"; + var expectedFragment = "test"; + + // Act + var result = pageModel.RedirectToRoutePermanentPreserveMethod(routeName: "TestRoute", routeValues: routeValues, fragment: "test"); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Equal(expectedRoute, result.RouteName); + Assert.Equal(expectedRouteValues, result.RouteValues); + Assert.Equal(expectedFragment, result.Fragment); + } + + [Fact] + public void RedirectToRoute_WithParameterRouteName_SetsResultSameRouteName() + { + // Arrange + var pageModel = new TestPageModel(); + var routeName = "CustomRouteName"; + + // Act + var resultTemporary = pageModel.RedirectToRoute(routeName); + + // Assert + Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Same(routeName, resultTemporary.RouteName); + } + + [Fact] + public void RedirectToRoutePreserveMethod_WithParameterRouteName_SetsResultSameRouteName() + { + // Arrange + var pageModel = new TestPageModel(); + var routeName = "CustomRouteName"; + + // Act; + var resultTemporary = pageModel.RedirectToRoutePreserveMethod(routeName: routeName); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Same(routeName, resultTemporary.RouteName); + } + + [Fact] + public void RedirectToRoutePermanent_WithParameterRouteName_SetsResultSameRouteNameAndPermanent() + { + // Arrange + var pageModel = new TestPageModel(); + var routeName = "CustomRouteName"; + + // Act + var resultPermanent = pageModel.RedirectToRoutePermanent(routeName); + + // Assert + Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Same(routeName, resultPermanent.RouteName); + } + + [Fact] + public void RedirectToRoutePermanentPreserveMethod_WithParameterRouteName_SetsResultSameRouteNameAndPermanent() + { + // Arrange + var pageModel = new TestPageModel(); + var routeName = "CustomRouteName"; + + // Act + var resultPermanent = pageModel.RedirectToRoutePermanentPreserveMethod(routeName: routeName); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Same(routeName, resultPermanent.RouteName); + } + + public static IEnumerable RedirectTestData + { + get + { + yield return new object[] + { + null, + null, + }; + + yield return new object[] + { + new Dictionary { { "hello", "world" } }, + new RouteValueDictionary() { { "hello", "world" } }, + }; + + var expected2 = new Dictionary + { + { "test", "case" }, + { "sample", "route" }, + }; + + yield return new object[] + { + new RouteValueDictionary(expected2), + new RouteValueDictionary(expected2), + }; + } + } + + [Fact] + public void RedirectToPagePreserveMethod_WithParameterUrl_SetsRedirectResultPreserveMethod() + { + // Arrange + var pageModel = new TestPageModel(); + var url = "/test/url"; + + // Act + var result = pageModel.RedirectToPagePreserveMethod(url); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Same(url, result.PageName); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToPagePreserveMethod_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestPageModel(); + var pageName = "CustomRouteName"; + + // Act + var resultPermanent = pageModel.RedirectToPagePreserveMethod(pageName, routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); + Assert.False(resultPermanent.Permanent); + Assert.Same(pageName, resultPermanent.PageName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToPagePermanentPreserveMethod_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestPageModel(); + var routeName = "CustomRouteName"; + + // Act + var resultPermanent = pageModel.RedirectToPagePermanentPreserveMethod(routeName, routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Same(routeName, resultPermanent.PageName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoute_WithParameterRouteNameAndRouteValues_SetsResultSameRouteNameAndRouteValues( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestPageModel(); + var routeName = "CustomRouteName"; + + // Act + var resultTemporary = pageModel.RedirectToRoute(routeName, routeValues); + + // Assert + Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Same(routeName, resultTemporary.RouteName); + Assert.Equal(expected, resultTemporary.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePreserveMethod_WithParameterRouteNameAndRouteValues_SetsResultSameRouteNameAndRouteValues( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestPageModel(); + var routeName = "CustomRouteName"; + + // Act + var resultTemporary = pageModel.RedirectToRoutePreserveMethod(routeName: routeName, routeValues: routeValues); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Same(routeName, resultTemporary.RouteName); + Assert.Equal(expected, resultTemporary.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePermanent_WithParameterRouteNameAndRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestPageModel(); + var routeName = "CustomRouteName"; + + // Act + var resultPermanent = pageModel.RedirectToRoutePermanent(routeName, routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Same(routeName, resultPermanent.RouteName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePermanentPreserveMethod_WithParameterRouteNameAndRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestPageModel(); + var routeName = "CustomRouteName"; + + // Act + var resultPermanent = pageModel.RedirectToRoutePermanentPreserveMethod(routeName: routeName, routeValues: routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Same(routeName, resultPermanent.RouteName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Fact] + public void File_WithContents() + { + // Arrange + var pageModel = new TestPageModel(); + var fileContents = new byte[0]; + + // Act + var result = pageModel.File(fileContents, "application/pdf"); + + // Assert + Assert.NotNull(result); + Assert.Same(fileContents, result.FileContents); + Assert.Equal("application/pdf", result.ContentType.ToString()); + Assert.Equal(string.Empty, result.FileDownloadName); + } + + [Fact] + public void File_WithContentsAndFileDownloadName() + { + // Arrange + var pageModel = new TestPageModel(); + var fileContents = new byte[0]; + + // Act + var result = pageModel.File(fileContents, "application/pdf", "someDownloadName"); + + // Assert + Assert.NotNull(result); + Assert.Same(fileContents, result.FileContents); + Assert.Equal("application/pdf", result.ContentType.ToString()); + Assert.Equal("someDownloadName", result.FileDownloadName); + } + + [Fact] + public void File_WithPath() + { + // Arrange + var pageModel = new TestPageModel(); + var path = Path.GetFullPath("somepath"); + + // Act + var result = pageModel.File(path, "application/pdf"); + + // Assert + Assert.NotNull(result); + Assert.Equal(path, result.FileName); + Assert.Equal("application/pdf", result.ContentType.ToString()); + Assert.Equal(string.Empty, result.FileDownloadName); + } + + [Fact] + public void File_WithPathAndFileDownloadName() + { + // Arrange + var pageModel = new TestPageModel(); + var path = Path.GetFullPath("somepath"); + + // Act + var result = pageModel.File(path, "application/pdf", "someDownloadName"); + + // Assert + Assert.NotNull(result); + Assert.Equal(path, result.FileName); + Assert.Equal("application/pdf", result.ContentType.ToString()); + Assert.Equal("someDownloadName", result.FileDownloadName); + } + + [Fact] + public void File_WithStream() + { + // Arrange + var mockHttpContext = new Mock(); + mockHttpContext.Setup(x => x.Response.RegisterForDispose(It.IsAny())); + + var pageModel = new TestPageModel() + { + PageContext = new PageContext + { + HttpContext = mockHttpContext.Object + } + }; + + var fileStream = Stream.Null; + + // Act + var result = pageModel.File(fileStream, "application/pdf"); + + // Assert + Assert.NotNull(result); + Assert.Same(fileStream, result.FileStream); + Assert.Equal("application/pdf", result.ContentType.ToString()); + Assert.Equal(string.Empty, result.FileDownloadName); + } + + [Fact] + public void File_WithStreamAndFileDownloadName() + { + // Arrange + var mockHttpContext = new Mock(); + + var pageModel = new TestPageModel() + { + PageContext = new PageContext + { + HttpContext = mockHttpContext.Object + } + }; + + var fileStream = Stream.Null; + + // Act + var result = pageModel.File(fileStream, "application/pdf", "someDownloadName"); + + // Assert + Assert.NotNull(result); + Assert.Same(fileStream, result.FileStream); + Assert.Equal("application/pdf", result.ContentType.ToString()); + Assert.Equal("someDownloadName", result.FileDownloadName); + } + + [Fact] + public void Unauthorized_SetsStatusCode() + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var result = pageModel.Unauthorized(); + + // Assert + Assert.IsType(result); + Assert.Equal(StatusCodes.Status401Unauthorized, result.StatusCode); + } + + [Fact] + public void NotFound_SetsStatusCode() + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var result = pageModel.NotFound(); + + // Assert + Assert.IsType(result); + Assert.Equal(StatusCodes.Status404NotFound, result.StatusCode); + } + + [Fact] + public void NotFound_SetsStatusCodeAndResponseContent() + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var result = pageModel.NotFound("Test Content"); + + // Assert + Assert.IsType(result); + Assert.Equal(StatusCodes.Status404NotFound, result.StatusCode); + Assert.Equal("Test Content", result.Value); + } + + [Fact] + public void Content_WithParameterContentString_SetsResultContent() + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var actualContentResult = pageModel.Content("TestContent"); + + // Assert + Assert.IsType(actualContentResult); + Assert.Equal("TestContent", actualContentResult.Content); + Assert.Null(actualContentResult.ContentType); + } + + [Fact] + public void Content_WithParameterContentStringAndContentType_SetsResultContentAndContentType() + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var actualContentResult = pageModel.Content("TestContent", "text/plain"); + + // Assert + Assert.IsType(actualContentResult); + Assert.Equal("TestContent", actualContentResult.Content); + Assert.Null(MediaType.GetEncoding(actualContentResult.ContentType)); + Assert.Equal("text/plain", actualContentResult.ContentType.ToString()); + } + + [Fact] + public void Content_WithParameterContentAndTypeAndEncoding_SetsResultContentAndTypeAndEncoding() + { + // Arrange + var pageModel = new TestPageModel(); + + // Act + var actualContentResult = pageModel.Content("TestContent", "text/plain", Encoding.UTF8); + + // Assert + Assert.IsType(actualContentResult); + Assert.Equal("TestContent", actualContentResult.Content); + Assert.Same(Encoding.UTF8, MediaType.GetEncoding(actualContentResult.ContentType)); + Assert.Equal("text/plain; charset=utf-8", actualContentResult.ContentType.ToString()); + } + + [Fact] + public void Content_NoContentType_DefaultEncodingIsUsed() + { + // Arrange + var contentPageModel = new ContentPageModel(); + + // Act + var contentResult = (ContentResult)contentPageModel.Content_WithNoEncoding(); + + // Assert + // The default content type of ContentResult is used when the result is executed. + Assert.Null(contentResult.ContentType); + } + + [Fact] + public void Content_InvalidCharset_DefaultEncodingIsUsed() + { + // Arrange + var contentPageModel = new ContentPageModel(); + var contentType = "text/xml; charset=invalid; p1=p1-value"; + + // Act + var contentResult = (ContentResult)contentPageModel.Content_WithInvalidCharset(); + + // Assert + Assert.NotNull(contentResult.ContentType); + Assert.Equal(contentType, contentResult.ContentType.ToString()); + // The default encoding of ContentResult is used when this result is executed. + Assert.Null(MediaType.GetEncoding(contentResult.ContentType)); + } + + [Fact] + public void Content_CharsetAndEncodingProvided_EncodingIsUsed() + { + // Arrange + var contentPageModel = new ContentPageModel(); + var contentType = "text/xml; charset=us-ascii; p1=p1-value"; + + // Act + var contentResult = (ContentResult)contentPageModel.Content_WithEncodingInCharset_AndEncodingParameter(); + + // Assert + MediaTypeAssert.Equal(contentType, contentResult.ContentType); + } + + [Fact] + public void Content_CharsetInContentType_IsUsedForEncoding() + { + // Arrange + var contentPageModel = new ContentPageModel(); + var contentType = "text/xml; charset=us-ascii; p1=p1-value"; + + // Act + var contentResult = (ContentResult)contentPageModel.Content_WithEncodingInCharset(); + + // Assert + Assert.Equal(contentType, contentResult.ContentType); + } + + [Fact] + public void StatusCode_SetObject() + { + // Arrange + var statusCode = 204; + var value = new { Value = 42 }; + + var statusCodeController = new StatusCodePageModel(); + + // Act + var result = (ObjectResult)statusCodeController.StatusCode_Object(statusCode, value); + + // Assert + Assert.Equal(statusCode, result.StatusCode); + Assert.Equal(value, result.Value); + } + + [Fact] + public void StatusCode_SetObjectNull() + { + // Arrange + var statusCode = 204; + object value = null; + + var statusCodeController = new StatusCodePageModel(); + + // Act + var result = statusCodeController.StatusCode_Object(statusCode, value); + + // Assert + Assert.Equal(statusCode, result.StatusCode); + Assert.Equal(value, result.Value); + } + + [Fact] + public void StatusCode_SetsStatusCode() + { + // Arrange + var statusCode = 205; + var statusCodeModel = new StatusCodePageModel(); + + // Act + var result = statusCodeModel.StatusCode_Int(statusCode); + + // Assert + Assert.Equal(statusCode, result.StatusCode); + } + [Fact] public void PageModelPropertiesArePopulatedFromContext() { @@ -142,6 +1523,42 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages Assert.Same(page, pageResult.Page); } + private class ContentPageModel : PageModel + { + public IActionResult Content_WithNoEncoding() + { + return Content("Hello!!"); + } + + public IActionResult Content_WithEncodingInCharset() + { + return Content("Hello!!", "text/xml; charset=us-ascii; p1=p1-value"); + } + + public IActionResult Content_WithInvalidCharset() + { + return Content("Hello!!", "text/xml; charset=invalid; p1=p1-value"); + } + + public IActionResult Content_WithEncodingInCharset_AndEncodingParameter() + { + return Content("Hello!!", "text/xml; charset=invalid; p1=p1-value", Encoding.ASCII); + } + } + + private class StatusCodePageModel : PageModel + { + public StatusCodeResult StatusCode_Int(int statusCode) + { + return StatusCode(statusCode); + } + + public ObjectResult StatusCode_Object(int statusCode, object value) + { + return StatusCode(statusCode, value); + } + } + private class TestPageModel : PageModel { } diff --git a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/PageTest.cs b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/PageTest.cs index 1a8fde83b3..4a355fb289 100644 --- a/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/PageTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.RazorPages.Test/PageTest.cs @@ -2,16 +2,20 @@ // 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.IO; +using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Formatters; using Microsoft.AspNetCore.Mvc.ModelBinding; -using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure; -using Microsoft.AspNetCore.Mvc.Routing; +using Microsoft.AspNetCore.Mvc.TestCommon; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Routing; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.AspNetCore.Testing; using Moq; using Xunit; + namespace Microsoft.AspNetCore.Mvc.RazorPages { public class PageTest @@ -42,6 +46,1427 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages Assert.Same(tempData, page.TempData); } + [Fact] + public void Redirect_WithParameterUrl_SetsRedirectResultSameUrl() + { + // Arrange + var page = new TestPage(); + var url = "/test/url"; + + // Act + var result = page.Redirect(url); + + // Assert + Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Same(url, result.Url); + } + + [Fact] + public void RedirectPermanent_WithParameterUrl_SetsRedirectResultPermanentAndSameUrl() + { + // Arrange + var page = new TestPage(); + var url = "/test/url"; + + // Act + var result = page.RedirectPermanent(url); + + // Assert + Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Same(url, result.Url); + } + + [Fact] + public void RedirectPermanent_WithParameterUrl_SetsRedirectResultPreserveMethodAndSameUrl() + { + // Arrange + var page = new TestPage(); + var url = "/test/url"; + + // Act + var result = page.RedirectPreserveMethod(url); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Same(url, result.Url); + } + + [Fact] + public void RedirectPermanent_WithParameterUrl_SetsRedirectResultPermanentPreserveMethodAndSameUrl() + { + // Arrange + var page = new TestPage(); + var url = "/test/url"; + + // Act + var result = page.RedirectPermanentPreserveMethod(url); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Same(url, result.Url); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void Redirect_WithParameter_NullOrEmptyUrl_Throws(string url) + { + // Arrange + var page = new TestPage(); + + // Act & Assert + ExceptionAssert.ThrowsArgumentNullOrEmpty( + () => page.Redirect(url: url), "url"); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void RedirectPreserveMethod_WithParameter_NullOrEmptyUrl_Throws(string url) + { + // Arrange + var page = new TestPage(); + + // Act & Assert + ExceptionAssert.ThrowsArgumentNullOrEmpty( + () => page.RedirectPreserveMethod(url: url), "url"); + } + + [Fact] + public void LocalRedirect_WithParameterUrl_SetsLocalRedirectResultWithSameUrl() + { + // Arrange + var page = new TestPage(); + var url = "/test/url"; + + // Act + var result = page.LocalRedirect(url); + + // Assert + Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Same(url, result.Url); + } + + [Fact] + public void LocalRedirectPermanent_WithParameterUrl_SetsLocalRedirectResultPermanentWithSameUrl() + { + // Arrange + var page = new TestPage(); + var url = "/test/url"; + + // Act + var result = page.LocalRedirectPermanent(url); + + // Assert + Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Same(url, result.Url); + } + + [Fact] + public void LocalRedirectPermanent_WithParameterUrl_SetsLocalRedirectResultPreserveMethodWithSameUrl() + { + // Arrange + var page = new TestPage(); + var url = "/test/url"; + + // Act + var result = page.LocalRedirectPreserveMethod(url); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Same(url, result.Url); + } + + [Fact] + public void LocalRedirectPermanent_WithParameterUrl_SetsLocalRedirectResultPermanentPreservesMethodWithSameUrl() + { + // Arrange + var page = new TestPage(); + var url = "/test/url"; + + // Act + var result = page.LocalRedirectPermanentPreserveMethod(url); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Same(url, result.Url); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void LocalRedirect_WithParameter_NullOrEmptyUrl_Throws(string url) + { + // Arrange + var page = new TestPage(); + + // Act & Assert + ExceptionAssert.ThrowsArgumentNullOrEmpty( + () => page.LocalRedirect(localUrl: url), "localUrl"); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void LocalRedirectPreserveMethod_WithParameter_NullOrEmptyUrl_Throws(string url) + { + // Arrange + var page = new TestPage(); + + // Act & Assert + ExceptionAssert.ThrowsArgumentNullOrEmpty( + () => page.LocalRedirectPreserveMethod(localUrl: url), "localUrl"); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void LocalRedirectPermanentPreserveMethod_WithParameter_NullOrEmptyUrl_Throws(string url) + { + // Arrange + var page = new TestPage(); + + // Act & Assert + ExceptionAssert.ThrowsArgumentNullOrEmpty( + () => page.LocalRedirectPermanentPreserveMethod(localUrl: url), "localUrl"); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void RedirectPermanent_WithParameter_NullOrEmptyUrl_Throws(string url) + { + // Arrange + var page = new TestPage(); + + // Act & Assert + ExceptionAssert.ThrowsArgumentNullOrEmpty( + () => page.RedirectPermanent(url: url), "url"); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void RedirectPermanentPreserveMethod_WithParameter_NullOrEmptyUrl_Throws(string url) + { + // Arrange + var page = new TestPage(); + + // Act & Assert + ExceptionAssert.ThrowsArgumentNullOrEmpty( + () => page.RedirectPermanentPreserveMethod(url: url), "url"); + } + + [Fact] + public void RedirectToAction_WithParameterActionName_SetsResultActionName() + { + // Arrange + var page = new TestPage(); + + // Act + var resultTemporary = page.RedirectToAction("SampleAction"); + + // Assert + Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Equal("SampleAction", resultTemporary.ActionName); + } + + [Fact] + public void RedirectToActionPreserveMethod_WithParameterActionName_SetsResultActionName() + { + // Arrange + var page = new TestPage(); + + // Act + var resultTemporary = page.RedirectToActionPreserveMethod(actionName: "SampleAction"); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Equal("SampleAction", resultTemporary.ActionName); + } + + [Fact] + public void RedirectToActionPermanent_WithParameterActionName_SetsResultActionNameAndPermanent() + { + // Arrange + var page = new TestPage(); + + // Act + var resultPermanent = page.RedirectToActionPermanent("SampleAction"); + + // Assert + Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Equal("SampleAction", resultPermanent.ActionName); + } + + [Fact] + public void RedirectToActionPermanentPreserveMethod_WithParameterActionName_SetsResultActionNameAndPermanent() + { + // Arrange + var page = new TestPage(); + + // Act + var resultPermanent = page.RedirectToActionPermanentPreserveMethod(actionName: "SampleAction"); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Equal("SampleAction", resultPermanent.ActionName); + } + + [Theory] + [InlineData("")] + [InlineData(null)] + [InlineData("SampleController")] + public void RedirectToAction_WithParameterActionAndControllerName_SetsEqualNames(string controllerName) + { + // Arrange + var page = new TestPage(); + + // Act + var resultTemporary = page.RedirectToAction("SampleAction", controllerName); + + // Assert + Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Equal("SampleAction", resultTemporary.ActionName); + Assert.Equal(controllerName, resultTemporary.ControllerName); + } + + [Theory] + [InlineData("")] + [InlineData(null)] + [InlineData("SampleController")] + public void RedirectToActionPreserveMethod_WithParameterActionAndControllerName_SetsEqualNames(string controllerName) + { + // Arrange + var page = new TestPage(); + + // Act + var resultTemporary = page.RedirectToActionPreserveMethod(actionName: "SampleAction", controllerName: controllerName); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Equal("SampleAction", resultTemporary.ActionName); + Assert.Equal(controllerName, resultTemporary.ControllerName); + } + + [Theory] + [InlineData("")] + [InlineData(null)] + [InlineData("SampleController")] + public void RedirectToActionPermanent_WithParameterActionAndControllerName_SetsEqualNames(string controllerName) + { + // Arrange + var page = new TestPage(); + + // Act + var resultPermanent = page.RedirectToActionPermanent("SampleAction", controllerName); + + // Assert + Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Equal("SampleAction", resultPermanent.ActionName); + Assert.Equal(controllerName, resultPermanent.ControllerName); + } + + [Theory] + [InlineData("")] + [InlineData(null)] + [InlineData("SampleController")] + public void RedirectToActionPermanentPreserveMethod_WithParameterActionAndControllerName_SetsEqualNames(string controllerName) + { + // Arrange + var page = new TestPage(); + + // Act + var resultPermanent = page.RedirectToActionPermanentPreserveMethod(actionName: "SampleAction", controllerName: controllerName); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Equal("SampleAction", resultPermanent.ActionName); + Assert.Equal(controllerName, resultPermanent.ControllerName); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToAction_WithParameterActionControllerRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var page = new TestPage(); + + // Act + var resultTemporary = page.RedirectToAction("SampleAction", "SampleController", routeValues); + + // Assert + Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Equal("SampleAction", resultTemporary.ActionName); + Assert.Equal("SampleController", resultTemporary.ControllerName); + Assert.Equal(expected, resultTemporary.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPreserveMethod_WithParameterActionControllerRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var page = new TestPage(); + + // Act + var resultTemporary = page.RedirectToActionPreserveMethod( + actionName: "SampleAction", + controllerName: "SampleController", + routeValues: routeValues); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Equal("SampleAction", resultTemporary.ActionName); + Assert.Equal("SampleController", resultTemporary.ControllerName); + Assert.Equal(expected, resultTemporary.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPermanent_WithParameterActionControllerRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var page = new TestPage(); + + // Act + var resultPermanent = page.RedirectToActionPermanent( + "SampleAction", + "SampleController", + routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Equal("SampleAction", resultPermanent.ActionName); + Assert.Equal("SampleController", resultPermanent.ControllerName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPermanentPreserveMethod_WithParameterActionControllerRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var page = new TestPage(); + + // Act + var resultPermanent = page.RedirectToActionPermanentPreserveMethod( + actionName: "SampleAction", + controllerName: "SampleController", + routeValues: routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Equal("SampleAction", resultPermanent.ActionName); + Assert.Equal("SampleController", resultPermanent.ControllerName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToAction_WithParameterActionAndRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var page = new TestPage(); + + // Act + var resultTemporary = page.RedirectToAction(actionName: null, routeValues: routeValues); + + // Assert + Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Null(resultTemporary.ActionName); + Assert.Equal(expected, resultTemporary.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPreserveMethod_WithParameterActionAndRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var page = new TestPage(); + + // Act + var resultTemporary = page.RedirectToActionPreserveMethod(actionName: null, routeValues: routeValues); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Null(resultTemporary.ActionName); + Assert.Equal(expected, resultTemporary.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToAction_WithParameterActionAndControllerAndRouteValuesAndFragment_SetsResultProperties( + object routeValues, + IEnumerable> expectedRouteValues) + { + // Arrange + var page = new TestPage(); + var expectedAction = "Action"; + var expectedController = "Home"; + var expectedFragment = "test"; + + // Act + var result = page.RedirectToAction("Action", "Home", routeValues, "test"); + + // Assert + Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Equal(expectedAction, result.ActionName); + Assert.Equal(expectedRouteValues, result.RouteValues); + Assert.Equal(expectedController, result.ControllerName); + Assert.Equal(expectedFragment, result.Fragment); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPreserveMethod_WithParameterActionAndControllerAndRouteValuesAndFragment_SetsResultProperties( + object routeValues, + IEnumerable> expectedRouteValues) + { + // Arrange + var page = new TestPage(); + var expectedAction = "Action"; + var expectedController = "Home"; + var expectedFragment = "test"; + + // Act + var result = page.RedirectToActionPreserveMethod("Action", "Home", routeValues, "test"); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Equal(expectedAction, result.ActionName); + Assert.Equal(expectedRouteValues, result.RouteValues); + Assert.Equal(expectedController, result.ControllerName); + Assert.Equal(expectedFragment, result.Fragment); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPermanent_WithParameterActionAndRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var page = new TestPage(); + + // Act + var resultPermanent = page.RedirectToActionPermanent(null, routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Null(resultPermanent.ActionName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPermanentPreserveMethod_WithParameterActionAndRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var page = new TestPage(); + + // Act + var resultPermanent = page.RedirectToActionPermanentPreserveMethod(actionName: null, routeValues: routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Null(resultPermanent.ActionName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPermanent_WithParameterActionAndControllerAndRouteValuesAndFragment_SetsResultProperties( + object routeValues, + IEnumerable> expectedRouteValues) + { + // Arrange + var page = new TestPage(); + var expectedAction = "Action"; + var expectedController = "Home"; + var expectedFragment = "test"; + + // Act + var result = page.RedirectToActionPermanent("Action", "Home", routeValues, fragment: "test"); + + // Assert + Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Equal(expectedAction, result.ActionName); + Assert.Equal(expectedRouteValues, result.RouteValues); + Assert.Equal(expectedController, result.ControllerName); + Assert.Equal(expectedFragment, result.Fragment); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToActionPermanentPreserveMethod_WithParameterActionAndControllerAndRouteValuesAndFragment_SetsResultProperties( + object routeValues, + IEnumerable> expectedRouteValues) + { + // Arrange + var page = new TestPage(); + var expectedAction = "Action"; + var expectedController = "Home"; + var expectedFragment = "test"; + + // Act + var result = page.RedirectToActionPermanentPreserveMethod( + actionName: "Action", + controllerName: "Home", + routeValues: routeValues, + fragment: "test"); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Equal(expectedAction, result.ActionName); + Assert.Equal(expectedRouteValues, result.RouteValues); + Assert.Equal(expectedController, result.ControllerName); + Assert.Equal(expectedFragment, result.Fragment); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoute_WithParameterRouteValues_SetsResultEqualRouteValues( + object routeValues, + IEnumerable> expected) + { + // Arrange + var page = new TestPage(); + + // Act + var resultTemporary = page.RedirectToRoute(routeValues); + + // Assert + Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Equal(expected, resultTemporary.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePreserveMethod_WithParameterRouteValues_SetsResultEqualRouteValues( + object routeValues, + IEnumerable> expected) + { + // Arrange + var page = new TestPage(); + + // Act + var resultTemporary = page.RedirectToRoutePreserveMethod(routeValues: routeValues); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Equal(expected, resultTemporary.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoute_WithParameterRouteNameAndRouteValuesAndFragment_SetsResultProperties( + object routeValues, + IEnumerable> expectedRouteValues) + { + // Arrange + var page = new TestPage(); + var expectedRoute = "TestRoute"; + var expectedFragment = "test"; + + // Act + var result = page.RedirectToRoute("TestRoute", routeValues, "test"); + + // Assert + Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Equal(expectedRoute, result.RouteName); + Assert.Equal(expectedRouteValues, result.RouteValues); + Assert.Equal(expectedFragment, result.Fragment); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePreserveMethod_WithParameterRouteNameAndRouteValuesAndFragment_SetsResultProperties( + object routeValues, + IEnumerable> expectedRouteValues) + { + // Arrange + var page = new TestPage(); + var expectedRoute = "TestRoute"; + var expectedFragment = "test"; + + // Act + var result = page.RedirectToRoutePreserveMethod(routeName: "TestRoute", routeValues: routeValues, fragment: "test"); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Equal(expectedRoute, result.RouteName); + Assert.Equal(expectedRouteValues, result.RouteValues); + Assert.Equal(expectedFragment, result.Fragment); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePermanent_WithParameterRouteValues_SetsResultEqualRouteValuesAndPermanent( + object routeValues, + IEnumerable> expected) + { + // Arrange + var page = new TestPage(); + + // Act + var resultPermanent = page.RedirectToRoutePermanent(routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePermanentPreserveMethod_WithParameterRouteValues_SetsResultEqualRouteValuesAndPermanent( + object routeValues, + IEnumerable> expected) + { + // Arrange + var page = new TestPage(); + + // Act + var resultPermanent = page.RedirectToRoutePermanentPreserveMethod(routeValues: routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePermanent_WithParameterRouteNameAndRouteValuesAndFragment_SetsResultProperties( + object routeValues, + IEnumerable> expectedRouteValues) + { + // Arrange + var page = new TestPage(); + var expectedRoute = "TestRoute"; + var expectedFragment = "test"; + + // Act + var result = page.RedirectToRoutePermanent("TestRoute", routeValues, "test"); + + // Assert + Assert.IsType(result); + Assert.False(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Equal(expectedRoute, result.RouteName); + Assert.Equal(expectedRouteValues, result.RouteValues); + Assert.Equal(expectedFragment, result.Fragment); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePermanentPreserveMethod_WithParameterRouteNameAndRouteValuesAndFragment_SetsResultProperties( + object routeValues, + IEnumerable> expectedRouteValues) + { + // Arrange + var page = new TestPage(); + var expectedRoute = "TestRoute"; + var expectedFragment = "test"; + + // Act + var result = page.RedirectToRoutePermanentPreserveMethod(routeName: "TestRoute", routeValues: routeValues, fragment: "test"); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.True(result.Permanent); + Assert.Equal(expectedRoute, result.RouteName); + Assert.Equal(expectedRouteValues, result.RouteValues); + Assert.Equal(expectedFragment, result.Fragment); + } + + [Fact] + public void RedirectToRoute_WithParameterRouteName_SetsResultSameRouteName() + { + // Arrange + var page = new TestPage(); + var routeName = "CustomRouteName"; + + // Act + var resultTemporary = page.RedirectToRoute(routeName); + + // Assert + Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Same(routeName, resultTemporary.RouteName); + } + + [Fact] + public void RedirectToRoutePreserveMethod_WithParameterRouteName_SetsResultSameRouteName() + { + // Arrange + var page = new TestPage(); + var routeName = "CustomRouteName"; + + // Act; + var resultTemporary = page.RedirectToRoutePreserveMethod(routeName: routeName); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Same(routeName, resultTemporary.RouteName); + } + + [Fact] + public void RedirectToRoutePermanent_WithParameterRouteName_SetsResultSameRouteNameAndPermanent() + { + // Arrange + var page = new TestPage(); + var routeName = "CustomRouteName"; + + // Act + var resultPermanent = page.RedirectToRoutePermanent(routeName); + + // Assert + Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Same(routeName, resultPermanent.RouteName); + } + + [Fact] + public void RedirectToRoutePermanentPreserveMethod_WithParameterRouteName_SetsResultSameRouteNameAndPermanent() + { + // Arrange + var page = new TestPage(); + var routeName = "CustomRouteName"; + + // Act + var resultPermanent = page.RedirectToRoutePermanentPreserveMethod(routeName: routeName); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Same(routeName, resultPermanent.RouteName); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoute_WithParameterRouteNameAndRouteValues_SetsResultSameRouteNameAndRouteValues( + object routeValues, + IEnumerable> expected) + { + // Arrange + var page = new TestPage(); + var routeName = "CustomRouteName"; + + // Act + var resultTemporary = page.RedirectToRoute(routeName, routeValues); + + // Assert + Assert.IsType(resultTemporary); + Assert.False(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Same(routeName, resultTemporary.RouteName); + Assert.Equal(expected, resultTemporary.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePreserveMethod_WithParameterRouteNameAndRouteValues_SetsResultSameRouteNameAndRouteValues( + object routeValues, + IEnumerable> expected) + { + // Arrange + var page = new TestPage(); + var routeName = "CustomRouteName"; + + // Act + var resultTemporary = page.RedirectToRoutePreserveMethod(routeName: routeName, routeValues: routeValues); + + // Assert + Assert.IsType(resultTemporary); + Assert.True(resultTemporary.PreserveMethod); + Assert.False(resultTemporary.Permanent); + Assert.Same(routeName, resultTemporary.RouteName); + Assert.Equal(expected, resultTemporary.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePermanent_WithParameterRouteNameAndRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var page = new TestPage(); + var routeName = "CustomRouteName"; + + // Act + var resultPermanent = page.RedirectToRoutePermanent(routeName, routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.False(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Same(routeName, resultPermanent.RouteName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToRoutePermanentPreserveMethod_WithParameterRouteNameAndRouteValues_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var page = new TestPage(); + var routeName = "CustomRouteName"; + + // Act + var resultPermanent = page.RedirectToRoutePermanentPreserveMethod(routeName: routeName, routeValues: routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Same(routeName, resultPermanent.RouteName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Fact] + public void RedirectToPagePreserveMethod_WithParameterUrl_SetsRedirectResultPreserveMethod() + { + // Arrange + var pageModel = new TestPage(); + var url = "/test/url"; + + // Act + var result = pageModel.RedirectToPagePreserveMethod(url); + + // Assert + Assert.IsType(result); + Assert.True(result.PreserveMethod); + Assert.False(result.Permanent); + Assert.Same(url, result.PageName); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToPagePreserveMethod_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestPage(); + var pageName = "CustomRouteName"; + + // Act + var resultPermanent = pageModel.RedirectToPagePreserveMethod(pageName, routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); + Assert.False(resultPermanent.Permanent); + Assert.Same(pageName, resultPermanent.PageName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Theory] + [MemberData(nameof(RedirectTestData))] + public void RedirectToPagePermanentPreserveMethod_SetsResultProperties( + object routeValues, + IEnumerable> expected) + { + // Arrange + var pageModel = new TestPage(); + var routeName = "CustomRouteName"; + + // Act + var resultPermanent = pageModel.RedirectToPagePermanentPreserveMethod(routeName, routeValues); + + // Assert + Assert.IsType(resultPermanent); + Assert.True(resultPermanent.PreserveMethod); + Assert.True(resultPermanent.Permanent); + Assert.Same(routeName, resultPermanent.PageName); + Assert.Equal(expected, resultPermanent.RouteValues); + } + + [Fact] + public void File_WithContents() + { + // Arrange + var page = new TestPage(); + var fileContents = new byte[0]; + + // Act + var result = page.File(fileContents, "application/pdf"); + + // Assert + Assert.NotNull(result); + Assert.Same(fileContents, result.FileContents); + Assert.Equal("application/pdf", result.ContentType.ToString()); + Assert.Equal(string.Empty, result.FileDownloadName); + } + + [Fact] + public void File_WithContentsAndFileDownloadName() + { + // Arrange + var page = new TestPage(); + var fileContents = new byte[0]; + + // Act + var result = page.File(fileContents, "application/pdf", "someDownloadName"); + + // Assert + Assert.NotNull(result); + Assert.Same(fileContents, result.FileContents); + Assert.Equal("application/pdf", result.ContentType.ToString()); + Assert.Equal("someDownloadName", result.FileDownloadName); + } + + [Fact] + public void File_WithPath() + { + // Arrange + var page = new TestPage(); + var path = Path.GetFullPath("somepath"); + + // Act + var result = page.File(path, "application/pdf"); + + // Assert + Assert.NotNull(result); + Assert.Equal(path, result.FileName); + Assert.Equal("application/pdf", result.ContentType.ToString()); + Assert.Equal(string.Empty, result.FileDownloadName); + } + + [Fact] + public void File_WithPathAndFileDownloadName() + { + // Arrange + var page = new TestPage(); + var path = Path.GetFullPath("somepath"); + + // Act + var result = page.File(path, "application/pdf", "someDownloadName"); + + // Assert + Assert.NotNull(result); + Assert.Equal(path, result.FileName); + Assert.Equal("application/pdf", result.ContentType.ToString()); + Assert.Equal("someDownloadName", result.FileDownloadName); + } + + [Fact] + public void File_WithStream() + { + // Arrange + var mockHttpContext = new Mock(); + mockHttpContext.Setup(x => x.Response.RegisterForDispose(It.IsAny())); + + var page = new TestPage() + { + PageContext = new PageContext + { + HttpContext = mockHttpContext.Object + } + }; + + var fileStream = Stream.Null; + + // Act + var result = page.File(fileStream, "application/pdf"); + + // Assert + Assert.NotNull(result); + Assert.Same(fileStream, result.FileStream); + Assert.Equal("application/pdf", result.ContentType.ToString()); + Assert.Equal(string.Empty, result.FileDownloadName); + } + + [Fact] + public void File_WithStreamAndFileDownloadName() + { + // Arrange + var mockHttpContext = new Mock(); + + var page = new TestPage() + { + PageContext = new PageContext + { + HttpContext = mockHttpContext.Object + } + }; + + var fileStream = Stream.Null; + + // Act + var result = page.File(fileStream, "application/pdf", "someDownloadName"); + + // Assert + Assert.NotNull(result); + Assert.Same(fileStream, result.FileStream); + Assert.Equal("application/pdf", result.ContentType.ToString()); + Assert.Equal("someDownloadName", result.FileDownloadName); + } + + [Fact] + public void Unauthorized_SetsStatusCode() + { + // Arrange + var page = new TestPage(); + + // Act + var result = page.Unauthorized(); + + // Assert + Assert.IsType(result); + Assert.Equal(StatusCodes.Status401Unauthorized, result.StatusCode); + } + + [Fact] + public void NotFound_SetsStatusCode() + { + // Arrange + var page = new TestPage(); + + // Act + var result = page.NotFound(); + + // Assert + Assert.IsType(result); + Assert.Equal(StatusCodes.Status404NotFound, result.StatusCode); + } + + [Fact] + public void NotFound_SetsStatusCodeAndResponseContent() + { + // Arrange + var page = new TestPage(); + + // Act + var result = page.NotFound("Test Content"); + + // Assert + Assert.IsType(result); + Assert.Equal(StatusCodes.Status404NotFound, result.StatusCode); + Assert.Equal("Test Content", result.Value); + } + + [Fact] + public void Content_WithParameterContentString_SetsResultContent() + { + // Arrange + var page = new TestPage(); + + // Act + var actualContentResult = page.Content("TestContent"); + + // Assert + Assert.IsType(actualContentResult); + Assert.Equal("TestContent", actualContentResult.Content); + Assert.Null(actualContentResult.ContentType); + } + + [Fact] + public void Content_WithParameterContentStringAndContentType_SetsResultContentAndContentType() + { + // Arrange + var page = new TestPage(); + + // Act + var actualContentResult = page.Content("TestContent", "text/plain"); + + // Assert + Assert.IsType(actualContentResult); + Assert.Equal("TestContent", actualContentResult.Content); + Assert.Null(MediaType.GetEncoding(actualContentResult.ContentType)); + Assert.Equal("text/plain", actualContentResult.ContentType.ToString()); + } + + [Fact] + public void Content_WithParameterContentAndTypeAndEncoding_SetsResultContentAndTypeAndEncoding() + { + // Arrange + var page = new TestPage(); + + // Act + var actualContentResult = page.Content("TestContent", "text/plain", Encoding.UTF8); + + // Assert + Assert.IsType(actualContentResult); + Assert.Equal("TestContent", actualContentResult.Content); + Assert.Same(Encoding.UTF8, MediaType.GetEncoding(actualContentResult.ContentType)); + Assert.Equal("text/plain; charset=utf-8", actualContentResult.ContentType.ToString()); + } + + [Fact] + public void Content_NoContentType_DefaultEncodingIsUsed() + { + // Arrange + var contentPage = new ContentPage(); + + // Act + var contentResult = (ContentResult)contentPage.Content_WithNoEncoding(); + + // Assert + // The default content type of ContentResult is used when the result is executed. + Assert.Null(contentResult.ContentType); + } + + [Fact] + public void Content_InvalidCharset_DefaultEncodingIsUsed() + { + // Arrange + var contentPage = new ContentPage(); + var contentType = "text/xml; charset=invalid; p1=p1-value"; + + // Act + var contentResult = (ContentResult)contentPage.Content_WithInvalidCharset(); + + // Assert + Assert.NotNull(contentResult.ContentType); + Assert.Equal(contentType, contentResult.ContentType.ToString()); + // The default encoding of ContentResult is used when this result is executed. + Assert.Null(MediaType.GetEncoding(contentResult.ContentType)); + } + + [Fact] + public void Content_CharsetAndEncodingProvided_EncodingIsUsed() + { + // Arrange + var contentPage = new ContentPage(); + var contentType = "text/xml; charset=us-ascii; p1=p1-value"; + + // Act + var contentResult = (ContentResult)contentPage.Content_WithEncodingInCharset_AndEncodingParameter(); + + // Assert + MediaTypeAssert.Equal(contentType, contentResult.ContentType); + } + + [Fact] + public void Content_CharsetInContentType_IsUsedForEncoding() + { + // Arrange + var contentPage = new ContentPage(); + var contentType = "text/xml; charset=us-ascii; p1=p1-value"; + + // Act + var contentResult = (ContentResult)contentPage.Content_WithEncodingInCharset(); + + // Assert + Assert.Equal(contentType, contentResult.ContentType); + } + + [Fact] + public void StatusCode_SetObject() + { + // Arrange + var statusCode = 204; + var value = new { Value = 42 }; + + var statusCodePage = new StatusCodePage(); + + // Act + var result = (ObjectResult)statusCodePage.StatusCode_Object(statusCode, value); + + // Assert + Assert.Equal(statusCode, result.StatusCode); + Assert.Equal(value, result.Value); + } + + [Fact] + public void StatusCode_SetObjectNull() + { + // Arrange + var statusCode = 204; + object value = null; + + var statusCodePage = new StatusCodePage(); + + // Act + var result = statusCodePage.StatusCode_Object(statusCode, value); + + // Assert + Assert.Equal(statusCode, result.StatusCode); + Assert.Equal(value, result.Value); + } + + [Fact] + public void StatusCode_SetsStatusCode() + { + // Arrange + var statusCode = 205; + var statusCodePage = new StatusCodePage(); + + // Act + var result = statusCodePage.StatusCode_Int(statusCode); + + // Assert + Assert.Equal(statusCode, result.StatusCode); + } + + public static IEnumerable RedirectTestData + { + get + { + yield return new object[] + { + null, + null, + }; + + yield return new object[] + { + new Dictionary { { "hello", "world" } }, + new RouteValueDictionary() { { "hello", "world" } }, + }; + + var expected2 = new Dictionary + { + { "test", "case" }, + { "sample", "route" }, + }; + + yield return new object[] + { + new RouteValueDictionary(expected2), + new RouteValueDictionary(expected2), + }; + } + } + + private class ContentPage : Page + { + public IActionResult Content_WithNoEncoding() + { + return Content("Hello!!"); + } + + public IActionResult Content_WithEncodingInCharset() + { + return Content("Hello!!", "text/xml; charset=us-ascii; p1=p1-value"); + } + + public IActionResult Content_WithInvalidCharset() + { + return Content("Hello!!", "text/xml; charset=invalid; p1=p1-value"); + } + + public IActionResult Content_WithEncodingInCharset_AndEncodingParameter() + { + return Content("Hello!!", "text/xml; charset=invalid; p1=p1-value", Encoding.ASCII); + } + + public override Task ExecuteAsync() + { + throw new NotImplementedException(); + } + } + + private class StatusCodePage : Page + { + public override Task ExecuteAsync() + { + throw new NotImplementedException(); + } + + public StatusCodeResult StatusCode_Int(int statusCode) + { + return StatusCode(statusCode); + } + + public ObjectResult StatusCode_Object(int statusCode, object value) + { + return StatusCode(statusCode, value); + } + } + private class TestPage : Page { public override Task ExecuteAsync()