Skip to content
This repository was archived by the owner on Dec 14, 2018. It is now read-only.

Commit e6202a4

Browse files
committed
IOutputFormatter changes.
1 parent 73fc840 commit e6202a4

14 files changed

+188
-144
lines changed

src/Microsoft.AspNet.Mvc.Core/ActionResults/ObjectResult.cs

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class ObjectResult : ActionResult
1616
{
1717
public object Value { get; set; }
1818

19-
public List<OutputFormatter> Formatters { get; set; }
19+
public List<IOutputFormatter> Formatters { get; set; }
2020

2121
public List<MediaTypeHeaderValue> ContentTypes { get; set; }
2222

@@ -25,7 +25,7 @@ public class ObjectResult : ActionResult
2525
public ObjectResult(object value)
2626
{
2727
Value = value;
28-
Formatters = new List<OutputFormatter>();
28+
Formatters = new List<IOutputFormatter>();
2929
ContentTypes = new List<MediaTypeHeaderValue>();
3030
}
3131

@@ -47,21 +47,20 @@ public override async Task ExecuteResultAsync(ActionContext context)
4747
return;
4848
}
4949

50-
// set the content headers.
51-
selectedFormatter.SetResponseContentHeaders(formatterContext);
52-
await selectedFormatter.WriteAsync(formatterContext, CancellationToken.None);
50+
await selectedFormatter.WriteAsync(formatterContext,
51+
formatterContext.ActionContext.HttpContext.RequestAborted);
5352
}
5453

55-
public virtual OutputFormatter SelectFormatter(OutputFormatterContext formatterContext,
56-
IEnumerable<OutputFormatter> formatters)
54+
public virtual IOutputFormatter SelectFormatter(OutputFormatterContext formatterContext,
55+
IEnumerable<IOutputFormatter> formatters)
5756
{
5857
var incomingAcceptHeader = HeaderParsingHelpers.GetAcceptHeaders(
5958
formatterContext.ActionContext.HttpContext.Request.Accept);
6059
var sortedAcceptHeaders = SortMediaTypeWithQualityHeaderValues(incomingAcceptHeader)
6160
.Where(header => header.Quality != FormattingUtilities.NoMatch)
6261
.ToArray();
6362

64-
OutputFormatter selectedFormatter = null;
63+
IOutputFormatter selectedFormatter = null;
6564

6665
if (ContentTypes == null || ContentTypes.Count == 0)
6766
{
@@ -80,7 +79,7 @@ public virtual OutputFormatter SelectFormatter(OutputFormatterContext formatterC
8079
// In case the incomingContentType is null (as can be the case with get requests),
8180
// we need to pick the first formatter which
8281
// can support writing this type.
83-
var contentTypes = new [] { incomingContentType };
82+
var contentTypes = new[] { incomingContentType };
8483
selectedFormatter = SelectFormatterUsingAnyAcceptableContentType(
8584
formatterContext,
8685
formatters,
@@ -131,12 +130,12 @@ public virtual OutputFormatter SelectFormatter(OutputFormatterContext formatterC
131130
return selectedFormatter;
132131
}
133132

134-
public virtual OutputFormatter SelectFormatterUsingSortedAcceptHeaders(
133+
public virtual IOutputFormatter SelectFormatterUsingSortedAcceptHeaders(
135134
OutputFormatterContext formatterContext,
136-
IEnumerable<OutputFormatter> formatters,
135+
IEnumerable<IOutputFormatter> formatters,
137136
IEnumerable<MediaTypeHeaderValue> sortedAcceptHeaders)
138137
{
139-
OutputFormatter selectedFormatter = null;
138+
IOutputFormatter selectedFormatter = null;
140139
foreach (var contentType in sortedAcceptHeaders)
141140
{
142141
// Loop through each of the formatters and see if any one will support this
@@ -154,9 +153,9 @@ public virtual OutputFormatter SelectFormatterUsingSortedAcceptHeaders(
154153
return selectedFormatter;
155154
}
156155

157-
public virtual OutputFormatter SelectFormatterUsingAnyAcceptableContentType(
156+
public virtual IOutputFormatter SelectFormatterUsingAnyAcceptableContentType(
158157
OutputFormatterContext formatterContext,
159-
IEnumerable<OutputFormatter> formatters,
158+
IEnumerable<IOutputFormatter> formatters,
160159
IEnumerable<MediaTypeHeaderValue> acceptableContentTypes)
161160
{
162161
var selectedFormatter = formatters.FirstOrDefault(
@@ -183,9 +182,9 @@ private static MediaTypeWithQualityHeaderValue[] SortMediaTypeWithQualityHeaderV
183182
.ToArray();
184183
}
185184

186-
private IEnumerable<OutputFormatter> GetDefaultFormatters(ActionContext context)
185+
private IEnumerable<IOutputFormatter> GetDefaultFormatters(ActionContext context)
187186
{
188-
IEnumerable<OutputFormatter> formatters = null;
187+
IEnumerable<IOutputFormatter> formatters = null;
189188
if (Formatters == null || Formatters.Count == 0)
190189
{
191190
formatters = context.HttpContext

src/Microsoft.AspNet.Mvc.Core/Formatters/DefaultOutputFormattersProvider.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,17 @@ public DefaultOutputFormattersProvider(IOptionsAccessor<MvcOptions> options,
3434
}
3535

3636
/// <inheritdoc />
37-
public IReadOnlyList<OutputFormatter> OutputFormatters
37+
public IReadOnlyList<IOutputFormatter> OutputFormatters
3838
{
3939
get
4040
{
41-
var outputFormatters = new List<OutputFormatter>();
41+
var outputFormatters = new List<IOutputFormatter>();
4242
foreach (var descriptor in _descriptors)
4343
{
4444
var formatter = descriptor.OutputFormatter;
4545
if (formatter == null)
4646
{
47-
formatter = (OutputFormatter)_typeActivator.CreateInstance(_serviceProvider,
47+
formatter = (IOutputFormatter)_typeActivator.CreateInstance(_serviceProvider,
4848
descriptor.OutputFormatterType);
4949
}
5050

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
using System.Text;
8+
using System.Threading;
9+
using System.Threading.Tasks;
10+
using Microsoft.AspNet.Http;
11+
using Microsoft.AspNet.Mvc.Core;
12+
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
13+
14+
namespace Microsoft.AspNet.Mvc
15+
{
16+
/// <summary>
17+
/// Writes an object to the output stream.
18+
/// </summary>
19+
public interface IOutputFormatter
20+
{
21+
/// <summary>
22+
/// Gets the mutable collection of character encodings supported by
23+
/// this <see cref="IOutputFormatter"/> instance. The encodings are
24+
/// used when writing the data.
25+
/// </summary>
26+
List<Encoding> SupportedEncodings { get; }
27+
28+
/// <summary>
29+
/// Gets the mutable collection of <see cref="MediaTypeHeaderValue"/> elements supported by
30+
/// this <see cref="IOutputFormatter"/> instance.
31+
/// </summary>
32+
List<MediaTypeHeaderValue> SupportedMediaTypes { get; }
33+
34+
/// <summary>
35+
/// Determines whether this <see cref="IOutputFormatter"/> can serialize
36+
/// an object of the specified type.
37+
/// </summary>
38+
/// <param name="context">The formatter context associated with the call.</param>
39+
/// <param name="contentType">The desired contentType on the response.</param>
40+
/// <remarks>
41+
/// Subclasses can override this method to determine if the given content can be handled by this formatter.
42+
/// Subclasses should call the base implementation.
43+
/// </remarks>
44+
/// <returns>True if this <see cref="IOutputFormatter"/> is able to serialize the object
45+
/// represent by <paramref name="context"/>'s ObjectResult and supports the passed in
46+
/// <paramref name="contentType"/>.
47+
/// False otherwise.</returns>
48+
bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType);
49+
50+
/// <summary>
51+
/// Writes given <paramref name="value"/> to the HttpResponse <paramref name="response"/> body stream.
52+
/// </summary>
53+
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
54+
/// <returns>A Task that serializes the value to the <paramref name="context"/>'s response message.</returns>
55+
Task WriteAsync(OutputFormatterContext context, CancellationToken cancellationToken);
56+
}
57+
}

src/Microsoft.AspNet.Mvc.Core/Formatters/IOutputFormattersProvider.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
namespace Microsoft.AspNet.Mvc
77
{
88
/// <summary>
9-
/// Provides an activated collection of <see cref="OutputFormatter"/> instances.
9+
/// Provides an activated collection of <see cref="IOutputFormatter"/> instances.
1010
/// </summary>
1111
public interface IOutputFormattersProvider
1212
{
1313
/// <summary>
1414
/// Gets a collection of activated OutputFormatter instances.
1515
/// </summary>
16-
IReadOnlyList<OutputFormatter> OutputFormatters { get; }
16+
IReadOnlyList<IOutputFormatter> OutputFormatters { get; }
1717
}
1818
}

src/Microsoft.AspNet.Mvc.Core/Formatters/JsonOutputFormatter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ private JsonSerializer CreateJsonSerializer()
7373
return jsonSerializer;
7474
}
7575

76-
public override Task WriteAsync(OutputFormatterContext context,
77-
CancellationToken cancellationToken)
76+
public override Task WriteResponseBodyAsync(OutputFormatterContext context,
77+
CancellationToken cancellationToken)
7878
{
7979
cancellationToken.ThrowIfCancellationRequested();
8080
var response = context.ActionContext.HttpContext.Response;

src/Microsoft.AspNet.Mvc.Core/Formatters/OutputFormatter.cs

Lines changed: 51 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
using System.Text;
88
using System.Threading;
99
using System.Threading.Tasks;
10-
using Microsoft.AspNet.Http;
1110
using Microsoft.AspNet.Mvc.Core;
1211
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
1312

@@ -16,19 +15,12 @@ namespace Microsoft.AspNet.Mvc
1615
/// <summary>
1716
/// Writes an object to the output stream.
1817
/// </summary>
19-
public abstract class OutputFormatter
18+
public abstract class OutputFormatter : IOutputFormatter
2019
{
21-
/// <summary>
22-
/// Gets the mutable collection of character encodings supported by
23-
/// this <see cref="OutputFormatter"/> instance. The encodings are
24-
/// used when writing the data.
25-
/// </summary>
20+
/// <inheritdoc />
2621
public List<Encoding> SupportedEncodings { get; private set; }
2722

28-
/// <summary>
29-
/// Gets the mutable collection of <see cref="MediaTypeHeaderValue"/> elements supported by
30-
/// this <see cref="OutputFormatter"/> instance.
31-
/// </summary>
23+
/// <inheritdoc />
3224
public List<MediaTypeHeaderValue> SupportedMediaTypes { get; private set; }
3325

3426
/// <summary>
@@ -49,11 +41,12 @@ protected OutputFormatter()
4941
/// <returns>The <see cref="Encoding"/> to use when reading the request or writing the response.</returns>
5042
public virtual Encoding SelectCharacterEncoding(OutputFormatterContext context)
5143
{
52-
var encoding = MatchAcceptCharacterEncoding(context.ActionContext.HttpContext.Request.AcceptCharset);
44+
var request = context.ActionContext.HttpContext.Request;
45+
var encoding = MatchAcceptCharacterEncoding(request.AcceptCharset);
5346
if (encoding == null)
5447
{
5548
// Match based on request acceptHeader.
56-
var requestContentType = MediaTypeHeaderValue.Parse(context.ActionContext.HttpContext.Request.ContentType);
49+
var requestContentType = MediaTypeHeaderValue.Parse(request.ContentType);
5750
if (requestContentType != null && !string.IsNullOrEmpty(requestContentType.Charset))
5851
{
5952
var requestCharset = requestContentType.Charset;
@@ -66,54 +59,8 @@ public virtual Encoding SelectCharacterEncoding(OutputFormatterContext context)
6659
encoding = encoding ?? SupportedEncodings.FirstOrDefault();
6760
return encoding;
6861
}
69-
70-
/// <summary>
71-
/// Sets the content-type headers with charset value to the HttpResponse.
72-
/// </summary>
73-
/// <param name="context">The formatter context associated with the call.</param>
74-
public virtual void SetResponseContentHeaders(OutputFormatterContext context)
75-
{
76-
var selectedMediaType = context.SelectedContentType;
77-
78-
// If content type is not set then set it based on supported media types.
79-
selectedMediaType = selectedMediaType ?? SupportedMediaTypes.FirstOrDefault();
80-
if(selectedMediaType == null)
81-
{
82-
throw new InvalidOperationException(Resources.FormatOutputFormatterNoMediaType(GetType().FullName));
83-
}
84-
85-
if (selectedMediaType != null && selectedMediaType.Charset == null)
86-
{
87-
// If content type charset parameter is not set then set it based on the supported encodings.
88-
var selectedEncoding = SelectCharacterEncoding(context);
89-
if (selectedEncoding == null)
90-
{
91-
// No supported encoding was found so there is no way for us to start writing.
92-
throw new InvalidOperationException(Resources.FormatOutputFormatterNoEncoding(GetType().FullName));
93-
}
94-
95-
context.SelectedEncoding = selectedEncoding;
96-
selectedMediaType.Charset = selectedEncoding.WebName;
97-
}
98-
99-
var response = context.ActionContext.HttpContext.Response;
100-
response.ContentType = selectedMediaType.RawValue;
101-
}
102-
103-
/// <summary>
104-
/// Determines whether this <see cref="OutputFormatter"/> can serialize
105-
/// an object of the specified type.
106-
/// </summary>
107-
/// <param name="context">The formatter context associated with the call.</param>
108-
/// <param name="contentType">The desired contentType on the response.</param>
109-
/// <remarks>
110-
/// Subclasses can override this method to determine if the given content can be handled by this formatter.
111-
/// Subclasses should call the base implementation.
112-
/// </remarks>
113-
/// <returns>True if this <see cref="OutputFormatter"/> is able to serialize the object
114-
/// represent by <paramref name="context"/>'s ObjectResult and supports the passed in
115-
/// <paramref name="contentType"/>.
116-
/// False otherwise.</returns>
62+
63+
/// <inheritdoc />
11764
public virtual bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
11865
{
11966
MediaTypeHeaderValue mediaType = null;
@@ -140,12 +87,52 @@ public virtual bool CanWriteResult(OutputFormatterContext context, MediaTypeHead
14087
return false;
14188
}
14289

90+
/// <inheritdoc />
91+
public async Task WriteAsync(OutputFormatterContext context, CancellationToken cancellationToken)
92+
{
93+
cancellationToken.ThrowIfCancellationRequested();
94+
WriteResponseContentHeaders(context);
95+
await WriteResponseBodyAsync(context, cancellationToken);
96+
}
97+
98+
/// <summary>
99+
/// Sets the content-type headers with charset value to the HttpResponse.
100+
/// </summary>
101+
/// <param name="context">The formatter context associated with the call.</param>
102+
public virtual void WriteResponseContentHeaders(OutputFormatterContext context)
103+
{
104+
var selectedMediaType = context.SelectedContentType;
105+
106+
// If content type is not set then set it based on supported media types.
107+
selectedMediaType = selectedMediaType ?? SupportedMediaTypes.FirstOrDefault();
108+
if (selectedMediaType == null)
109+
{
110+
throw new InvalidOperationException(Resources.FormatOutputFormatterNoMediaType(GetType().FullName));
111+
}
112+
113+
var selectedEncoding = SelectCharacterEncoding(context);
114+
if (selectedEncoding == null)
115+
{
116+
// No supported encoding was found so there is no way for us to start writing.
117+
throw new InvalidOperationException(Resources.FormatOutputFormatterNoEncoding(GetType().FullName));
118+
}
119+
120+
context.SelectedEncoding = selectedEncoding;
121+
122+
// Override the content type value even if one already existed.
123+
selectedMediaType.Charset = selectedEncoding.WebName;
124+
var response = context.ActionContext.HttpContext.Response;
125+
response.ContentType = selectedMediaType.RawValue;
126+
}
127+
143128
/// <summary>
144-
/// Writes given <paramref name="value"/> to the HttpResponse <paramref name="response"/> body stream.
129+
/// Writes the response body.
145130
/// </summary>
131+
/// <param name="context">The formatter context assoicated with the call.</param>
146132
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
147-
/// <returns>A Task that serializes the value to the <paramref name="context"/>'s response message.</returns>
148-
public abstract Task WriteAsync(OutputFormatterContext context, CancellationToken cancellationToken);
133+
/// <returns></returns>
134+
public abstract Task WriteResponseBodyAsync(OutputFormatterContext context,
135+
CancellationToken cancellationToken);
149136

150137
private Encoding MatchAcceptCharacterEncoding(string acceptCharsetHeader)
151138
{

0 commit comments

Comments
 (0)