• ASP.NET MVC XML绑定Action参数列表


    昨天查看了 ASP.NET MVC 的生命周期,并没有找到类似的解决方案。

    不过今天在 stackoverflow上找到了解决方案,没耐心的同学可以直接戳原文拷贝代码,原文地址:How to pass XML as POST to an ActionResult in ASP MVC .NET

    看了外国同学的说明,才发现 MVC居然可以根据不同的请求 Content Type来选择 ValueProvider,这样提供了很好的扩展。

    MVC本身提供了 JsonValueProviderFactory,顾名思义就是为 Json服务的。那么在这里我们需要提供为 XML服务的ValueProviderFactory。

    第一步:创建 XMLValueProviderFactory

    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, $"{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;
            }
    
            private static string MakeArrayKey(string prefix, int index)
            {
                return prefix + "[" + index.ToString(CultureInfo.InvariantCulture) + "]";
            }
    
            private static string MakePropertyKey(string prefix, string propertyName)
            {
                return (prefix.IsNullOrEmpty()) ? propertyName : prefix + "." + propertyName;
            }
    
            #region ValueProviderFactory Members
    
            public override IValueProvider GetValueProvider(ControllerContext controllerContext)
            {
                var xmlData = GetDeserializedXml(controllerContext);
                if (xmlData == null)
                    return null;
    
                var backingStore = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
                AddToBackingStore(backingStore, String.Empty, xmlData.Root);
                return new DictionaryValueProvider<object>(backingStore, CultureInfo.CurrentCulture);
            }
    
            #endregion
        }

    该段代码属于网上抄袭,基本没有改,在下觉得这样已经满足需求了,原文地址:Sending XML to an ASP.NET MVC Action Method Argument

    PS:如果涉及版权问题,请告知在下。

    第二步:在 Global.asmx.cs 的 Application_Start 方法中注册 ValueProviderFactory

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

     

    亲测可用,如有问题,请留言。

  • 相关阅读:
    kafka重新启动时出现:found a corrupted index file due to requirement failed问题解决方法
    filebeat向kafka中传输数据报WARN Failed to connect to broker DOMSDev07:9092: dial tcp: lookup DOMSDev07: getaddrinfow: No such host is known.解决方法
    安装Zookeeper出现Unable to start AdminServer,existing abnormally问题解决方法
    Windows Server 2008 R2 安装WinDbg以及符号路径设置
    Windows安装ElastAlert问题总结
    Windows系统下Log4Net+FileBeat+ELK日志分析系统问题总结
    Anaconda和basemap的安装和使用
    temp
    Mininet-wifi典型用法
    mininet-wifi 创建ryu和ofsoftswitch的拓扑流程
  • 原文地址:https://www.cnblogs.com/Currention/p/5169597.html
Copyright © 2020-2023  润新知