public override async Task ExecuteResultAsync(ActionContext context) { // See if the list of content types added to this object result is valid. ThrowIfUnsupportedContentType(); var formatters = GetDefaultFormatters(context); var formatterContext = new OutputFormatterContext() { DeclaredType = DeclaredType, ActionContext = context, Object = Value, StatusCode = StatusCode }; var selectedFormatter = SelectFormatter(formatterContext, formatters); if (selectedFormatter == null) { // No formatter supports this. context.HttpContext.Response.StatusCode = StatusCodes.Status406NotAcceptable; return; } if (StatusCode.HasValue) { context.HttpContext.Response.StatusCode = StatusCode.Value; } OnFormatting(context); await selectedFormatter.WriteAsync(formatterContext); }
public async Task WriteAsync(OutputFormatterContext context) { // Override using the selected encoding. context.SelectedEncoding = Encoding; var jsonFormatter = new JsonOutputFormatter(); await jsonFormatter.WriteResponseBodyAsync(context); }
public async Task WriteAsync_DoesNotWriteNullStrings() { // Arrange Encoding encoding = Encoding.UTF8; var memoryStream = new MemoryStream(); var response = new Mock <HttpResponse>(); response.SetupProperty <long?>(o => o.ContentLength); response.SetupGet(r => r.Body).Returns(memoryStream); var mockHttpContext = new Mock <HttpContext>(); mockHttpContext.Setup(o => o.Response).Returns(response.Object); var formatter = new TextPlainFormatter(); var formatterContext = new OutputFormatterContext() { Object = null, DeclaredType = typeof(string), ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor()), SelectedEncoding = encoding }; // Act await formatter.WriteResponseBodyAsync(formatterContext); // Assert Assert.Equal(0, memoryStream.Length); response.VerifySet(r => r.ContentLength = It.IsAny <long?>(), Times.Never()); }
public async Task WriteAsync_DoesNotWriteNullStrings() { // Arrange Encoding encoding = Encoding.UTF8; var memoryStream = new MemoryStream(); var response = new Mock<HttpResponse>(); response.SetupProperty<long?>(o => o.ContentLength); response.SetupGet(r => r.Body).Returns(memoryStream); var mockHttpContext = new Mock<HttpContext>(); mockHttpContext.Setup(o => o.Response).Returns(response.Object); var formatter = new StringOutputFormatter(); var formatterContext = new OutputFormatterContext() { Object = null, DeclaredType = typeof(string), HttpContext = mockHttpContext.Object, SelectedEncoding = encoding }; // Act await formatter.WriteResponseBodyAsync(formatterContext); // Assert Assert.Equal(0, memoryStream.Length); response.VerifySet(r => r.ContentLength = It.IsAny<long?>(), Times.Never()); }
public override async Task ExecuteResultAsync(ActionContext context) { var formatters = GetDefaultFormatters(context); var formatterContext = new OutputFormatterContext() { DeclaredType = DeclaredType, ActionContext = context, Object = Value, }; var selectedFormatter = SelectFormatter(formatterContext, formatters); if (selectedFormatter == null) { // No formatter supports this. context.HttpContext.Response.StatusCode = 406; return; } if (StatusCode != null) { context.HttpContext.Response.StatusCode = (int)StatusCode; } OnFormatting(context); await selectedFormatter.WriteAsync(formatterContext); }
/// <summary> /// Sets the headers on <see cref="Microsoft.AspNet.Http.HttpResponse"/> object. /// </summary> /// <param name="context">The formatter context associated with the call.</param> public virtual void WriteResponseHeaders([NotNull] OutputFormatterContext context) { var selectedMediaType = context.SelectedContentType; // If content type is not set then set it based on supported media types. selectedMediaType = selectedMediaType ?? SupportedMediaTypes.FirstOrDefault(); if (selectedMediaType == null) { throw new InvalidOperationException(Resources.FormatOutputFormatterNoMediaType(GetType().FullName)); } // Clone the media type as we don't want it to affect the next request selectedMediaType = MediaTypeHeaderValue.Parse(selectedMediaType.ToString()); var selectedEncoding = SelectCharacterEncoding(context); if (selectedEncoding == null) { // No supported encoding was found so there is no way for us to start writing. throw new InvalidOperationException(Resources.FormatOutputFormatterNoEncoding(GetType().FullName)); } context.SelectedEncoding = selectedEncoding; // Override the content type value even if one already existed. selectedMediaType.Charset = selectedEncoding.WebName; context.SelectedContentType = context.SelectedContentType ?? selectedMediaType; var response = context.ActionContext.HttpContext.Response; response.ContentType = selectedMediaType.ToString(); }
public void SelectFormatter_WithNoMatchingAcceptHeadersAndRequestContentType_PicksFormatterBasedOnObjectType (string acceptHeader) { // For no accept headers, // can write is called twice once for the request Content-Type and once for the type match pass. // For each additional accept header, it is called once. // Arrange var acceptHeaderCollection = string.IsNullOrEmpty(acceptHeader) ? null : MediaTypeHeaderValue.ParseList(new[] { acceptHeader }).ToArray(); var stream = new MemoryStream(); var httpResponse = new Mock <HttpResponse>(); httpResponse.SetupProperty <string>(o => o.ContentType); httpResponse.SetupGet(r => r.Body).Returns(stream); var actionContext = CreateMockActionContext(httpResponse.Object, requestAcceptHeader: acceptHeader, requestContentType: "application/xml"); var input = "testInput"; var result = new ObjectResult(input); var mockCountingFormatter = new Mock <IOutputFormatter>(); var context = new OutputFormatterContext() { HttpContext = actionContext.HttpContext, Object = input, DeclaredType = typeof(string) }; var mockCountingSupportedContentType = MediaTypeHeaderValue.Parse("application/text"); mockCountingFormatter.Setup(o => o.CanWriteResult(context, It.Is <MediaTypeHeaderValue>(mth => mth == null))) .Returns(true); mockCountingFormatter.Setup(o => o.CanWriteResult(context, mockCountingSupportedContentType)) .Returns(true); // Set more than one formatters. The test output formatter throws on write. result.Formatters = new List <IOutputFormatter> { new CannotWriteFormatter(), mockCountingFormatter.Object, }; // Act var formatter = result.SelectFormatter(context, result.Formatters); // Assert Assert.Equal(mockCountingFormatter.Object, formatter); mockCountingFormatter.Verify(v => v.CanWriteResult(context, null), Times.Once()); // CanWriteResult is invoked for the following cases: // 1. For each accept header present // 2. Request Content-Type // 3. Type based match var callCount = (acceptHeaderCollection == null ? 0 : acceptHeaderCollection.Count()) + 2; mockCountingFormatter.Verify(v => v.CanWriteResult(context, It.IsNotIn <MediaTypeHeaderValue>(mockCountingSupportedContentType)), Times.Exactly(callCount)); }
/// <inheritdoc /> public Task WriteAsync(OutputFormatterContext context) { var response = context.HttpContext.Response; response.StatusCode = StatusCodes.Status406NotAcceptable; return(Task.FromResult(true)); }
/// <inheritdoc /> public virtual bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType) { MediaTypeHeaderValue mediaType = null; if (contentType == null) { // If the desired content type is set to null, the current formatter is free to choose the // response media type. mediaType = SupportedMediaTypes.FirstOrDefault(); } else { // Since supportedMedia Type is going to be more specific check if supportedMediaType is a subset // of the content type which is typically what we get on acceptHeader. mediaType = SupportedMediaTypes .FirstOrDefault(supportedMediaType => supportedMediaType.IsSubsetOf(contentType)); } if (mediaType != null) { context.SelectedContentType = mediaType; return true; } return false; }
/// <inheritdoc /> public Task WriteAsync(OutputFormatterContext context) { var response = context.ActionContext.HttpContext.Response; response.StatusCode = 406; return(Task.FromResult(true)); }
public override async Task ExecuteResultAsync(ActionContext context) { // See if the list of content types added to this object result is valid. ThrowIfUnsupportedContentType(); var formatters = GetDefaultFormatters(context); var formatterContext = new OutputFormatterContext() { DeclaredType = DeclaredType, ActionContext = context, Object = Value, StatusCode = StatusCode }; var selectedFormatter = SelectFormatter(formatterContext, formatters); if (selectedFormatter == null) { // No formatter supports this. context.HttpContext.Response.StatusCode = StatusCodes.Status406NotAcceptable; return; } if (StatusCode.HasValue) { context.HttpContext.Response.StatusCode = StatusCode.Value; } OnFormatting(context); await selectedFormatter.WriteAsync(formatterContext); }
public Task WriteAsync(OutputFormatterContext context) { var response = context.HttpContext.Response; response.ContentLength = 0; response.StatusCode = context.StatusCode ?? StatusCodes.Status204NoContent; return Task.FromResult(true); }
private IEnumerable <MediaTypeHeaderValue> GetSortedAcceptHeaderMediaTypes( OutputFormatterContext formatterContext) { var request = formatterContext.HttpContext.Request; var incomingAcceptHeaderMediaTypes = request.GetTypedHeaders().Accept ?? new MediaTypeHeaderValue[] { }; // By default we want to ignore considering accept headers for content negotiation when // they have a media type like */* in them. Browsers typically have these media types. // In these cases we would want the first formatter in the list of output formatters to // write the response. This default behavior can be changed through options, so checking here. var options = formatterContext .HttpContext .RequestServices .GetRequiredService <IOptions <MvcOptions> >() .Value; var respectAcceptHeader = true; if (options.RespectBrowserAcceptHeader == false && incomingAcceptHeaderMediaTypes.Any(mediaType => mediaType.MatchesAllTypes)) { respectAcceptHeader = false; } var sortedAcceptHeaderMediaTypes = Enumerable.Empty <MediaTypeHeaderValue>(); if (respectAcceptHeader) { sortedAcceptHeaderMediaTypes = SortMediaTypeHeaderValues(incomingAcceptHeaderMediaTypes) .Where(header => header.Quality != HeaderQuality.NoMatch); } return(sortedAcceptHeaderMediaTypes); }
/// <inheritdoc /> public override async Task ExecuteResultAsync([NotNull] ActionContext context) { var objectResult = new ObjectResult(Value); // Set the content type explicitly to application/json and text/json. // if the user has not already set it. if (ContentTypes == null || ContentTypes.Count == 0) { foreach (var contentType in DefaultContentTypes) { objectResult.ContentTypes.Add(contentType); } } else { objectResult.ContentTypes = ContentTypes; } var formatterContext = new OutputFormatterContext() { ActionContext = context, DeclaredType = objectResult.DeclaredType, Object = Value, }; var formatter = SelectFormatter(objectResult, formatterContext); await formatter.WriteAsync(formatterContext); }
/// <inheritdoc /> public virtual bool CanWriteResult([NotNull] OutputFormatterContext context, MediaTypeHeaderValue contentType) { var runtimeType = context.Object == null ? null : context.Object.GetType(); if (!CanWriteType(context.DeclaredType, runtimeType)) { return(false); } MediaTypeHeaderValue mediaType = null; if (contentType == null) { // If the desired content type is set to null, the current formatter is free to choose the // response media type. mediaType = SupportedMediaTypes.FirstOrDefault(); } else { // Since supportedMedia Type is going to be more specific check if supportedMediaType is a subset // of the content type which is typically what we get on acceptHeader. mediaType = SupportedMediaTypes .FirstOrDefault(supportedMediaType => supportedMediaType.IsSubsetOf(contentType)); } if (mediaType != null) { context.SelectedContentType = mediaType; return(true); } return(false); }
public Task WriteAsync(OutputFormatterContext context) { var response = context.HttpContext.Response; response.ContentLength = 0; response.StatusCode = context.StatusCode ?? StatusCodes.Status204NoContent; return(Task.FromResult(true)); }
public async Task WriteAsync(OutputFormatterContext context) { // Override using the selected encoding. context.SelectedEncoding = Encoding; var jsonFormatter = new JsonOutputFormatter(JsonOutputFormatter.CreateDefaultSettings(), indent: false); await jsonFormatter.WriteResponseBodyAsync(context); }
public async override Task WriteResponseBodyAsync(OutputFormatterContext context) { var itemType = context.DeclaredType.GetElementType() ?? context.DeclaredType.GetGenericArguments()[0]; using (var stringWriter = new StringWriter()) { stringWriter.WriteLine( string.Join<string>( ",", itemType.GetProperties().Select(x => x.Name) ) ); foreach (var obj in (IEnumerable<object>) context.Object) { var vals = obj.GetType().GetProperties().Select( pi => new { Value = pi.GetValue(obj, null) } ); var valueLine = string.Empty; string _val; foreach (var val in vals) { if (val.Value != null) { _val = val.Value.ToString(); //Check if the value contans a comma and place it in quotes if so if (_val.Contains(",")) _val = string.Concat("\"", _val, "\""); //Replace any \r or \n special characters from a new line with a space if (_val.Contains("\r")) _val = _val.Replace("\r", " "); if (_val.Contains("\n")) _val = _val.Replace("\n", " "); valueLine = string.Concat(valueLine, _val, ","); } else { valueLine = string.Concat(valueLine, ","); } } stringWriter.WriteLine(valueLine.TrimEnd(',')); } var writer = new StreamWriter(context.HttpContext.Response.Body); await writer.WriteAsync(stringWriter.ToString()); await writer.FlushAsync(); } }
public override async Task WriteResponseBodyAsync(OutputFormatterContext context) { var response = context.ActionContext.HttpContext.Response; var selectedEncoding = context.SelectedEncoding; Model.Serialize(response.Body, context.Object); return; // await response.Body.WriteAsync(valueAsString, context.SelectedEncoding); }
public override void WriteResponseHeaders(OutputFormatterContext context) { if (context.Object is IEdmModel) { context.SelectedContentType = SupportedMediaTypes[2]; } context.ActionContext.HttpContext.Response.Headers.Add("OData-Version", new[] { "4.0" }); base.WriteResponseHeaders(context); }
/// <inheritdoc /> public bool CanWriteResult([NotNull] OutputFormatterContext context, MediaTypeHeaderValue contentType) { // Ignore the passed in content type, if the object is a Stream. if (context.Object is Stream) { context.SelectedContentType = contentType; return(true); } return(false); }
public override async Task WriteResponseBodyAsync(OutputFormatterContext context) { var contact = (Contact)context.Object; var builder = new StringBuilder(); builder.AppendLine("BEGIN:VCARD"); builder.AppendFormat("FN:{0}", contact.Name); builder.AppendLine(); builder.AppendLine("END:VCARD"); await context.HttpContext.Response.WriteAsync(builder.ToString(), context.SelectedEncoding); }
public override Task WriteResponseBodyAsync(OutputFormatterContext context) { var response = context.HttpContext.Response; var selectedEncoding = context.SelectedEncoding; using (var writer = new HttpResponseStreamWriter(response.Body, selectedEncoding)) { WriteObject(writer, context.Object); } return(Task.FromResult(true)); }
public override Task WriteResponseBodyAsync(OutputFormatterContext context) { var response = context.HttpContext.Response; var selectedEncoding = context.SelectedEncoding; using (var writer = new HttpResponseStreamWriter(response.Body, selectedEncoding)) { WriteObject(writer, context.Object); } return Task.FromResult(true); }
public Task WriteAsync(OutputFormatterContext context) { var response = context.ActionContext.HttpContext.Response; response.ContentLength = 0; // Only set the status code if its not already set. // TODO: By default the status code is set to 200. // https://github.com/aspnet/HttpAbstractions/issues/114 response.StatusCode = 204; return(Task.FromResult(true)); }
public bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType) { // ignore the contentType and just look at the content. // This formatter will be selected if the content is null. // We check for Task as a user can directly create an ObjectContentResult with the unwrapped type. if (context.DeclaredType == typeof(void) || context.DeclaredType == typeof(Task)) { return true; } return TreatNullValueAsNoContent && context.Object == null; }
public bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType) { // ignore the contentType and just look at the content. // This formatter will be selected if the content is null. // We check for Task as a user can directly create an ObjectContentResult with the unwrapped type. if (context.DeclaredType == typeof(void) || context.DeclaredType == typeof(Task)) { return(true); } return(TreatNullValueAsNoContent && context.Object == null); }
public override bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType) { if (base.CanWriteResult(context, contentType)) { var actionReturnString = context.Object as string; if (actionReturnString != null) { return true; } } return false; }
public override async Task WriteResponseBodyAsync(OutputFormatterContext context) { var valueAsString = (string)context.Object; if (string.IsNullOrEmpty(valueAsString)) { return; } var response = context.HttpContext.Response; await response.WriteAsync(valueAsString, context.SelectedEncoding); }
/// <inheritdoc /> public override bool CanWriteResult([NotNull] OutputFormatterContext context, MediaTypeHeaderValue contentType) { if (base.CanWriteResult(context, contentType)) { if (CreateSerializer(GetObjectType(context)) != null) { return(true); } } return(false); }
public override async Task WriteResponseBodyAsync(OutputFormatterContext context) { var valueAsString = (string)context.Object; if (string.IsNullOrEmpty(valueAsString)) { return; } var response = context.HttpContext.Response; await response.WriteAsync(valueAsString, context.SelectedEncoding); }
public override Task WriteResponseBodyAsync(OutputFormatterContext context) { var response = context.ActionContext.HttpContext.Response; var selectedEncoding = context.SelectedEncoding; using (var delegatingStream = new DelegatingStream(response.Body)) using (var writer = new StreamWriter(delegatingStream, selectedEncoding, 1024, leaveOpen: true)) { WriteObject(writer, context.Object); } return(Task.FromResult(true)); }
public virtual IOutputFormatter SelectFormatterUsingAnyAcceptableContentType( OutputFormatterContext formatterContext, IEnumerable <IOutputFormatter> formatters, IEnumerable <MediaTypeHeaderValue> acceptableContentTypes) { var selectedFormatter = formatters.FirstOrDefault( formatter => acceptableContentTypes .Any(contentType => formatter.CanWriteResult(formatterContext, contentType))); return(selectedFormatter); }
/// <summary> /// Gets the type of the object to be serialized. /// </summary> /// <param name="context">The context which contains the object to be serialized.</param> /// <returns>The type of the object to be serialized.</returns> public virtual Type GetObjectType([NotNull] OutputFormatterContext context) { if (context.DeclaredType == null || context.DeclaredType == typeof(object)) { if (context.Object != null) { return(context.Object.GetType()); } } return(context.DeclaredType); }
public override Task WriteResponseBodyAsync(OutputFormatterContext context) { var response = context.ActionContext.HttpContext.Response; var selectedEncoding = context.SelectedEncoding; using (var nonDisposableStream = new NonDisposableStream(response.Body)) using (var writer = new StreamWriter(nonDisposableStream, selectedEncoding, 1024, leaveOpen: true)) { WriteObject(writer, context.Object); } return Task.FromResult(true); }
/// <inheritdoc /> public async Task WriteAsync([NotNull] OutputFormatterContext context) { using (var valueAsStream = ((Stream)context.Object)) { var response = context.ActionContext.HttpContext.Response; if (context.SelectedContentType != null) { response.ContentType = context.SelectedContentType.ToString(); } await valueAsStream.CopyToAsync(response.Body); } }
public virtual IOutputFormatter SelectFormatterBasedOnTypeMatch( OutputFormatterContext formatterContext, IEnumerable <IOutputFormatter> formatters) { foreach (var formatter in formatters) { if (formatter.CanWriteResult(formatterContext, contentType: null)) { return(formatter); } } return(null); }
public override bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType) { if (base.CanWriteResult(context, contentType)) { var actionReturn = context.Object as Product; if (actionReturn != null) { var response = context.ActionContext.HttpContext.Response; context.SelectedContentType = contentType; return true; } } return false; }
public override async Task WriteResponseBodyAsync(OutputFormatterContext context) { var valueAsString = (string)context.Object; if (valueAsString == null) { // if the value is null don't write anything. return; } var response = context.ActionContext.HttpContext.Response; using (var writer = new StreamWriter(response.Body, context.SelectedEncoding, 1024, leaveOpen: true)) { await writer.WriteAsync(valueAsString); } }
public override bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType) { // Ignore the passed in content type, if the object is string // always return it as a text/plain format. if (context.DeclaredType == typeof(string)) { return true; } if (context.Object is string) { return true; } return false; }
public void CanWriteResult_SetsContentType() { // Arrange var formatter = new StreamOutputFormatter(); var contentType = new MediaTypeHeaderValue("text/plain"); var context = new OutputFormatterContext(); context.Object = new MemoryStream(); // Act var result = formatter.CanWriteResult(context, contentType); // Assert Assert.True(result); Assert.Same(contentType, context.SelectedContentType); }
public void CanWriteResult_OnlyActsOnStreams(Type type) { // Arrange var formatter = new StreamOutputFormatter(); var context = new OutputFormatterContext(); var contentType = new MediaTypeHeaderValue("text/plain"); context.Object = type != null?Activator.CreateInstance(type) : null; // Act var result = formatter.CanWriteResult(context, contentType); // Assert Assert.False(result); Assert.Null(context.SelectedContentType); }
public override async Task WriteResponseBodyAsync(OutputFormatterContext context) { var contact = (Contact)context.Object; var builder = new StringBuilder(); builder.AppendLine("BEGIN:VCARD"); builder.AppendFormat("FN:{0}", contact.Name); builder.AppendLine(); builder.AppendLine("END:VCARD"); var responseStream = new NonDisposableStream(context.ActionContext.HttpContext.Response.Body); using (var writer = new StreamWriter(responseStream, context.SelectedEncoding, bufferSize: 1024)) { await writer.WriteAsync(builder.ToString()); } }
public void CanWriteResult_OnlyActsOnStreams(Type type) { // Arrange var formatter = new StreamOutputFormatter(); var context = new OutputFormatterContext(); var contentType = new MediaTypeHeaderValue("text/plain"); context.Object = type != null ? Activator.CreateInstance(type) : null; // Act var result = formatter.CanWriteResult(context, contentType); // Assert Assert.False(result); Assert.Null(context.SelectedContentType); }
public override bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType) { // Ignore the passed in content type, if the object is string // always return it as a text/plain format. if (context.DeclaredType == typeof(string)) { return(true); } if (context.Object is string) { return(true); } return(false); }
public override async Task WriteResponseBodyAsync(OutputFormatterContext context) { var valueAsString = (string)context.Object; if (valueAsString == null) { // if the value is null don't write anything. return; } var response = context.ActionContext.HttpContext.Response; using (var writer = new StreamWriter(response.Body, context.SelectedEncoding, 1024, leaveOpen: true)) { await writer.WriteAsync(valueAsString); } }
public void CanWriteResult_ReturnsTrue_ForStreams(Type declaredType, string contentType) { // Arrange var formatter = new StreamOutputFormatter(); var contentTypeHeader = contentType == null ? null : new MediaTypeHeaderValue(contentType); var formatterContext = new OutputFormatterContext() { DeclaredType = declaredType, Object = new MemoryStream() }; // Act var canWrite = formatter.CanWriteResult(formatterContext, contentTypeHeader); // Assert Assert.True(canWrite); }
public void CanWriteResult_OnlyActsOnStreams_IgnoringContentType(Type declaredType, string contentType) { // Arrange var formatter = new StreamOutputFormatter(); var contentTypeHeader = contentType == null ? null : new MediaTypeHeaderValue(contentType); var formatterContext = new OutputFormatterContext() { DeclaredType = declaredType, Object = new SimplePOCO() }; // Act var canWrite = formatter.CanWriteResult(formatterContext, contentTypeHeader); // Assert Assert.False(canWrite); }
public void CanWriteResult_ReturnsTrueForStringTypes(object value, bool useDeclaredTypeAsString, bool expectedCanWriteResult) { // Arrange var formatter = new TextPlainFormatter(); var typeToUse = useDeclaredTypeAsString ? typeof(string) : typeof(object); var formatterContext = new OutputFormatterContext() { Object = value, DeclaredType = typeToUse }; // Act var result = formatter.CanWriteResult(formatterContext, null); // Assert Assert.Equal(expectedCanWriteResult, result); }
public void CanWriteResult_ReturnsTrue_ForStreams(Type declaredType, string contentType) { // Arrange var formatter = new StreamOutputFormatter(); var contentTypeHeader = contentType == null ? null : new MediaTypeHeaderValue(contentType); var formatterContext = new OutputFormatterContext() { DeclaredType = declaredType, Object = new MemoryStream() }; // Act var canWrite = formatter.CanWriteResult(formatterContext, contentTypeHeader); // Assert Assert.True(canWrite); }
public void CanWriteResult_OnlyActsOnStreams_IgnoringContentType(Type declaredType, string contentType) { // Arrange var formatter = new StreamOutputFormatter(); var contentTypeHeader = contentType == null ? null : new MediaTypeHeaderValue(contentType); var formatterContext = new OutputFormatterContext() { DeclaredType = declaredType, Object = new SimplePOCO() }; // Act var canWrite = formatter.CanWriteResult(formatterContext, contentTypeHeader); // Assert Assert.False(canWrite); }
public override Task WriteResponseBodyAsync(OutputFormatterContext context) { var response = context.ActionContext.HttpContext.Response; var selectedEncoding = context.SelectedEncoding; using (var writer = new StreamWriter(response.Body, selectedEncoding, 1024, leaveOpen: true)) { using (var jsonWriter = CreateJsonWriter(writer)) { var jsonSerializer = CreateJsonSerializer(); jsonSerializer.Serialize(jsonWriter, context.Object); // We're explicitly calling flush here to simplify the debugging experience because the // underlying TextWriter might be long-lived. If this method ends up being called repeatedly // for a request, we should revisit. jsonWriter.Flush(); } } return Task.FromResult(true); }
/// <summary> /// Determines the best <see cref="Encoding"/> amongst the supported encodings /// for reading or writing an HTTP entity body based on the provided <paramref name="contentTypeHeader"/>. /// </summary> /// <param name="context">The formatter context associated with the call. /// </param> /// <returns>The <see cref="Encoding"/> to use when reading the request or writing the response.</returns> public virtual Encoding SelectCharacterEncoding(OutputFormatterContext context) { var request = context.ActionContext.HttpContext.Request; var encoding = MatchAcceptCharacterEncoding(request.AcceptCharset); if (encoding == null) { // Match based on request acceptHeader. var requestContentType = MediaTypeHeaderValue.Parse(request.ContentType); if (requestContentType != null && !string.IsNullOrEmpty(requestContentType.Charset)) { var requestCharset = requestContentType.Charset; encoding = SupportedEncodings.FirstOrDefault( supportedEncoding => requestCharset.Equals(supportedEncoding.WebName)); } } encoding = encoding ?? SupportedEncodings.FirstOrDefault(); return encoding; }
public override async Task ExecuteResultAsync(ActionContext context) { var formatters = GetDefaultFormatters(context); var formatterContext = new OutputFormatterContext() { DeclaredType = DeclaredType, ActionContext = context, Object = Value, }; var selectedFormatter = SelectFormatter(formatterContext, formatters); if (selectedFormatter == null) { // No formatter supports this. context.HttpContext.Response.StatusCode = 406; return; } await selectedFormatter.WriteAsync(formatterContext); }
public async Task WriteAsync_DoesNotWriteNullStrings() { // Arrange var formatter = new TextPlainFormatter(); var formatterContext = new OutputFormatterContext() { Object = null, DeclaredType = typeof(string), }; var tempMemoryStream = new MemoryStream(); var mockHttpContext = new Mock<HttpContext>(); mockHttpContext.SetupGet(o => o.Response.Body) .Returns(tempMemoryStream); // Act await formatter.WriteResponseBodyAsync(formatterContext); // Assert Assert.Equal(0, tempMemoryStream.Length); }
public override async Task ExecuteResultAsync(ActionContext context) { var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<ObjectResult>>(); // See if the list of content types added to this object result is valid. ThrowIfUnsupportedContentType(); var formatters = GetDefaultFormatters(context); var formatterContext = new OutputFormatterContext() { DeclaredType = DeclaredType, HttpContext = context.HttpContext, Object = Value, StatusCode = StatusCode }; var selectedFormatter = SelectFormatter(formatterContext, formatters); if (selectedFormatter == null) { // No formatter supports this. logger.LogWarning("No output formatter was found to write the response."); context.HttpContext.Response.StatusCode = StatusCodes.Status406NotAcceptable; return; } logger.LogVerbose( "Selected output formatter '{OutputFormatter}' and content type " + "'{ContentType}' to write the response.", selectedFormatter.GetType().FullName, formatterContext.SelectedContentType); if (StatusCode.HasValue) { context.HttpContext.Response.StatusCode = StatusCode.Value; } OnFormatting(context); await selectedFormatter.WriteAsync(formatterContext); }
private IEnumerable<MediaTypeHeaderValue> GetSortedAcceptHeaderMediaTypes( OutputFormatterContext formatterContext) { var request = formatterContext.ActionContext.HttpContext.Request; var incomingAcceptHeaderMediaTypes = request.GetTypedHeaders().Accept ?? new MediaTypeHeaderValue[] { }; // By default we want to ignore considering accept headers for content negotiation when // they have a media type like */* in them. Browsers typically have these media types. // In these cases we would want the first formatter in the list of output formatters to // write the response. This default behavior can be changed through options, so checking here. var options = formatterContext.ActionContext.HttpContext .RequestServices .GetRequiredService<IOptions<MvcOptions>>() .Options; var respectAcceptHeader = true; if (options.RespectBrowserAcceptHeader == false && incomingAcceptHeaderMediaTypes.Any(mediaType => mediaType.MatchesAllTypes)) { respectAcceptHeader = false; } var sortedAcceptHeaderMediaTypes = Enumerable.Empty<MediaTypeHeaderValue>(); if (respectAcceptHeader) { sortedAcceptHeaderMediaTypes = SortMediaTypeHeaderValues(incomingAcceptHeaderMediaTypes) .Where(header => header.Quality != HeaderQuality.NoMatch); } return sortedAcceptHeaderMediaTypes; }
public virtual IOutputFormatter SelectFormatter( OutputFormatterContext formatterContext, IEnumerable<IOutputFormatter> formatters) { // Check if any content-type was explicitly set (for example, via ProducesAttribute // or Url path extension mapping). If yes, then ignore content-negotiation and use this content-type. if (ContentTypes.Count == 1) { return SelectFormatterUsingAnyAcceptableContentType(formatterContext, formatters, ContentTypes); } var sortedAcceptHeaderMediaTypes = GetSortedAcceptHeaderMediaTypes(formatterContext); IOutputFormatter selectedFormatter = null; if (ContentTypes == null || ContentTypes.Count == 0) { // Check if we have enough information to do content-negotiation, otherwise get the first formatter // which can write the type. MediaTypeHeaderValue requestContentType = null; MediaTypeHeaderValue.TryParse( formatterContext.ActionContext.HttpContext.Request.ContentType, out requestContentType); if (!sortedAcceptHeaderMediaTypes.Any() && requestContentType == null) { return SelectFormatterBasedOnTypeMatch(formatterContext, formatters); } // // Content-Negotiation starts from this point on. // // 1. Select based on sorted accept headers. if (sortedAcceptHeaderMediaTypes.Any()) { selectedFormatter = SelectFormatterUsingSortedAcceptHeaders( formatterContext, formatters, sortedAcceptHeaderMediaTypes); } // 2. No formatter was found based on accept headers, fall back on request Content-Type header. if (selectedFormatter == null && requestContentType != null) { selectedFormatter = SelectFormatterUsingAnyAcceptableContentType( formatterContext, formatters, new[] { requestContentType }); } // 3. No formatter was found based on Accept and request Content-Type headers, so // fallback on type based match. if (selectedFormatter == null) { // Set this flag to indicate that content-negotiation has failed to let formatters decide // if they want to write the response or not. formatterContext.FailedContentNegotiation = true; return SelectFormatterBasedOnTypeMatch(formatterContext, formatters); } } else { if (sortedAcceptHeaderMediaTypes.Any()) { // Filter and remove accept headers which cannot support any of the user specified content types. var filteredAndSortedAcceptHeaders = sortedAcceptHeaderMediaTypes .Where(acceptHeader => ContentTypes.Any(contentType => contentType.IsSubsetOf(acceptHeader))); selectedFormatter = SelectFormatterUsingSortedAcceptHeaders( formatterContext, formatters, filteredAndSortedAcceptHeaders); } if (selectedFormatter == null) { // Either there were no acceptHeaders that were present OR // There were no accept headers which matched OR // There were acceptHeaders which matched but there was no formatter // which supported any of them. // In any of these cases, if the user has specified content types, // do a last effort to find a formatter which can write any of the user specified content type. selectedFormatter = SelectFormatterUsingAnyAcceptableContentType( formatterContext, formatters, ContentTypes); } } return selectedFormatter; }
public override async Task WriteResponseBodyAsync(OutputFormatterContext context) { var response = context.ActionContext.HttpContext.Response; response.ContentType = ContentType + ";charset=utf-8"; await response.WriteAsync(context.Object.ToString()); }
public override async Task WriteResponseBodyAsync(OutputFormatterContext context) { var response = context.ActionContext.HttpContext.Response; await response.WriteAsync(context.Object.ToString()); }