aspnetcore/src/Microsoft.AspNetCore.Mvc.Fo.../ProblemDetailsWrapper.cs

188 lines
5.8 KiB
C#

// Copyright (c) .NET Foundation. 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.Globalization;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
namespace Microsoft.AspNetCore.Mvc.Formatters.Xml
{
/// <summary>
/// Wrapper class for <see cref="Mvc.ProblemDetails"/> to enable it to be serialized by the xml formatters.
/// </summary>
[XmlRoot(nameof(ProblemDetails))]
public class ProblemDetailsWrapper : IXmlSerializable, IUnwrappable
{
/// <summary>
/// Key used to represent dictionary elements with empty keys
/// </summary>
protected static readonly string EmptyKey = SerializableErrorWrapper.EmptyKey;
/// <summary>
/// Initializes a new instance of <see cref="ProblemDetailsWrapper"/>.
/// </summary>
public ProblemDetailsWrapper()
: this(new ProblemDetails())
{
}
/// <summary>
/// Initializes a new instance of <see cref="ProblemDetailsWrapper"/>.
/// </summary>
public ProblemDetailsWrapper(ProblemDetails problemDetails)
{
ProblemDetails = problemDetails;
}
internal ProblemDetails ProblemDetails { get; }
/// <inheritdoc />
public XmlSchema GetSchema() => null;
/// <inheritdoc />
public virtual void ReadXml(XmlReader reader)
{
if (reader == null)
{
throw new ArgumentNullException(nameof(reader));
}
if (reader.IsEmptyElement)
{
reader.Read();
return;
}
reader.ReadStartElement();
while (reader.NodeType != XmlNodeType.EndElement)
{
var key = XmlConvert.DecodeName(reader.LocalName);
ReadValue(reader, key);
reader.MoveToContent();
}
reader.ReadEndElement();
}
/// <summary>
/// Reads the value for the specified <paramref name="name"/> from the <paramref name="reader"/>.
/// </summary>
/// <param name="reader">The <see cref="XmlReader"/>.</param>
/// <param name="name">The name of the node.</param>
protected virtual void ReadValue(XmlReader reader, string name)
{
if (reader == null)
{
throw new ArgumentNullException(nameof(reader));
}
var value = reader.ReadInnerXml();
switch (name)
{
case nameof(ProblemDetails.Detail):
ProblemDetails.Detail = value;
break;
case nameof(ProblemDetails.Instance):
ProblemDetails.Instance = value;
break;
case nameof(ProblemDetails.Status):
ProblemDetails.Status = string.IsNullOrEmpty(value) ?
(int?)null :
int.Parse(value, CultureInfo.InvariantCulture);
break;
case nameof(ProblemDetails.Title):
ProblemDetails.Title = value;
break;
case nameof(ProblemDetails.Type):
ProblemDetails.Type = value;
break;
default:
if (string.Equals(name, EmptyKey, StringComparison.Ordinal))
{
name = string.Empty;
}
ProblemDetails.Extensions.Add(name, value);
break;
}
}
/// <inheritdoc />
public virtual void WriteXml(XmlWriter writer)
{
if (!string.IsNullOrEmpty(ProblemDetails.Detail))
{
writer.WriteElementString(
XmlConvert.EncodeLocalName(nameof(ProblemDetails.Detail)),
ProblemDetails.Detail);
}
if (!string.IsNullOrEmpty(ProblemDetails.Instance))
{
writer.WriteElementString(
XmlConvert.EncodeLocalName(nameof(ProblemDetails.Instance)),
ProblemDetails.Instance);
}
if (ProblemDetails.Status.HasValue)
{
writer.WriteStartElement(XmlConvert.EncodeLocalName(nameof(ProblemDetails.Status)));
writer.WriteValue(ProblemDetails.Status.Value);
writer.WriteEndElement();
}
if (!string.IsNullOrEmpty(ProblemDetails.Title))
{
writer.WriteElementString(
XmlConvert.EncodeLocalName(nameof(ProblemDetails.Title)),
ProblemDetails.Title);
}
if (!string.IsNullOrEmpty(ProblemDetails.Type))
{
writer.WriteElementString(
XmlConvert.EncodeLocalName(nameof(ProblemDetails.Type)),
ProblemDetails.Type);
}
foreach (var keyValuePair in ProblemDetails.Extensions)
{
var key = keyValuePair.Key;
var value = keyValuePair.Value;
if (string.IsNullOrEmpty(key))
{
key = EmptyKey;
}
writer.WriteStartElement(XmlConvert.EncodeLocalName(key));
if (value != null)
{
writer.WriteValue(value);
}
writer.WriteEndElement();
}
}
object IUnwrappable.Unwrap(Type declaredType)
{
if (declaredType == null)
{
throw new ArgumentNullException(nameof(declaredType));
}
return ProblemDetails;
}
}
}