120 lines
4.3 KiB
C#
120 lines
4.3 KiB
C#
// 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.IO;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Xml;
|
|
using System.Xml.Serialization;
|
|
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
|
|
|
|
namespace Microsoft.AspNet.Mvc.ModelBinding
|
|
{
|
|
/// <summary>
|
|
/// This class handles deserialization of input XML data
|
|
/// to strongly-typed objects using <see cref="XmlSerializer"/>
|
|
/// </summary>
|
|
public class XmlSerializerInputFormatter : IInputFormatter
|
|
{
|
|
private readonly XmlDictionaryReaderQuotas _readerQuotas = FormattingUtilities.GetDefaultXmlReaderQuotas();
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of XmlSerializerInputFormatter.
|
|
/// </summary>
|
|
public XmlSerializerInputFormatter()
|
|
{
|
|
SupportedEncodings = new List<Encoding>();
|
|
SupportedEncodings.Add(Encodings.UTF8EncodingWithoutBOM);
|
|
SupportedEncodings.Add(Encodings.UTF16EncodingLittleEndian);
|
|
SupportedMediaTypes = new List<MediaTypeHeaderValue>();
|
|
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/xml"));
|
|
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/xml"));
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public IList<MediaTypeHeaderValue> SupportedMediaTypes { get; private set; }
|
|
|
|
/// <inheritdoc />
|
|
public IList<Encoding> SupportedEncodings { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Indicates the acceptable input XML depth.
|
|
/// </summary>
|
|
public int MaxDepth
|
|
{
|
|
get { return _readerQuotas.MaxDepth; }
|
|
set { _readerQuotas.MaxDepth = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The quotas include - DefaultMaxDepth, DefaultMaxStringContentLength, DefaultMaxArrayLength,
|
|
/// DefaultMaxBytesPerRead, DefaultMaxNameTableCharCount
|
|
/// </summary>
|
|
public XmlDictionaryReaderQuotas XmlDictionaryReaderQuotas
|
|
{
|
|
get { return _readerQuotas; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads the input XML.
|
|
/// </summary>
|
|
/// <param name="context">The input formatter context which contains the body to be read.</param>
|
|
/// <returns>Task which reads the input.</returns>
|
|
public async Task ReadAsync(InputFormatterContext context)
|
|
{
|
|
var request = context.HttpContext.Request;
|
|
if (request.ContentLength == 0)
|
|
{
|
|
context.Model = GetDefaultValueForType(context.Metadata.ModelType);
|
|
return;
|
|
}
|
|
|
|
context.Model = await ReadInternal(context);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called during deserialization to get the <see cref="XmlReader"/>.
|
|
/// </summary>
|
|
/// <param name="readStream">The <see cref="Stream"/> from which to read.</param>
|
|
/// <returns>The <see cref="XmlReader"/> used during deserialization.</returns>
|
|
protected virtual XmlReader CreateXmlReader([NotNull] Stream readStream)
|
|
{
|
|
return XmlDictionaryReader.CreateTextReader(
|
|
readStream, _readerQuotas);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called during deserialization to get the <see cref="XmlSerializer"/>.
|
|
/// </summary>
|
|
/// <returns>The <see cref="XmlSerializer"/> used during deserialization.</returns>
|
|
protected virtual XmlSerializer CreateXmlSerializer(Type type)
|
|
{
|
|
return new XmlSerializer(type);
|
|
}
|
|
|
|
private object GetDefaultValueForType(Type modelType)
|
|
{
|
|
if (modelType.GetTypeInfo().IsValueType)
|
|
{
|
|
return Activator.CreateInstance(modelType);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private Task<object> ReadInternal(InputFormatterContext context)
|
|
{
|
|
var type = context.Metadata.ModelType;
|
|
var request = context.HttpContext.Request;
|
|
|
|
using (var xmlReader = CreateXmlReader(new DelegatingStream(request.Body)))
|
|
{
|
|
var xmlSerializer = CreateXmlSerializer(type);
|
|
return Task.FromResult(xmlSerializer.Deserialize(xmlReader));
|
|
}
|
|
}
|
|
}
|
|
} |