// 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);
}
}
}
}