允许.NET WebApi忽略DOCTYPE声明 [英] Allow .NET WebApi to disregard DOCTYPE declaration

查看:142
本文介绍了允许.NET WebApi忽略DOCTYPE声明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过WebApi方法将XML反序列化为对象.

I am trying to deserialize XML to an object through a WebApi Method.

我有以下课程:

[XmlRoot(IsNullable = false)]
public class MyObject 
{
     [XmlElement("Name")]
     public string Name {get;set;}
}

以及WebApi控制器中的以下方法.

And the following Method in a WebApi Controller.

 [HttpPost]
 public HttpResponseMessage UpdateMyObject(MyObject model)
 {
   //do something with the model
 }

我通过在Web项目的启动中设置以下内容来使用XmlSerializer:

I am using the XmlSerializer by setting the following in the startup of the Web Project:

config.Formatters.XmlFormatter.UseXmlSerializer = true;

当我发布以下XML时,model已正确反序列化,并且我可以读取其属性.

When I POST the following XML, the model is correctly deserialized, and I can read the properties of it.

<?xml version="1.0" encoding="UTF-8"?>
<MyObject>
    <Name>HelloWorld</Name>
</MyObject>

但是,当我使用DOCTYPE声明发布XML时,model值为null,并且似乎在方法输入时未反序列化. IE.该XML不会反序列化为模型:

However, when I POST the XML with a DOCTYPE declaration, the model value is null and seemingly not being deserialized on method-entry. I.e. this XML does not deserialize to a model:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE MyObject SYSTEM "http://example.com/MyObject.dtd">
<MyObject>
    <Name>HelloWorld</Name>
</MyObject>

希望有人能够提供帮助.

Hope someone is able to help.

推荐答案

即使是旧帖子,我也遇到了同样的情况.我最后写了一个自定义版本的 XmlMediaTypeFormatter ,该版本覆盖了 ReadFromStreamAsync 方法.

Even if is an old post, I found myself in the same situation. I ended up in writing a customized version of the XmlMediaTypeFormatter overriding the ReadFromStreamAsync method.

这是我的个人解决方案:

Here my personal solution:

public class CustomXmlMediaTypeFormatter : XmlMediaTypeFormatter
{
    /// <summary>
    /// Initializes a new instance of the <see cref="CustomXmlMediaTypeFormatter"/> class.
    /// This XmlMediaTypeFormatter will ignore the doctype while reading the provided stream.
    /// </summary>
    public CustomXmlMediaTypeFormatter()
    {
        UseXmlSerializer = true;
    }

    public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
    {
        if (type == null)
            throw new ArgumentNullException("type");
        if (readStream == null)
            throw new ArgumentNullException("readStream");

        try
        {
            return Task.FromResult(ReadFromStream(type, readStream, content, formatterLogger));
        }
        catch (Exception ex)
        {
            var completionSource = new TaskCompletionSource<object>();
            completionSource.SetException(ex);
            return completionSource.Task;
        }

    }

    private object ReadFromStream(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
    {
        var httpContentHeaders = content == null ? (HttpContentHeaders)null : content.Headers;
        if (httpContentHeaders != null)
        {
            var contentLength = httpContentHeaders.ContentLength;
            if ((contentLength.GetValueOrDefault() != 0L ? 0 : (contentLength.HasValue ? 1 : 0)) != 0)
                return GetDefaultValueForType(type);
        }

        var settings = new XmlReaderSettings
        {
            DtdProcessing = DtdProcessing.Ignore
        };

        var deserializer = GetDeserializer(type, content);
        try
        {
            // The standard XmlMediaTypeFormatter will get the encoding from the HttpContent, instead
            // here the XmlReader will decide by itself according to the content
            using (var xmlReader = XmlReader.Create(readStream, settings))
            {
                var xmlSerializer = deserializer as XmlSerializer;
                if (xmlSerializer != null)
                    return xmlSerializer.Deserialize(xmlReader);

                var objectSerializer = deserializer as XmlObjectSerializer;
                if (objectSerializer == null)
                    throw new InvalidOperationException("xml object deserializer not available");

                return objectSerializer.ReadObject(xmlReader);
            }
        }
        catch (Exception ex)
        {
            if (formatterLogger == null)
            {
                throw;
            }

            formatterLogger.LogError(string.Empty, ex);
            return GetDefaultValueForType(type);
        }
    }
}

然后显然我已经替换了配置的标准 XmlFormatter :

Then obviously I've replaced the standard XmlFormatter of my configuration:

config.Formatters.Remove(config.Formatters.XmlFormatter);
config.Formatters.Add(new CustomXmlMediaTypeFormatter());

这篇关于允许.NET WebApi忽略DOCTYPE声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆