// 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.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.Mvc.ApiExplorer;
using Microsoft.AspNet.Mvc.Core;
using Microsoft.Framework.Internal;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
{
///
/// Specifies the allowed content types and the type of the value returned by the action
/// which can be used to select a formatter while executing .
///
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class ProducesAttribute : ResultFilterAttribute, IApiResponseMetadataProvider
{
///
/// Initializes an instance of .
///
/// The of object that is going to be written in the response.
public ProducesAttribute([NotNull] Type type)
{
Type = type;
ContentTypes = new List();
}
///
/// Initializes an instance of with allowed content types.
///
/// The allowed content type for a response.
/// Additional allowed content types for a response.
public ProducesAttribute([NotNull] string contentType, params string[] additionalContentTypes)
{
ContentTypes = GetContentTypes(contentType, additionalContentTypes);
}
public Type Type { get; set; }
public IList ContentTypes { get; set; }
public override void OnResultExecuting([NotNull] ResultExecutingContext context)
{
base.OnResultExecuting(context);
var objectResult = context.Result as ObjectResult;
if (objectResult != null)
{
// Check if there are any IFormatFilter in the pipeline, and if any of them is active. If there is one,
// do not override the content type value.
if (context.Filters.OfType().All(f => !f.IsActive))
{
SetContentTypes(objectResult.ContentTypes);
}
}
}
private List GetContentTypes(string firstArg, string[] args)
{
var completeArgs = new List();
completeArgs.Add(firstArg);
completeArgs.AddRange(args);
var contentTypes = new List();
foreach (var arg in completeArgs)
{
var contentType = MediaTypeHeaderValue.Parse(arg);
if (contentType.MatchesAllSubTypes || contentType.MatchesAllTypes)
{
throw new InvalidOperationException(
Resources.FormatMatchAllContentTypeIsNotAllowed(arg));
}
contentTypes.Add(contentType);
}
return contentTypes;
}
public void SetContentTypes(IList contentTypes)
{
contentTypes.Clear();
foreach (var contentType in ContentTypes)
{
contentTypes.Add(contentType);
}
}
}
}