AcceptedResult(), AcceptedAtActionResult(), AcceptedAtRouteResult() support
Addresses #4937
This commit is contained in:
parent
e7c992ff06
commit
c2fee4d74d
|
|
@ -0,0 +1,94 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Core;
|
||||||
|
using Microsoft.AspNetCore.Routing;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Routing;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Net.Http.Headers;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An <see cref="ActionResult"/> that returns a Accepted (202) response with a Location header.
|
||||||
|
/// </summary>
|
||||||
|
public class AcceptedAtActionResult : ObjectResult
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="AcceptedAtActionResult"/> with the values
|
||||||
|
/// provided.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="actionName">The name of the action to use for generating the URL.</param>
|
||||||
|
/// <param name="controllerName">The name of the controller to use for generating the URL.</param>
|
||||||
|
/// <param name="routeValues">The route data to use for generating the URL.</param>
|
||||||
|
/// <param name="value">The value to format in the entity body.</param>
|
||||||
|
public AcceptedAtActionResult(
|
||||||
|
string actionName,
|
||||||
|
string controllerName,
|
||||||
|
object routeValues,
|
||||||
|
object value)
|
||||||
|
: base(value)
|
||||||
|
{
|
||||||
|
ActionName = actionName;
|
||||||
|
ControllerName = controllerName;
|
||||||
|
RouteValues = routeValues == null ? null : new RouteValueDictionary(routeValues);
|
||||||
|
StatusCode = StatusCodes.Status202Accepted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the <see cref="IUrlHelper" /> used to generate URLs.
|
||||||
|
/// </summary>
|
||||||
|
public IUrlHelper UrlHelper { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name of the action to use for generating the URL.
|
||||||
|
/// </summary>
|
||||||
|
public string ActionName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name of the controller to use for generating the URL.
|
||||||
|
/// </summary>
|
||||||
|
public string ControllerName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the route data to use for generating the URL.
|
||||||
|
/// </summary>
|
||||||
|
public RouteValueDictionary RouteValues { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnFormatting(ActionContext context)
|
||||||
|
{
|
||||||
|
if (context == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnFormatting(context);
|
||||||
|
|
||||||
|
var request = context.HttpContext.Request;
|
||||||
|
|
||||||
|
var urlHelper = UrlHelper;
|
||||||
|
if (urlHelper == null)
|
||||||
|
{
|
||||||
|
var services = context.HttpContext.RequestServices;
|
||||||
|
urlHelper = services.GetRequiredService<IUrlHelperFactory>().GetUrlHelper(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
var url = urlHelper.Action(
|
||||||
|
ActionName,
|
||||||
|
ControllerName,
|
||||||
|
RouteValues,
|
||||||
|
request.Scheme,
|
||||||
|
request.Host.ToUriComponent());
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(url))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(Resources.NoRoutesMatched);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.HttpContext.Response.Headers[HeaderNames.Location] = url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,90 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Core;
|
||||||
|
using Microsoft.AspNetCore.Routing;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Routing;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Net.Http.Headers;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An <see cref="ActionResult"/> that returns a Accepted (202) response with a Location header.
|
||||||
|
/// </summary>
|
||||||
|
public class AcceptedAtRouteResult : ObjectResult
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="AcceptedAtRouteResult"/> class with the values
|
||||||
|
/// provided.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="routeValues">The route data to use for generating the URL.</param>
|
||||||
|
/// <param name="value">The value to format in the entity body.</param>
|
||||||
|
public AcceptedAtRouteResult(object routeValues, object value)
|
||||||
|
: this(routeName: null, routeValues: routeValues, value: value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="AcceptedAtRouteResult"/> class with the values
|
||||||
|
/// provided.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="routeName">The name of the route to use for generating the URL.</param>
|
||||||
|
/// <param name="routeValues">The route data to use for generating the URL.</param>
|
||||||
|
/// <param name="value">The value to format in the entity body.</param>
|
||||||
|
public AcceptedAtRouteResult(
|
||||||
|
string routeName,
|
||||||
|
object routeValues,
|
||||||
|
object value)
|
||||||
|
: base(value)
|
||||||
|
{
|
||||||
|
RouteName = routeName;
|
||||||
|
RouteValues = routeValues == null ? null : new RouteValueDictionary(routeValues);
|
||||||
|
StatusCode = StatusCodes.Status202Accepted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the <see cref="IUrlHelper" /> used to generate URLs.
|
||||||
|
/// </summary>
|
||||||
|
public IUrlHelper UrlHelper { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name of the route to use for generating the URL.
|
||||||
|
/// </summary>
|
||||||
|
public string RouteName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the route data to use for generating the URL.
|
||||||
|
/// </summary>
|
||||||
|
public RouteValueDictionary RouteValues { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnFormatting(ActionContext context)
|
||||||
|
{
|
||||||
|
if (context == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnFormatting(context);
|
||||||
|
|
||||||
|
var urlHelper = UrlHelper;
|
||||||
|
if (urlHelper == null)
|
||||||
|
{
|
||||||
|
var services = context.HttpContext.RequestServices;
|
||||||
|
urlHelper = services.GetRequiredService<IUrlHelperFactory>().GetUrlHelper(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
var url = urlHelper.Link(RouteName, RouteValues);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(url))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(Resources.NoRoutesMatched);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.HttpContext.Response.Headers[HeaderNames.Location] = url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Net.Http.Headers;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An <see cref="ActionResult"/> that returns an Accepted (202) response with a Location header.
|
||||||
|
/// </summary>
|
||||||
|
public class AcceptedResult : ObjectResult
|
||||||
|
{
|
||||||
|
private string _location;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="AcceptedResult"/> class with the values
|
||||||
|
/// provided.
|
||||||
|
/// </summary>
|
||||||
|
public AcceptedResult()
|
||||||
|
: base(value: null)
|
||||||
|
{
|
||||||
|
StatusCode = StatusCodes.Status202Accepted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="AcceptedResult"/> class with the values
|
||||||
|
/// provided.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="location">The location at which the status of requested content can be monitored.</param>
|
||||||
|
/// <param name="value">The value to format in the entity body.</param>
|
||||||
|
public AcceptedResult(string location, object value)
|
||||||
|
: base(value)
|
||||||
|
{
|
||||||
|
Location = location;
|
||||||
|
StatusCode = StatusCodes.Status202Accepted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="AcceptedResult"/> class with the values
|
||||||
|
/// provided.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="locationUri">The location at which the status of requested content can be monitored
|
||||||
|
/// It is an optional paramater and may be null</param>
|
||||||
|
/// <param name="value">The value to format in the entity body.</param>
|
||||||
|
public AcceptedResult(Uri locationUri, object value)
|
||||||
|
: base(value)
|
||||||
|
{
|
||||||
|
if (locationUri == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(locationUri));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (locationUri.IsAbsoluteUri)
|
||||||
|
{
|
||||||
|
Location = locationUri.AbsoluteUri;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Location = locationUri.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped);
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusCode = StatusCodes.Status202Accepted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the location at which the status of the requested content can be monitored.
|
||||||
|
/// </summary>
|
||||||
|
public string Location
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _location;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_location = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void OnFormatting(ActionContext context)
|
||||||
|
{
|
||||||
|
if (context == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnFormatting(context);
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(Location))
|
||||||
|
{
|
||||||
|
context.HttpContext.Response.Headers[HeaderNames.Location] = Location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -910,6 +910,223 @@ namespace Microsoft.AspNetCore.Mvc
|
||||||
return new CreatedAtRouteResult(routeName, routeValues, value);
|
return new CreatedAtRouteResult(routeName, routeValues, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="AcceptedResult"/> object that produces an Accepted (202) response.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The created <see cref="AcceptedResult"/> for the response.</returns>
|
||||||
|
[NonAction]
|
||||||
|
public virtual AcceptedResult Accepted()
|
||||||
|
{
|
||||||
|
return new AcceptedResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="AcceptedResult"/> object that produces an Accepted (202) response.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value">The optional content value to format in the entity body; may be null.</param>
|
||||||
|
/// <returns>The created <see cref="AcceptedResult"/> for the response.</returns>
|
||||||
|
[NonAction]
|
||||||
|
public virtual AcceptedResult Accepted(object value)
|
||||||
|
{
|
||||||
|
return new AcceptedResult(location: null, value: value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="AcceptedResult"/> object that produces an Accepted (202) response.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uri">The optional URI with the location at which the status of requested content can be monitored.
|
||||||
|
/// May be null.</param>
|
||||||
|
/// <returns>The created <see cref="AcceptedResult"/> for the response.</returns>
|
||||||
|
[NonAction]
|
||||||
|
public virtual AcceptedResult Accepted(Uri uri)
|
||||||
|
{
|
||||||
|
if (uri == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(uri));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new AcceptedResult(locationUri: uri, value: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="AcceptedResult"/> object that produces an Accepted (202) response.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uri">The optional URI with the location at which the status of requested content can be monitored.
|
||||||
|
/// May be null.</param>
|
||||||
|
/// <returns>The created <see cref="AcceptedResult"/> for the response.</returns>
|
||||||
|
[NonAction]
|
||||||
|
public virtual AcceptedResult Accepted(string uri)
|
||||||
|
{
|
||||||
|
return new AcceptedResult(location: uri, value: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="AcceptedResult"/> object that produces an Accepted (202) response.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uri">The URI with the location at which the status of requested content can be monitored.</param>
|
||||||
|
/// <param name="value">The optional content value to format in the entity body; may be null.</param>
|
||||||
|
/// <returns>The created <see cref="AcceptedResult"/> for the response.</returns>
|
||||||
|
[NonAction]
|
||||||
|
public virtual AcceptedResult Accepted(string uri, object value)
|
||||||
|
{
|
||||||
|
return new AcceptedResult(uri, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="AcceptedResult"/> object that produces an Accepted (202) response.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uri">The URI with the location at which the status of requested content can be monitored.</param>
|
||||||
|
/// <param name="value">The optional content value to format in the entity body; may be null.</param>
|
||||||
|
/// <returns>The created <see cref="AcceptedResult"/> for the response.</returns>
|
||||||
|
[NonAction]
|
||||||
|
public virtual AcceptedResult Accepted(Uri uri, object value)
|
||||||
|
{
|
||||||
|
if (uri == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(uri));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new AcceptedResult(locationUri: uri, value: value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="AcceptedAtActionResult"/> object that produces an Accepted (202) response.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="actionName">The name of the action to use for generating the URL.</param>
|
||||||
|
/// <returns>The created <see cref="AcceptedAtActionResult"/> for the response.</returns>
|
||||||
|
[NonAction]
|
||||||
|
public virtual AcceptedAtActionResult AcceptedAtAction(string actionName)
|
||||||
|
{
|
||||||
|
return AcceptedAtAction(actionName, routeValues: null, value: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="AcceptedAtActionResult"/> object that produces an Accepted (202) response.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="actionName">The name of the action to use for generating the URL.</param>
|
||||||
|
/// <param name="controllerName">The name of the controller to use for generating the URL.</param>
|
||||||
|
/// <returns>The created <see cref="AcceptedAtActionResult"/> for the response.</returns>
|
||||||
|
[NonAction]
|
||||||
|
public virtual AcceptedAtActionResult AcceptedAtAction(string actionName, string controllerName)
|
||||||
|
{
|
||||||
|
return AcceptedAtAction(actionName, controllerName, routeValues: null, value: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="AcceptedAtActionResult"/> object that produces an Accepted (202) response.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="actionName">The name of the action to use for generating the URL.</param>
|
||||||
|
/// <param name="value">The optional content value to format in the entity body; may be null.</param>
|
||||||
|
/// <returns>The created <see cref="AcceptedAtActionResult"/> for the response.</returns>
|
||||||
|
[NonAction]
|
||||||
|
public virtual AcceptedAtActionResult AcceptedAtAction(string actionName, object value)
|
||||||
|
{
|
||||||
|
return AcceptedAtAction(actionName, routeValues: null, value: value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="AcceptedAtActionResult"/> object that produces an Accepted (202) response.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="actionName">The name of the action to use for generating the URL.</param>
|
||||||
|
/// <param name="controllerName">The name of the controller to use for generating the URL.</param>
|
||||||
|
/// <param name="routeValues">The route data to use for generating the URL.</param>
|
||||||
|
/// <returns>The created <see cref="AcceptedAtActionResult"/> for the response.</returns>
|
||||||
|
[NonAction]
|
||||||
|
public virtual AcceptedAtActionResult AcceptedAtAction(string actionName, string controllerName, object routeValues)
|
||||||
|
{
|
||||||
|
return AcceptedAtAction(actionName, controllerName, routeValues, value: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="AcceptedAtActionResult"/> object that produces an Accepted (202) response.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="actionName">The name of the action to use for generating the URL.</param>
|
||||||
|
/// <param name="routeValues">The route data to use for generating the URL.</param>
|
||||||
|
/// <param name="value">The optional content value to format in the entity body; may be null.</param>
|
||||||
|
/// <returns>The created <see cref="AcceptedAtActionResult"/> for the response.</returns>
|
||||||
|
[NonAction]
|
||||||
|
public virtual AcceptedAtActionResult AcceptedAtAction(string actionName, object routeValues, object value)
|
||||||
|
{
|
||||||
|
return AcceptedAtAction(actionName, controllerName: null, routeValues: routeValues, value: value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="AcceptedAtActionResult"/> object that produces an Accepted (202) response.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="actionName">The name of the action to use for generating the URL.</param>
|
||||||
|
/// <param name="controllerName">The name of the controller to use for generating the URL.</param>
|
||||||
|
/// <param name="routeValues">The route data to use for generating the URL.</param>
|
||||||
|
/// <param name="value">The optional content value to format in the entity body; may be null.</param>
|
||||||
|
/// <returns>The created <see cref="AcceptedAtActionResult"/> for the response.</returns>
|
||||||
|
[NonAction]
|
||||||
|
public virtual AcceptedAtActionResult AcceptedAtAction(
|
||||||
|
string actionName,
|
||||||
|
string controllerName,
|
||||||
|
object routeValues,
|
||||||
|
object value)
|
||||||
|
{
|
||||||
|
return new AcceptedAtActionResult(actionName, controllerName, routeValues, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="AcceptedAtRouteResult"/> object that produces an Accepted (202) response.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="routeValues">The route data to use for generating the URL.</param>
|
||||||
|
/// <returns>The created <see cref="AcceptedAtRouteResult"/> for the response.</returns>
|
||||||
|
[NonAction]
|
||||||
|
public virtual AcceptedAtRouteResult AcceptedAtRoute(object routeValues)
|
||||||
|
{
|
||||||
|
return AcceptedAtRoute(routeName: null, routeValues: routeValues, value: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="AcceptedAtRouteResult"/> object that produces an Accepted (202) response.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="routeName">The name of the route to use for generating the URL.</param>
|
||||||
|
/// <returns>The created <see cref="AcceptedAtRouteResult"/> for the response.</returns>
|
||||||
|
[NonAction]
|
||||||
|
public virtual AcceptedAtRouteResult AcceptedAtRoute(string routeName)
|
||||||
|
{
|
||||||
|
return AcceptedAtRoute(routeName, routeValues: null, value: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="AcceptedAtRouteResult"/> object that produces an Accepted (202) response.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="routeName">The name of the route to use for generating the URL.</param>
|
||||||
|
///<param name="routeValues">The route data to use for generating the URL.</param>
|
||||||
|
/// <returns>The created <see cref="AcceptedAtRouteResult"/> for the response.</returns>
|
||||||
|
[NonAction]
|
||||||
|
public virtual AcceptedAtRouteResult AcceptedAtRoute(string routeName, object routeValues)
|
||||||
|
{
|
||||||
|
return AcceptedAtRoute(routeName, routeValues, value: null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="AcceptedAtRouteResult"/> object that produces an Accepted (202) response.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="routeValues">The route data to use for generating the URL.</param>
|
||||||
|
/// <param name="value">The optional content value to format in the entity body; may be null.</param>
|
||||||
|
/// <returns>The created <see cref="AcceptedAtRouteResult"/> for the response.</returns>
|
||||||
|
[NonAction]
|
||||||
|
public virtual AcceptedAtRouteResult AcceptedAtRoute(object routeValues, object value)
|
||||||
|
{
|
||||||
|
return AcceptedAtRoute(routeName: null, routeValues: routeValues, value: value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a <see cref="AcceptedAtRouteResult"/> object that produces an Accepted (202) response.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="routeName">The name of the route to use for generating the URL.</param>
|
||||||
|
/// <param name="routeValues">The route data to use for generating the URL.</param>
|
||||||
|
/// <param name="value">The optional content value to format in the entity body; may be null.</param>
|
||||||
|
/// <returns>The created <see cref="AcceptedAtRouteResult"/> for the response.</returns>
|
||||||
|
[NonAction]
|
||||||
|
public virtual AcceptedAtRouteResult AcceptedAtRoute(string routeName, object routeValues, object value)
|
||||||
|
{
|
||||||
|
return new AcceptedAtRouteResult(routeName, routeValues, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a <see cref="ChallengeResult"/>.
|
/// Creates a <see cref="ChallengeResult"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,188 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Buffers;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Internal;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Routing;
|
||||||
|
using Microsoft.AspNetCore.Routing;
|
||||||
|
using Microsoft.AspNetCore.Testing;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging.Testing;
|
||||||
|
using Moq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc
|
||||||
|
{
|
||||||
|
public class AcceptedAtActionResultTests
|
||||||
|
{
|
||||||
|
public static TheoryData<object> ValuesData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new TheoryData<object>
|
||||||
|
{
|
||||||
|
null,
|
||||||
|
"Test string",
|
||||||
|
new object(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ValuesData))]
|
||||||
|
public void Constructor_InitializesStatusCodeAndValue(object value)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var url = "testAction";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = new AcceptedAtActionResult(
|
||||||
|
actionName: url,
|
||||||
|
controllerName: null,
|
||||||
|
routeValues: null,
|
||||||
|
value: value);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(StatusCodes.Status202Accepted, result.StatusCode);
|
||||||
|
Assert.Same(value, result.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ValuesData))]
|
||||||
|
public async Task ExecuteResultAsync_SetsObjectValueOfFormatter(object value)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var url = "testAction";
|
||||||
|
var formatter = CreateMockFormatter();
|
||||||
|
var httpContext = GetHttpContext(formatter);
|
||||||
|
object actual = null;
|
||||||
|
formatter.Setup(f => f.WriteAsync(It.IsAny<OutputFormatterWriteContext>()))
|
||||||
|
.Callback((OutputFormatterWriteContext context) => actual = context.Object)
|
||||||
|
.Returns(Task.FromResult(0));
|
||||||
|
|
||||||
|
var actionContext = GetActionContext(httpContext);
|
||||||
|
var urlHelper = GetMockUrlHelper(url);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = new AcceptedAtActionResult(
|
||||||
|
actionName: url,
|
||||||
|
controllerName: null,
|
||||||
|
routeValues: null,
|
||||||
|
value: value);
|
||||||
|
|
||||||
|
result.UrlHelper = urlHelper;
|
||||||
|
await result.ExecuteResultAsync(actionContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Same(value, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ExecuteResultAsync_SetsStatusCodeAndLocationHeader()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expectedUrl = "testAction";
|
||||||
|
var formatter = CreateMockFormatter();
|
||||||
|
var httpContext = GetHttpContext(formatter);
|
||||||
|
var actionContext = GetActionContext(httpContext);
|
||||||
|
var urlHelper = GetMockUrlHelper(expectedUrl);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = new AcceptedAtActionResult(
|
||||||
|
actionName: expectedUrl,
|
||||||
|
controllerName: null,
|
||||||
|
routeValues: null,
|
||||||
|
value: null);
|
||||||
|
|
||||||
|
result.UrlHelper = urlHelper;
|
||||||
|
await result.ExecuteResultAsync(actionContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(StatusCodes.Status202Accepted, httpContext.Response.StatusCode);
|
||||||
|
Assert.Equal(expectedUrl, httpContext.Response.Headers["Location"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ExecuteResultAsync_ThrowsIfActionUrlIsNull()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var formatter = CreateMockFormatter();
|
||||||
|
var httpContext = GetHttpContext(formatter);
|
||||||
|
var actionContext = GetActionContext(httpContext);
|
||||||
|
var urlHelper = GetMockUrlHelper(returnValue: null);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = new AcceptedAtActionResult(
|
||||||
|
actionName: null,
|
||||||
|
controllerName: null,
|
||||||
|
routeValues: null,
|
||||||
|
value: null);
|
||||||
|
|
||||||
|
result.UrlHelper = urlHelper;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
await ExceptionAssert.ThrowsAsync<InvalidOperationException>(() =>
|
||||||
|
result.ExecuteResultAsync(actionContext),
|
||||||
|
"No route matches the supplied values.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ActionContext GetActionContext(HttpContext httpContext)
|
||||||
|
{
|
||||||
|
var routeData = new RouteData();
|
||||||
|
routeData.Routers.Add(Mock.Of<IRouter>());
|
||||||
|
|
||||||
|
return new ActionContext(
|
||||||
|
httpContext,
|
||||||
|
routeData,
|
||||||
|
new ActionDescriptor());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HttpContext GetHttpContext(Mock<IOutputFormatter> formatter)
|
||||||
|
{
|
||||||
|
var httpContext = new DefaultHttpContext();
|
||||||
|
httpContext.RequestServices = CreateServices(formatter);
|
||||||
|
return httpContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Mock<IOutputFormatter> CreateMockFormatter()
|
||||||
|
{
|
||||||
|
var formatter = new Mock<IOutputFormatter>
|
||||||
|
{
|
||||||
|
CallBase = true
|
||||||
|
};
|
||||||
|
formatter.Setup(f => f.CanWriteResult(It.IsAny<OutputFormatterWriteContext>())).Returns(true);
|
||||||
|
|
||||||
|
return formatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IServiceProvider CreateServices(Mock<IOutputFormatter> formatter)
|
||||||
|
{
|
||||||
|
var options = new TestOptionsManager<MvcOptions>();
|
||||||
|
options.Value.OutputFormatters.Add(formatter.Object);
|
||||||
|
var services = new ServiceCollection();
|
||||||
|
services.AddSingleton(new ObjectResultExecutor(
|
||||||
|
options,
|
||||||
|
new TestHttpResponseStreamWriterFactory(),
|
||||||
|
NullLoggerFactory.Instance));
|
||||||
|
|
||||||
|
return services.BuildServiceProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IUrlHelper GetMockUrlHelper(string returnValue)
|
||||||
|
{
|
||||||
|
var urlHelper = new Mock<IUrlHelper>();
|
||||||
|
urlHelper.Setup(o => o.Action(It.IsAny<UrlActionContext>())).Returns(returnValue);
|
||||||
|
|
||||||
|
return urlHelper.Object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,201 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Buffers;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Internal;
|
||||||
|
using Microsoft.AspNetCore.Routing;
|
||||||
|
using Microsoft.AspNetCore.Testing;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging.Testing;
|
||||||
|
using Moq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc
|
||||||
|
{
|
||||||
|
public class AcceptedAtRouteResultTests
|
||||||
|
{
|
||||||
|
public static TheoryData<object> ValuesData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new TheoryData<object>
|
||||||
|
{
|
||||||
|
null,
|
||||||
|
"Test string",
|
||||||
|
new object(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ValuesData))]
|
||||||
|
public void Constructor_InitializesStatusCodeAndValue(object value)
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var result = new AcceptedAtRouteResult(
|
||||||
|
routeName: null,
|
||||||
|
routeValues: null,
|
||||||
|
value: value);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(StatusCodes.Status202Accepted, result.StatusCode);
|
||||||
|
Assert.Same(value, result.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ValuesData))]
|
||||||
|
public async Task ExecuteResultAsync_SetsObjectValueOfFormatter(object value)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var url = "testAction";
|
||||||
|
var formatter = CreateMockFormatter();
|
||||||
|
var httpContext = GetHttpContext(formatter);
|
||||||
|
object actual = null;
|
||||||
|
formatter.Setup(f => f.WriteAsync(It.IsAny<OutputFormatterWriteContext>()))
|
||||||
|
.Callback((OutputFormatterWriteContext context) => actual = context.Object)
|
||||||
|
.Returns(Task.FromResult(0));
|
||||||
|
|
||||||
|
var actionContext = GetActionContext(httpContext);
|
||||||
|
var urlHelper = GetMockUrlHelper(url);
|
||||||
|
var routeValues = new RouteValueDictionary(new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ "test", "case" },
|
||||||
|
{ "sample", "route" }
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = new AcceptedAtRouteResult(
|
||||||
|
routeName: "sample",
|
||||||
|
routeValues: routeValues,
|
||||||
|
value: value);
|
||||||
|
result.UrlHelper = urlHelper;
|
||||||
|
await result.ExecuteResultAsync(actionContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Same(value, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TheoryData<object> AcceptedAtRouteData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new TheoryData<object>
|
||||||
|
{
|
||||||
|
null,
|
||||||
|
new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ "hello", "world" }
|
||||||
|
},
|
||||||
|
new RouteValueDictionary(
|
||||||
|
new Dictionary<string, string>()
|
||||||
|
{
|
||||||
|
{ "test", "case" },
|
||||||
|
{ "sample", "route" }
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(AcceptedAtRouteData))]
|
||||||
|
public async Task ExecuteResultAsync_SetsStatusCodeAndLocationHeader(object values)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expectedUrl = "testAction";
|
||||||
|
var formatter = CreateMockFormatter();
|
||||||
|
var httpContext = GetHttpContext(formatter);
|
||||||
|
var actionContext = GetActionContext(httpContext);
|
||||||
|
var urlHelper = GetMockUrlHelper(expectedUrl);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = new AcceptedAtRouteResult(routeValues: values, value: null);
|
||||||
|
result.UrlHelper = urlHelper;
|
||||||
|
await result.ExecuteResultAsync(actionContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(StatusCodes.Status202Accepted, httpContext.Response.StatusCode);
|
||||||
|
Assert.Equal(expectedUrl, httpContext.Response.Headers["Location"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ExecuteResultAsync_ThrowsIfRouteUrlIsNull()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var formatter = CreateMockFormatter();
|
||||||
|
var httpContext = GetHttpContext(formatter);
|
||||||
|
var actionContext = GetActionContext(httpContext);
|
||||||
|
var urlHelper = GetMockUrlHelper(returnValue: null);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = new AcceptedAtRouteResult(
|
||||||
|
routeName: null,
|
||||||
|
routeValues: new Dictionary<string, object>(),
|
||||||
|
value: null);
|
||||||
|
|
||||||
|
result.UrlHelper = urlHelper;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
await ExceptionAssert.ThrowsAsync<InvalidOperationException>(() =>
|
||||||
|
result.ExecuteResultAsync(actionContext),
|
||||||
|
"No route matches the supplied values.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ActionContext GetActionContext(HttpContext httpContext)
|
||||||
|
{
|
||||||
|
var routeData = new RouteData();
|
||||||
|
routeData.Routers.Add(Mock.Of<IRouter>());
|
||||||
|
|
||||||
|
return new ActionContext(
|
||||||
|
httpContext,
|
||||||
|
routeData,
|
||||||
|
new ActionDescriptor());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HttpContext GetHttpContext(Mock<IOutputFormatter> formatter)
|
||||||
|
{
|
||||||
|
var httpContext = new DefaultHttpContext();
|
||||||
|
httpContext.RequestServices = CreateServices(formatter);
|
||||||
|
return httpContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Mock<IOutputFormatter> CreateMockFormatter()
|
||||||
|
{
|
||||||
|
var formatter = new Mock<IOutputFormatter>
|
||||||
|
{
|
||||||
|
CallBase = true
|
||||||
|
};
|
||||||
|
formatter.Setup(f => f.CanWriteResult(It.IsAny<OutputFormatterWriteContext>())).Returns(true);
|
||||||
|
|
||||||
|
return formatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IServiceProvider CreateServices(Mock<IOutputFormatter> formatter)
|
||||||
|
{
|
||||||
|
var options = new TestOptionsManager<MvcOptions>();
|
||||||
|
options.Value.OutputFormatters.Add(formatter.Object);
|
||||||
|
var services = new ServiceCollection();
|
||||||
|
services.AddSingleton(new ObjectResultExecutor(
|
||||||
|
options,
|
||||||
|
new TestHttpResponseStreamWriterFactory(),
|
||||||
|
NullLoggerFactory.Instance));
|
||||||
|
|
||||||
|
return services.BuildServiceProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IUrlHelper GetMockUrlHelper(string returnValue)
|
||||||
|
{
|
||||||
|
var urlHelper = new Mock<IUrlHelper>();
|
||||||
|
urlHelper.Setup(o => o.Link(It.IsAny<string>(), It.IsAny<object>())).Returns(returnValue);
|
||||||
|
|
||||||
|
return urlHelper.Object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,149 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Buffers;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Internal;
|
||||||
|
using Microsoft.AspNetCore.Routing;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging.Testing;
|
||||||
|
using Moq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNetCore.Mvc.Core.Test
|
||||||
|
{
|
||||||
|
public class AcceptedResultTests
|
||||||
|
{
|
||||||
|
public static TheoryData<object> ValuesData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new TheoryData<object>
|
||||||
|
{
|
||||||
|
null,
|
||||||
|
"Test string",
|
||||||
|
new object(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ValuesData))]
|
||||||
|
public void Constructor_InitializesStatusCodeAndValue(object value)
|
||||||
|
{
|
||||||
|
// Arrange & Act
|
||||||
|
var result = new AcceptedResult("testlocation", value);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(StatusCodes.Status202Accepted, result.StatusCode);
|
||||||
|
Assert.Same(value, result.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(ValuesData))]
|
||||||
|
public async Task ExecuteResultAsync_SetsObjectValueOfFormatter(object value)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var location = "/test/";
|
||||||
|
var formatter = CreateMockFormatter();
|
||||||
|
var httpContext = GetHttpContext(formatter);
|
||||||
|
object actual = null;
|
||||||
|
formatter.Setup(f => f.WriteAsync(It.IsAny<OutputFormatterWriteContext>()))
|
||||||
|
.Callback((OutputFormatterWriteContext context) => actual = context.Object)
|
||||||
|
.Returns(Task.FromResult(0));
|
||||||
|
|
||||||
|
var actionContext = GetActionContext(httpContext);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = new AcceptedResult(location, value);
|
||||||
|
await result.ExecuteResultAsync(actionContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Same(value, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ExecuteResultAsync_SetsStatusCodeAndLocationHeader()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var location = "/test/";
|
||||||
|
var formatter = CreateMockFormatter();
|
||||||
|
var httpContext = GetHttpContext(formatter);
|
||||||
|
var actionContext = GetActionContext(httpContext);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = new AcceptedResult(location, "testInput");
|
||||||
|
await result.ExecuteResultAsync(actionContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(StatusCodes.Status202Accepted, httpContext.Response.StatusCode);
|
||||||
|
Assert.Equal(location, httpContext.Response.Headers["Location"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ExecuteResultAsync_OverwritesLocationHeader()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var location = "/test/";
|
||||||
|
var formatter = CreateMockFormatter();
|
||||||
|
var httpContext = GetHttpContext(formatter);
|
||||||
|
var actionContext = GetActionContext(httpContext);
|
||||||
|
httpContext.Response.Headers["Location"] = "/different/location/";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = new AcceptedResult(location, "testInput");
|
||||||
|
await result.ExecuteResultAsync(actionContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(StatusCodes.Status202Accepted, httpContext.Response.StatusCode);
|
||||||
|
Assert.Equal(location, httpContext.Response.Headers["Location"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ActionContext GetActionContext(HttpContext httpContext)
|
||||||
|
{
|
||||||
|
var routeData = new RouteData();
|
||||||
|
routeData.Routers.Add(Mock.Of<IRouter>());
|
||||||
|
return new ActionContext(
|
||||||
|
httpContext,
|
||||||
|
routeData,
|
||||||
|
new ActionDescriptor());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HttpContext GetHttpContext(Mock<IOutputFormatter> formatter)
|
||||||
|
{
|
||||||
|
var httpContext = new DefaultHttpContext();
|
||||||
|
httpContext.RequestServices = CreateServices(formatter);
|
||||||
|
return httpContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Mock<IOutputFormatter> CreateMockFormatter()
|
||||||
|
{
|
||||||
|
var formatter = new Mock<IOutputFormatter>
|
||||||
|
{
|
||||||
|
CallBase = true
|
||||||
|
};
|
||||||
|
formatter.Setup(f => f.CanWriteResult(It.IsAny<OutputFormatterWriteContext>())).Returns(true);
|
||||||
|
|
||||||
|
return formatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IServiceProvider CreateServices(Mock<IOutputFormatter> formatter)
|
||||||
|
{
|
||||||
|
var options = new TestOptionsManager<MvcOptions>();
|
||||||
|
options.Value.OutputFormatters.Add(formatter.Object);
|
||||||
|
var services = new ServiceCollection();
|
||||||
|
services.AddSingleton(new ObjectResultExecutor(
|
||||||
|
options,
|
||||||
|
new TestHttpResponseStreamWriterFactory(),
|
||||||
|
NullLoggerFactory.Instance));
|
||||||
|
|
||||||
|
return services.BuildServiceProvider();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -566,6 +566,185 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
|
||||||
Assert.Equal(expected, result.RouteValues);
|
Assert.Equal(expected, result.RouteValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Accepted_SetsStatusCode()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var controller = new TestableController();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = controller.Accepted();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsType<AcceptedResult>(result);
|
||||||
|
Assert.Equal(StatusCodes.Status202Accepted, result.StatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Accepted_SetsValue()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var controller = new TestableController();
|
||||||
|
var value = new object();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = controller.Accepted(value);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsType<AcceptedResult>(result);
|
||||||
|
Assert.Equal(StatusCodes.Status202Accepted, result.StatusCode);
|
||||||
|
Assert.Same(value, result.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Accepted_StringUri_SetsAcceptedLocation()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var controller = new TestableController();
|
||||||
|
var uri = "http://test/url";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = controller.Accepted(uri);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsType<AcceptedResult>(result);
|
||||||
|
Assert.Equal(StatusCodes.Status202Accepted, result.StatusCode);
|
||||||
|
Assert.Same(uri, result.Location);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Accepted_AbsoluteUri_SetsAcceptedLocation()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var controller = new TestableController();
|
||||||
|
var uri = new Uri("http://test/url");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = controller.Accepted(uri);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsType<AcceptedResult>(result);
|
||||||
|
Assert.Equal(StatusCodes.Status202Accepted, result.StatusCode);
|
||||||
|
Assert.Equal(uri.OriginalString, result.Location);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Accepted_RelativeUri_SetsAcceptedLocation()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var controller = new TestableController();
|
||||||
|
var uri = new Uri("/test/url", UriKind.Relative);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = controller.Accepted(uri);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsType<AcceptedResult>(result);
|
||||||
|
Assert.Equal(StatusCodes.Status202Accepted, result.StatusCode);
|
||||||
|
Assert.Equal(uri.OriginalString, result.Location);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AcceptedAtAction_SetsActionName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var controller = new TestableController();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = controller.AcceptedAtAction("SampleAction");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsType<AcceptedAtActionResult>(result);
|
||||||
|
Assert.Equal(StatusCodes.Status202Accepted, result.StatusCode);
|
||||||
|
Assert.Equal("SampleAction", result.ActionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("")]
|
||||||
|
[InlineData(null)]
|
||||||
|
[InlineData("SampleController")]
|
||||||
|
public void AcceptedAtAction_SetsActionController(string controllerName)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var controller = new TestableController();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = controller.AcceptedAtAction("SampleAction", controllerName);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsType<AcceptedAtActionResult>(result);
|
||||||
|
Assert.Equal(StatusCodes.Status202Accepted, result.StatusCode);
|
||||||
|
Assert.Equal("SampleAction", result.ActionName);
|
||||||
|
Assert.Equal(controllerName, result.ControllerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AcceptedAtAction_SetsActionControllerRouteValues()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var controller = new TestableController();
|
||||||
|
var expected = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "test", "case" },
|
||||||
|
{ "sample", "route" },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = controller.AcceptedAtAction(
|
||||||
|
"SampleAction",
|
||||||
|
"SampleController",
|
||||||
|
new RouteValueDictionary(expected));
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsType<AcceptedAtActionResult>(result);
|
||||||
|
Assert.Equal(StatusCodes.Status202Accepted, result.StatusCode);
|
||||||
|
Assert.Equal("SampleAction", result.ActionName);
|
||||||
|
Assert.Equal("SampleController", result.ControllerName);
|
||||||
|
Assert.Equal(expected, result.RouteValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AcceptedAtRoute_SetsRouteValues()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var controller = new TestableController();
|
||||||
|
var expected = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "test", "case" },
|
||||||
|
{ "sample", "route" },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = controller.AcceptedAtRoute(new RouteValueDictionary(expected));
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsType<AcceptedAtRouteResult>(result);
|
||||||
|
Assert.Equal(StatusCodes.Status202Accepted, result.StatusCode);
|
||||||
|
Assert.Equal(expected, result.RouteValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AcceptedAtRoute_SetsRouteNameAndValues()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var controller = new TestableController();
|
||||||
|
var routeName = "SampleRoute";
|
||||||
|
var expected = new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "test", "case" },
|
||||||
|
{ "sample", "route" },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = controller.AcceptedAtRoute(routeName, new RouteValueDictionary(expected));
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.IsType<AcceptedAtRouteResult>(result);
|
||||||
|
Assert.Equal(StatusCodes.Status202Accepted, result.StatusCode);
|
||||||
|
Assert.Same(routeName, result.RouteName);
|
||||||
|
Assert.Equal(expected, result.RouteValues);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void File_WithContents()
|
public void File_WithContents()
|
||||||
{
|
{
|
||||||
|
|
@ -1107,7 +1286,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var modelName = "mymodel";
|
var modelName = "mymodel";
|
||||||
|
|
||||||
Func<ModelMetadata, bool> propertyFilter = (m) =>
|
Func<ModelMetadata, bool> propertyFilter = (m) =>
|
||||||
string.Equals(m.PropertyName, "Include1", StringComparison.OrdinalIgnoreCase) ||
|
string.Equals(m.PropertyName, "Include1", StringComparison.OrdinalIgnoreCase) ||
|
||||||
string.Equals(m.PropertyName, "Include2", StringComparison.OrdinalIgnoreCase);
|
string.Equals(m.PropertyName, "Include2", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
|
@ -1207,7 +1386,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
|
||||||
// Arrange
|
// Arrange
|
||||||
var modelName = "mymodel";
|
var modelName = "mymodel";
|
||||||
|
|
||||||
Func<ModelMetadata, bool> propertyFilter = (m) =>
|
Func<ModelMetadata, bool> propertyFilter = (m) =>
|
||||||
string.Equals(m.PropertyName, "Include1", StringComparison.OrdinalIgnoreCase) ||
|
string.Equals(m.PropertyName, "Include1", StringComparison.OrdinalIgnoreCase) ||
|
||||||
string.Equals(m.PropertyName, "Include2", StringComparison.OrdinalIgnoreCase);
|
string.Equals(m.PropertyName, "Include2", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
|
@ -1446,7 +1625,7 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
|
||||||
var binder = new StubModelBinder();
|
var binder = new StubModelBinder();
|
||||||
var controller = GetController(binder, valueProvider: null);
|
var controller = GetController(binder, valueProvider: null);
|
||||||
controller.ObjectValidator = new DefaultObjectValidator(
|
controller.ObjectValidator = new DefaultObjectValidator(
|
||||||
controller.MetadataProvider,
|
controller.MetadataProvider,
|
||||||
new[] { provider.Object });
|
new[] { provider.Object });
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,26 @@ namespace Microsoft.AspNetCore.Mvc
|
||||||
Assert.Equal(StatusCodes.Status201Created, createdResult.StatusCode);
|
Assert.Equal(StatusCodes.Status201Created, createdResult.StatusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("/Accepted_1", "<html>AcceptedBody</html>")]
|
||||||
|
[InlineData("/Accepted_2", null)]
|
||||||
|
public void ControllerAccepted_InvokedInUnitTests(string uri, string content)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var controller = new TestabilityController();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = controller.Accepted_Action(uri, content);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
|
||||||
|
var acceptedResult = Assert.IsType<AcceptedResult>(result);
|
||||||
|
Assert.Equal(uri, acceptedResult.Location);
|
||||||
|
Assert.Equal(content, acceptedResult.Value);
|
||||||
|
Assert.Equal(StatusCodes.Status202Accepted, acceptedResult.StatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ControllerFileContent_InvokedInUnitTests()
|
public void ControllerFileContent_InvokedInUnitTests()
|
||||||
{
|
{
|
||||||
|
|
@ -335,6 +355,42 @@ namespace Microsoft.AspNetCore.Mvc
|
||||||
Assert.Null(createdAtRouteResult.Value);
|
Assert.Null(createdAtRouteResult.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ControllerAcceptedAtRoute_InvokedInUnitTests()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var controller = new TestabilityController();
|
||||||
|
var routeName = "RouteName_1";
|
||||||
|
var routeValues = new Dictionary<string, object>() { { "route", "sample" } };
|
||||||
|
var value = new { Value = "Value_1" };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = controller.AcceptedAtRoute_Action(routeName, routeValues, value);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
|
||||||
|
var acceptedAtRouteResult = Assert.IsType<AcceptedAtRouteResult>(result);
|
||||||
|
Assert.Equal(routeName, acceptedAtRouteResult.RouteName);
|
||||||
|
Assert.Single(acceptedAtRouteResult.RouteValues);
|
||||||
|
Assert.Equal("sample", acceptedAtRouteResult.RouteValues["route"]);
|
||||||
|
Assert.Same(value,acceptedAtRouteResult.Value);
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
controller = new TestabilityController();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
result = controller.AcceptedAtRoute_Action(null, null, null);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
|
||||||
|
acceptedAtRouteResult = Assert.IsType<AcceptedAtRouteResult>(result);
|
||||||
|
Assert.Null(acceptedAtRouteResult.RouteName);
|
||||||
|
Assert.Null(acceptedAtRouteResult.RouteValues);
|
||||||
|
Assert.Null(acceptedAtRouteResult.Value);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ControllerCreatedAtAction_InvokedInUnitTests()
|
public void ControllerCreatedAtAction_InvokedInUnitTests()
|
||||||
{
|
{
|
||||||
|
|
@ -374,6 +430,45 @@ namespace Microsoft.AspNetCore.Mvc
|
||||||
Assert.Null(createdAtActionResult.RouteValues);
|
Assert.Null(createdAtActionResult.RouteValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void ControllerAcceptedAtAction_InvokedInUnitTests()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var controller = new TestabilityController();
|
||||||
|
var actionName = "ActionName_1";
|
||||||
|
var controllerName = "ControllerName_1";
|
||||||
|
var routeValues = new Dictionary<string, object>() { { "route", "sample" } };
|
||||||
|
var value = new { Value = "Value_1" };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = controller.AcceptedAtAction_Action(actionName, controllerName, routeValues, value);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
|
||||||
|
var acceptedAtActionResult = Assert.IsType<AcceptedAtActionResult>(result);
|
||||||
|
Assert.Equal(actionName, acceptedAtActionResult.ActionName);
|
||||||
|
Assert.Equal(controllerName, acceptedAtActionResult.ControllerName);
|
||||||
|
Assert.Single(acceptedAtActionResult.RouteValues);
|
||||||
|
Assert.Equal("sample", acceptedAtActionResult.RouteValues["route"]);
|
||||||
|
Assert.Same(value, acceptedAtActionResult.Value);
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
controller = new TestabilityController();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
result = controller.AcceptedAtAction_Action(null, null, null, null);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(result);
|
||||||
|
|
||||||
|
acceptedAtActionResult = Assert.IsType<AcceptedAtActionResult>(result);
|
||||||
|
Assert.Null(acceptedAtActionResult.ActionName);
|
||||||
|
Assert.Null(acceptedAtActionResult.ControllerName);
|
||||||
|
Assert.Null(acceptedAtActionResult.Value);
|
||||||
|
Assert.Null(acceptedAtActionResult.RouteValues);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ControllerRedirectToRoute_InvokedInUnitTests()
|
public void ControllerRedirectToRoute_InvokedInUnitTests()
|
||||||
{
|
{
|
||||||
|
|
@ -628,6 +723,11 @@ namespace Microsoft.AspNetCore.Mvc
|
||||||
return Created(uri, data);
|
return Created(uri, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IActionResult Accepted_Action(string uri, object data)
|
||||||
|
{
|
||||||
|
return Accepted(uri, data);
|
||||||
|
}
|
||||||
|
|
||||||
public IActionResult FileContent_Action(string content, string contentType, string fileName)
|
public IActionResult FileContent_Action(string content, string contentType, string fileName)
|
||||||
{
|
{
|
||||||
var contentArray = Encoding.UTF8.GetBytes(content);
|
var contentArray = Encoding.UTF8.GetBytes(content);
|
||||||
|
|
@ -675,6 +775,16 @@ namespace Microsoft.AspNetCore.Mvc
|
||||||
return CreatedAtRoute(routeName, routeValues, value);
|
return CreatedAtRoute(routeName, routeValues, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IActionResult AcceptedAtAction_Action(string actionName, string controllerName, object routeValues, object value)
|
||||||
|
{
|
||||||
|
return AcceptedAtAction(actionName, controllerName, routeValues, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IActionResult AcceptedAtRoute_Action(string routeName, object routeValues, object value)
|
||||||
|
{
|
||||||
|
return AcceptedAtRoute(routeName, routeValues, value);
|
||||||
|
}
|
||||||
|
|
||||||
public IActionResult HttpBadRequest_Action()
|
public IActionResult HttpBadRequest_Action()
|
||||||
{
|
{
|
||||||
return BadRequest();
|
return BadRequest();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue