// 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.Diagnostics.Contracts; using System.Net; using System.Net.Http; using System.Threading; using System.Threading.Tasks; using System.Web.Http.Properties; namespace System.Web.Http.Results { /// Represents an action result that returns a specified HTTP status code. public class StatusCodeResult : IHttpActionResult { private readonly HttpStatusCode _statusCode; private readonly IDependencyProvider _dependencies; /// Initializes a new instance of the class. /// The HTTP status code for the response message. /// The request message which led to this result. public StatusCodeResult(HttpStatusCode statusCode, HttpRequestMessage request) : this(statusCode, new DirectDependencyProvider(request)) { } /// Initializes a new instance of the class. /// The HTTP status code for the response message. /// The controller from which to obtain the dependencies needed for execution. public StatusCodeResult(HttpStatusCode statusCode, ApiController controller) : this(statusCode, new ApiControllerDependencyProvider(controller)) { } private StatusCodeResult(HttpStatusCode statusCode, IDependencyProvider dependencies) { Contract.Assert(dependencies != null); _statusCode = statusCode; _dependencies = dependencies; } /// Gets the HTTP status code for the response message. public HttpStatusCode StatusCode { get { return _statusCode; } } /// Gets the request message which led to this result. public HttpRequestMessage Request { get { return _dependencies.Request; } } /// public virtual Task ExecuteAsync(CancellationToken cancellationToken) { return Task.FromResult(Execute()); } private HttpResponseMessage Execute() { return Execute(_statusCode, _dependencies.Request); } internal static HttpResponseMessage Execute(HttpStatusCode statusCode, HttpRequestMessage request) { HttpResponseMessage response = new HttpResponseMessage(statusCode); try { response.RequestMessage = request; } catch { response.Dispose(); throw; } return response; } /// Defines a provider for dependencies that are not always directly available. /// /// This abstraction supports the unit testing scenario of creating the result without creating a request /// message. (The ApiController provider implementation does lazy evaluation to make that scenario work.) /// internal interface IDependencyProvider { HttpRequestMessage Request { get; } } internal sealed class DirectDependencyProvider : IDependencyProvider { private readonly HttpRequestMessage _request; public DirectDependencyProvider(HttpRequestMessage request) { if (request == null) { throw new ArgumentNullException("request"); } _request = request; } public HttpRequestMessage Request { get { return _request; } } } internal sealed class ApiControllerDependencyProvider : IDependencyProvider { private readonly ApiController _controller; private HttpRequestMessage _request; public ApiControllerDependencyProvider(ApiController controller) { if (controller == null) { throw new ArgumentNullException("controller"); } _controller = controller; } public HttpRequestMessage Request { get { EnsureResolved(); return _request; } } private void EnsureResolved() { if (_request == null) { HttpRequestMessage request = _controller.Request; if (request == null) { throw new InvalidOperationException(SRResources.ApiController_RequestMustNotBeNull); } _request = request; } } } } }