// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using System; using System.Collections.Generic; using System.Diagnostics.Contracts; using Microsoft.Owin; using System.Net; using System.Net.Http; using System.Net.Http.Formatting; using System.Threading; using System.Threading.Tasks; using System.Web.Http.Properties; using System.Linq; namespace Microsoft.AspNet.Mvc { /// Represents an action result that performs content negotiation. /// The type of content in the entity body. internal class NegotiatedContentResult : IActionResult { /// /// Initializes a new instance of the class with the values provided. /// /// The HTTP status code for the response message. /// The content value to negotiate and format in the entity body. /// The content negotiator to handle content negotiation. /// The request message which led to this result. /// The formatters to use to negotiate and format the content. public NegotiatedContentResult(HttpStatusCode statusCode, Type declaredType, object content, IOwinContentNegotiator contentNegotiator, IOwinContext owinContext, IEnumerable formatters) { Contract.Assert(content != null); Contract.Assert(declaredType != null); Contract.Assert(owinContext != null); Contract.Assert(formatters != null); StatusCode = statusCode; DeclaredType = declaredType; Content = content; CurrentOwinContext = owinContext; Formatters = formatters; ContentNegotiator = contentNegotiator; } /// Gets the HTTP status code for the response message. public HttpStatusCode StatusCode { get; private set; } public Type DeclaredType { get; private set; } /// Gets the content value to negotiate and format in the entity body. public object Content { get; private set; } /// Gets the content negotiator to handle content negotiation. public IOwinContentNegotiator ContentNegotiator { get; private set; } /// Gets the request message which led to this result. public IOwinContext CurrentOwinContext { get; private set; } /// Gets the formatters to use to negotiate and format the content. public IEnumerable Formatters { get; private set; } /// public virtual Task ExecuteResultAsync(RequestContext context) { // Run content negotiation. ContentNegotiationResult result = ContentNegotiator.Negotiate(DeclaredType, CurrentOwinContext, Formatters); if (result == null) { // A null result from content negotiation indicates that the response should be a 406. CurrentOwinContext.Response.StatusCode = (int)HttpStatusCode.NotAcceptable; return Task.FromResult(false); } else { IOwinResponse response = CurrentOwinContext.Response; response.StatusCode = (int)StatusCode; Contract.Assert(result.Formatter != null); var objectContent = new ObjectContent(DeclaredType, Content, result.Formatter, result.MediaType); // Copy non-content headers IDictionary responseHeaders = response.Headers; foreach (KeyValuePair header in response.Headers) { responseHeaders[header.Key] = header.Value.AsArray(); } // Copy content headers foreach (KeyValuePair> contentHeader in objectContent.Headers) { responseHeaders[contentHeader.Key] = contentHeader.Value.AsArray(); } return objectContent.CopyToAsync(response.Body); } } } }