Skip to content

Commit

Permalink
1. Introducing XML Input Formatters.
Browse files Browse the repository at this point in the history
2. Adding DelegatingStream class
3. Unit + Functional tests for formatters.
  • Loading branch information
sornaks committed Jul 29, 2014
1 parent 43d1253 commit cee73c0
Show file tree
Hide file tree
Showing 24 changed files with 1,395 additions and 11 deletions.
13 changes: 13 additions & 0 deletions Mvc.sln
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "CompositeViewEngine", "test
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "RazorWebSite", "test\WebSites\RazorWebSite\RazorWebSite.kproj", "{B07CAF59-11ED-40E3-A5DB-E1178F84FA78}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "FormatterWebSite", "test\WebSites\FormatterWebSite\FormatterWebSite.kproj", "{62735776-46FF-4170-9392-02E128A69B89}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ValueProvidersSite", "test\WebSites\ValueProvidersSite\ValueProvidersSite.kproj", "{14F79E79-AE79-48FA-95DE-D794EF4EABB3}"
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.HeaderValueAbstractions", "src\Microsoft.AspNet.Mvc.HeaderValueAbstractions\Microsoft.AspNet.Mvc.HeaderValueAbstractions.kproj", "{98335B23-E4B9-4CAD-9749-0DED32A659A1}"
EndProject
Expand Down Expand Up @@ -279,6 +281,16 @@ Global
{B07CAF59-11ED-40E3-A5DB-E1178F84FA78}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{B07CAF59-11ED-40E3-A5DB-E1178F84FA78}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{B07CAF59-11ED-40E3-A5DB-E1178F84FA78}.Release|x86.ActiveCfg = Release|Any CPU
{62735776-46FF-4170-9392-02E128A69B89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{62735776-46FF-4170-9392-02E128A69B89}.Debug|Any CPU.Build.0 = Debug|Any CPU
{62735776-46FF-4170-9392-02E128A69B89}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{62735776-46FF-4170-9392-02E128A69B89}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{62735776-46FF-4170-9392-02E128A69B89}.Debug|x86.ActiveCfg = Debug|Any CPU
{62735776-46FF-4170-9392-02E128A69B89}.Release|Any CPU.ActiveCfg = Release|Any CPU
{62735776-46FF-4170-9392-02E128A69B89}.Release|Any CPU.Build.0 = Release|Any CPU
{62735776-46FF-4170-9392-02E128A69B89}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{62735776-46FF-4170-9392-02E128A69B89}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{62735776-46FF-4170-9392-02E128A69B89}.Release|x86.ActiveCfg = Release|Any CPU
{14F79E79-AE79-48FA-95DE-D794EF4EABB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{14F79E79-AE79-48FA-95DE-D794EF4EABB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{14F79E79-AE79-48FA-95DE-D794EF4EABB3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
Expand Down Expand Up @@ -336,6 +348,7 @@ Global
{5F945B82-FE5F-425C-956C-8BC2F2020254} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
{A853B2BA-4449-4908-A416-5A3C027FC22B} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{B07CAF59-11ED-40E3-A5DB-E1178F84FA78} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{62735776-46FF-4170-9392-02E128A69B89} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{14F79E79-AE79-48FA-95DE-D794EF4EABB3} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
{98335B23-E4B9-4CAD-9749-0DED32A659A1} = {32285FA4-6B46-4D6B-A840-2B13E4C8B58E}
{E69FD235-2042-43A4-9970-59CB29955B4E} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
Expand Down
5 changes: 2 additions & 3 deletions src/Microsoft.AspNet.Mvc.Common/Encodings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ public static readonly Encoding UTF8EncodingWithoutBOM
/// <summary>
/// Returns UTF16 Encoding which uses littleEndian byte order with BOM and throws on invalid bytes.
/// </summary>
public static readonly Encoding UnicodeEncodingWithBOM = new UnicodeEncoding(bigEndian: false,
byteOrderMark: true,
throwOnInvalidBytes: true);
public static readonly Encoding UTF16EncodingLittleEndian
= new UnicodeEncoding(bigEndian: false, byteOrderMark: true, throwOnInvalidBytes: true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public JsonOutputFormatter([NotNull] JsonSerializerSettings settings, bool inden
_settings = settings;
_indent = indent;
SupportedEncodings.Add(Encodings.UTF8EncodingWithoutBOM);
SupportedEncodings.Add(Encodings.UnicodeEncodingWithBOM);
SupportedEncodings.Add(Encodings.UTF16EncodingLittleEndian);
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/json"));
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/json"));
}
Expand Down
11 changes: 9 additions & 2 deletions src/Microsoft.AspNet.Mvc.Core/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@
"Newtonsoft.Json": "5.0.8"
},
"frameworks": {
"net45": {},
"net45": {
"dependencies": {
"System.Xml": ""
}
},
"k10": {
"dependencies": {
"Microsoft.CSharp": "4.0.0.0",
Expand All @@ -41,13 +45,16 @@
"System.Runtime": "4.0.20.0",
"System.Runtime.Extensions": "4.0.10.0",
"System.Runtime.InteropServices": "4.0.20.0",
"System.Runtime.Serialization.Xml": "4.0.0.0",
"System.Security.Claims": "1.0.0-*",
"System.Security.Cryptography.Encryption": "4.0.0.0",
"System.Security.Cryptography.Hashing.Algorithms": "4.0.0.0",
"System.Security.Principal": "4.0.0.0",
"System.Text.Encoding": "4.0.20.0",
"System.Threading": "4.0.0.0",
"System.Threading.Tasks": "4.0.10.0"
"System.Threading.Tasks": "4.0.10.0",
"System.Xml.ReaderWriter": "4.0.0.0",
"System.Xml.XmlSerializer": "4.0.0.0"
}
}
}
Expand Down
189 changes: 189 additions & 0 deletions src/Microsoft.AspNet.Mvc.ModelBinding/Formatters/DelegatingStream.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
// Copyright (c) Microsoft Open Technologies, Inc. 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.IO;
using System.Threading;
using System.Threading.Tasks;

namespace Microsoft.AspNet.Mvc.ModelBinding
{
/// <summary>
/// Stream that delegates to an inner stream.
/// This Stream is present so that the inner stream is not closed
/// even when Close() or Dispose() is called.
/// </summary>
public class DelegatingStream : Stream
{
private readonly Stream _innerStream;

/// <summary>
/// Initializes a new object of DelegatingStream
/// </summary>
/// <param name="innerStream">The stream on which should not be closed</param>
public DelegatingStream([NotNull] Stream innerStream)
{
_innerStream = innerStream;
}

protected Stream InnerStream
{
get { return _innerStream; }
}

/// <inheritdoc />
public override bool CanRead
{
get { return _innerStream.CanRead; }
}

/// <inheritdoc />
public override bool CanSeek
{
get { return _innerStream.CanSeek; }
}

/// <inheritdoc />
public override bool CanWrite
{
get { return _innerStream.CanWrite; }
}

/// <inheritdoc />
public override long Length
{
get { return _innerStream.Length; }
}

/// <inheritdoc />
public override long Position
{
get { return _innerStream.Position; }
set { _innerStream.Position = value; }
}

/// <inheritdoc />
public override int ReadTimeout
{
get { return _innerStream.ReadTimeout; }
set { _innerStream.ReadTimeout = value; }
}

/// <inheritdoc />
public override bool CanTimeout
{
get { return _innerStream.CanTimeout; }
}

/// <inheritdoc />
public override int WriteTimeout
{
get { return _innerStream.WriteTimeout; }
set { _innerStream.WriteTimeout = value; }
}

/// <inheritdoc />
public override long Seek(long offset, SeekOrigin origin)
{
return _innerStream.Seek(offset, origin);
}

/// <inheritdoc />
public override int Read(byte[] buffer, int offset, int count)
{
return _innerStream.Read(buffer, offset, count);
}

/// <inheritdoc />
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
return _innerStream.ReadAsync(buffer, offset, count, cancellationToken);
}
#if NET45
/// <inheritdoc />
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count,
AsyncCallback callback, object state)
{
return _innerStream.BeginRead(buffer, offset, count, callback, state);
}

/// <inheritdoc />
public override int EndRead(IAsyncResult asyncResult)
{
return _innerStream.EndRead(asyncResult);
}
#endif
/// <inheritdoc />
public override int ReadByte()
{
return _innerStream.ReadByte();
}

/// <inheritdoc />
public override void Flush()
{
_innerStream.Flush();
}

/// <inheritdoc />
public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
{
return _innerStream.CopyToAsync(destination, bufferSize, cancellationToken);
}

/// <inheritdoc />
public override Task FlushAsync(CancellationToken cancellationToken)
{
return _innerStream.FlushAsync(cancellationToken);
}

/// <inheritdoc />
public override void SetLength(long value)
{
_innerStream.SetLength(value);
}

/// <inheritdoc />
public override void Write(byte[] buffer, int offset, int count)
{
_innerStream.Write(buffer, offset, count);
}

/// <inheritdoc />
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
return _innerStream.WriteAsync(buffer, offset, count, cancellationToken);
}
#if NET45
/// <inheritdoc />
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count,
AsyncCallback callback, object state)
{
return _innerStream.BeginWrite(buffer, offset, count, callback, state);
}

/// <inheritdoc />
public override void EndWrite(IAsyncResult asyncResult)
{
_innerStream.EndWrite(asyncResult);
}
#endif
/// <inheritdoc />
public override void WriteByte(byte value)
{
_innerStream.WriteByte(value);
}
#if NET45
/// <inheritdoc />
public override void Close()
{
}
#endif
/// <inheritdoc />
protected override void Dispose(bool disposing)
{
// No-op. In CoreCLR this is equivalent to Close.
// Given that we don't own the underlying stream, we never want to do anything interesting here.
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright (c) Microsoft Open Technologies, Inc. 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.Text;
using System.Xml;

namespace Microsoft.AspNet.Mvc.ModelBinding
{
/// <summary>
/// Contains methods which are used by input formatters.
/// </summary>
public static class FormattingUtilities
{
public static readonly int DefaultMaxDepth = 32;

/// <summary>
/// Gets the default Reader Quotas for XmlReader.
/// </summary>
/// <returns>XmlReaderQuotas with default values</returns>
public static XmlDictionaryReaderQuotas GetDefaultXmlReaderQuotas()
{
#if NET45
return new XmlDictionaryReaderQuotas()
{
MaxArrayLength = Int32.MaxValue,
MaxBytesPerRead = Int32.MaxValue,
MaxDepth = DefaultMaxDepth,
MaxNameTableCharCount = Int32.MaxValue,
MaxStringContentLength = Int32.MaxValue
};
#else
return XmlDictionaryReaderQuotas.Max;
#endif
}

/// Internal because ContentTypeHeaderValue is internal.
internal static Encoding SelectCharacterEncoding(IList<Encoding> supportedEncodings,
ContentTypeHeaderValue contentType, Type callerType)
{
if (contentType != null)
{
// Find encoding based on content type charset parameter
var charset = contentType.CharSet;
if (!string.IsNullOrWhiteSpace(contentType.CharSet))
{
for (var i = 0; i < supportedEncodings.Count; i++)
{
var supportedEncoding = supportedEncodings[i];
if (string.Equals(charset, supportedEncoding.WebName, StringComparison.OrdinalIgnoreCase))
{
return supportedEncoding;
}
}
}
}

if (supportedEncodings.Count > 0)
{
return supportedEncodings[0];
}

// No supported encoding was found so there is no way for us to start reading.
throw new InvalidOperationException(Resources.FormatMediaTypeFormatterNoEncoding(callerType.FullName));
}
}
}
Loading

0 comments on commit cee73c0

Please sign in to comment.