首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >允许.NET WebApi无视DOCTYPE声明

允许.NET WebApi无视DOCTYPE声明
EN

Stack Overflow用户
提问于 2014-10-07 04:03:40
回答 2查看 1.1K关注 0票数 2

我试图通过WebApi方法将XML反序列化为对象。

我有以下课程:

代码语言:javascript
运行
复制
[XmlRoot(IsNullable = false)]
public class MyObject 
{
     [XmlElement("Name")]
     public string Name {get;set;}
}

以及WebApi控制器中的下列方法。

代码语言:javascript
运行
复制
 [HttpPost]
 public HttpResponseMessage UpdateMyObject(MyObject model)
 {
   //do something with the model
 }

在网络项目的启动过程中,我通过设置以下内容来使用XmlSerializer

代码语言:javascript
运行
复制
config.Formatters.XmlFormatter.UseXmlSerializer = true;

当我发布以下XML时,model被正确地反序列化,并且我可以读取它的属性。

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="UTF-8"?>
<MyObject>
    <Name>HelloWorld</Name>
</MyObject>

但是,当我发布带有DOCTYPE声明的XML时,model值为null,而且似乎没有在方法条目上反序列化。也就是说,这个XML没有反序列化为一个模型:

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE MyObject SYSTEM "http://example.com/MyObject.dtd">
<MyObject>
    <Name>HelloWorld</Name>
</MyObject>

希望有人能帮忙。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-04-15 13:51:35

即使是个老职位,我也发现自己也处于同样的境地。最后,我编写了一个XmlMediaTypeFormatter的自定义版本,覆盖了ReadFromStreamAsync方法。

在这里,我的个人解决方案:

代码语言:javascript
运行
复制
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:

代码语言:javascript
运行
复制
config.Formatters.Remove(config.Formatters.XmlFormatter);
config.Formatters.Add(new CustomXmlMediaTypeFormatter());
票数 6
EN

Stack Overflow用户

发布于 2014-10-07 04:59:30

我还没有尝试过DOCTYPEs,但是实现IXmlSerializable接口应该可以让您完全控制XmlSerializer对对象序列化的控制。

IXmlSerializable接口

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26228371

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档