在ASP.NET Web App中通过HTTP POST接收XML

时间:2015-06-25 16:44:32

标签: c# asp.net xml http

我在Visual Studio中创建了一个ASP.NET MVC 4 Web应用程序,并且需要能够通过HTTP POST接收XML。最好的方法是什么?

2 个答案:

答案 0 :(得分:0)

读取通过HTTP POST进入控制器的数据
HttpContext.Current.Request.InputStream

您可以使用StreamReader的ReadToEnd方法将其读入字符串。

由于它是标题中指定的xml,如果要将其加载到XDocument中,则应将其读入字节数组并从该字节数组创建MemoryStream以在XDocument的Load方法中使用。

示例:

var message = XDocument.Load(new UTF8Encoding().GetBytes(new StreamReader(HttpContext.Current.Request.InputStream).ReadToEnd()));

为您提供一个包含已发布的xml的XDocument。

答案 1 :(得分:0)

您必须添加xmlvalueproviderfactory

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Web.Mvc;
using System.Xml;
using System.Xml.Linq;

public class XmlValueProviderFactory : ValueProviderFactory
{
    private static void AddToBackingStore(Dictionary<string, object> backingStore, string prefix, XElement xmlDoc)
    {
        // Check the keys to see if this is an array or an object
        var uniqueKeys = new List<String>();
        int totalCount = 0;
        foreach (XElement element in xmlDoc.Elements())
        {
            if(!uniqueKeys.Contains(element.Name.LocalName)) {
                uniqueKeys.Add(element.Name.LocalName);
            }
            totalCount++;
        }

        bool isArray;
        if (uniqueKeys.Count == 1) {
            isArray = true;
        }
        else if (uniqueKeys.Count == totalCount) {
            isArray = false;
        }
        else {
            // Not sure how to deal with a XML doc that has some keys the same, but not all
            // For now don't process this node
            return;
        }

        // Add the elements to the backing store
        int elementCount = 0;
        foreach (XElement element in xmlDoc.Elements())
        {
            if (element.HasElements)
            {
                if (isArray)
                {
                    // Omit local name for arrays and add index instead
                    AddToBackingStore(backingStore, String.Format("{0}[{1}]", prefix, elementCount), element);
                }
                else
                {
                    AddToBackingStore(backingStore, MakePropertyKey(prefix, element.Name.LocalName), element);
                }
            }
            else
            {
                backingStore.Add(MakePropertyKey(prefix, element.Name.LocalName), element.Value);
            }

            elementCount++;
        }
    }

    private static XDocument GetDeserializedXml(ControllerContext controllerContext) {
        var contentType = controllerContext.HttpContext.Request.ContentType;
        if (!contentType.StartsWith("text/xml", StringComparison.OrdinalIgnoreCase)
            && !contentType.StartsWith("application/xml", StringComparison.OrdinalIgnoreCase)) {
            // Are there any other XML mime types that are used? (Add them here)

            // not XML request
            return null;
        }


        XDocument xml;
        try
        {
            // DTD processing disabled to stop XML bomb attack - if you require DTD processing, read this first: http://msdn.microsoft.com/en-us/magazine/ee335713.aspx
            var xmlReaderSettings = new XmlReaderSettings { DtdProcessing = DtdProcessing.Prohibit };
            var xmlReader = XmlReader.Create(controllerContext.HttpContext.Request.InputStream, xmlReaderSettings);
            xml = XDocument.Load(xmlReader);
        }
        catch (Exception)
        {
            return null;
        }


        if (xml.FirstNode == null)
        {
            // No XML data
            return null;
        }

        return xml;
    }

    public override IValueProvider GetValueProvider(ControllerContext controllerContext) {
        XDocument xmlData = GetDeserializedXml(controllerContext);
        if (xmlData == null) {
            return null;
        }

        Dictionary<string, object> backingStore = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
        AddToBackingStore(backingStore, String.Empty, xmlData.Root);
        return new DictionaryValueProvider<object>(backingStore, CultureInfo.CurrentCulture);
    }

    private static string MakeArrayKey(string prefix, int index) {
        return prefix + "[" + index.ToString(CultureInfo.InvariantCulture) + "]";
    }

    private static string MakePropertyKey(string prefix, string propertyName) {
        return (String.IsNullOrEmpty(prefix)) ? propertyName : prefix + "." + propertyName;
    }
}

然后在你的应用程序启动时,调用

  ValueProviderFactories.Factories.Add(new XmlValueProviderFactory());