44using System ;
55using Microsoft . AspNetCore . Mvc . ApiExplorer ;
66using Microsoft . AspNetCore . Mvc . Formatters ;
7+ using Microsoft . Net . Http . Headers ;
78
89namespace Microsoft . AspNetCore . Mvc
910{
@@ -33,6 +34,37 @@ public ProducesResponseTypeAttribute(Type type, int statusCode)
3334 Type = type ?? throw new ArgumentNullException ( nameof ( type ) ) ;
3435 StatusCode = statusCode ;
3536 IsResponseTypeSetByDefault = false ;
37+ ContentTypes = new ( ) ;
38+ }
39+
40+ /// <summary>
41+ /// Initializes an instance of <see cref="ProducesResponseTypeAttribute"/>.
42+ /// </summary>
43+ /// <param name="type">The <see cref="Type"/> of object that is going to be written in the response.</param>
44+ /// <param name="statusCode">The HTTP response status code.</param>
45+ /// <param name="contentType">The content type associated with the response.</param>
46+ /// <param name="additionalContentTypes">Additional content types supported by the response.</param>
47+ public ProducesResponseTypeAttribute ( Type type , int statusCode , string ? contentType , params string [ ] additionalContentTypes )
48+ {
49+ Type = type ?? throw new ArgumentNullException ( nameof ( type ) ) ;
50+ StatusCode = statusCode ;
51+ IsResponseTypeSetByDefault = false ;
52+
53+ if ( ! string . IsNullOrEmpty ( contentType ) )
54+ {
55+ MediaTypeHeaderValue . Parse ( contentType ) ;
56+ for ( var i = 0 ; i < additionalContentTypes . Length ; i ++ )
57+ {
58+ MediaTypeHeaderValue . Parse ( additionalContentTypes [ i ] ) ;
59+ }
60+
61+ ContentTypes = GetContentTypes ( contentType , additionalContentTypes ) ;
62+ }
63+ else
64+ {
65+ ContentTypes = new ( ) ;
66+ }
67+
3668 }
3769
3870 /// <summary>
@@ -45,6 +77,11 @@ public ProducesResponseTypeAttribute(Type type, int statusCode)
4577 /// </summary>
4678 public int StatusCode { get ; set ; }
4779
80+ /// <summary>
81+ /// Gets or sets the content types supported by the response.
82+ /// </summary>
83+ public MediaTypeCollection ContentTypes { get ; set ; }
84+
4885 /// <summary>
4986 /// Used to distinguish a `Type` set by default in the constructor versus
5087 /// one provided by the user.
@@ -58,9 +95,33 @@ public ProducesResponseTypeAttribute(Type type, int statusCode)
5895 internal bool IsResponseTypeSetByDefault { get ; }
5996
6097 /// <inheritdoc />
61- void IApiResponseMetadataProvider . SetContentTypes ( MediaTypeCollection contentTypes )
98+ public void SetContentTypes ( MediaTypeCollection contentTypes )
6299 {
63- // Users are supposed to use the 'Produces' attribute to set the content types that an action can support.
100+ contentTypes . Clear ( ) ;
101+ foreach ( var contentType in ContentTypes )
102+ {
103+ contentTypes . Add ( contentType ) ;
104+ }
105+ }
106+
107+ private MediaTypeCollection GetContentTypes ( string contentType , string [ ] additionalContentTypes )
108+ {
109+ List < string > completeContentTypes = new ( additionalContentTypes . Length + 1 ) ;
110+ completeContentTypes . Add ( contentType ) ;
111+ completeContentTypes . AddRange ( additionalContentTypes ) ;
112+ MediaTypeCollection contentTypes = new ( ) ;
113+ foreach ( var type in completeContentTypes )
114+ {
115+ var mediaType = new MediaType ( type ) ;
116+ if ( mediaType . HasWildcard )
117+ {
118+ throw new InvalidOperationException ( "Content types with wild cards are not supported." ) ;
119+ }
120+
121+ contentTypes . Add ( type ) ;
122+ }
123+
124+ return contentTypes ;
64125 }
65126 }
66127}
0 commit comments