zoukankan      html  css  js  c++  java
  • 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());
     

     

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

  • 相关阅读:
    frida hook native -- frida hook so层 实例代码讲解
    frida hook 类所有方法(ZenTracker)
    frida hook AES DES RSA 自吐算法
    frida java层和c层打印堆栈 (修复优化)
    frida延时hook的3种方法
    [去广告]x米万能遥控 去掉底部banner广告
    Linux使用C语言连接MYSQL
    Linux一对一通信(UDP)
    Linux一对多的通信
    Linux一对一的通信
  • 原文地址:https://www.cnblogs.com/Currention/p/5169597.html
Copyright © 2011-2022 走看看