예제 #1
0
        public object DeserializeInputParameter(
            System.Xml.XmlDictionaryReader xmlReader,
            Type parameterType,
            string parameterName,
            string parameterNs,
            ICustomAttributeProvider customAttributeProvider,
            IEnumerable <Type> knownTypes = null)
        {
            // Advance past any whitespace.
            while (xmlReader.NodeType == System.Xml.XmlNodeType.Whitespace && xmlReader.Read())
            {
            }

            if (xmlReader.IsStartElement(parameterName, parameterNs))
            {
                xmlReader.MoveToStartElement(parameterName, parameterNs);

                if (xmlReader.IsStartElement(parameterName, parameterNs))
                {
                    switch (_serializer)
                    {
                    case SoapSerializer.XmlSerializer:
                        if (!parameterType.IsArray)
                        {
                            // case [XmlElement("parameter")] int parameter
                            // case [XmlArray("parameter")] int[] parameter
                            return(DeserializeObject(xmlReader, parameterType, parameterName, parameterNs));
                        }
                        else
                        {
                            // case int[] parameter
                            // case [XmlElement("parameter")] int[] parameter
                            // case [XmlArray("parameter"), XmlArrayItem(ElementName = "item")] int[] parameter
                            return(DeserializeArrayXmlSerializer(xmlReader, parameterType, parameterName, parameterNs, customAttributeProvider));
                        }

                    case SoapSerializer.DataContractSerializer:
                        return(DeserializeDataContract(xmlReader, parameterType, parameterName, parameterNs, knownTypes));

                    default:
                        throw new NotImplementedException();
                    }
                }
            }

            if (parameterType.IsArray)
            {
                return(Array.CreateInstance(parameterType.GetElementType(), 0));
            }

            return(null);
        }
예제 #2
0
        private static object DeserializeObject(System.Xml.XmlDictionaryReader xmlReader, Type parameterType, string parameterName, string parameterNs)
        {
            // see https://referencesource.microsoft.com/System.Xml/System/Xml/Serialization/XmlSerializer.cs.html#c97688a6c07294d5
            var elementType = parameterType.GetElementType();

            if (elementType == null || parameterType.IsArray)
            {
                elementType = parameterType;
            }

            var serializer = CachedXmlSerializer.GetXmlSerializer(elementType, parameterName, parameterNs);

            lock (serializer)
            {
                if (elementType == typeof(Stream) || typeof(Stream).IsAssignableFrom(elementType))
                {
                    xmlReader.Read();
                    return(new MemoryStream(xmlReader.ReadContentAsBase64()));
                }

                return(serializer.Deserialize(xmlReader));
            }
        }
예제 #3
0
        private object[] GetRequestArguments(Message requestMessage, System.Xml.XmlDictionaryReader xmlReader, OperationDescription operation, HttpContext httpContext)
        {
            var arguments = new object[operation.AllParameters.Length];

            // if any ordering issues, possible to rewrite like:

            /*while (!xmlReader.EOF)
             * {
             *      var parameterInfo = operation.InParameters.FirstOrDefault(p => p.Name == xmlReader.LocalName && p.Namespace == xmlReader.NamespaceURI);
             *      if (parameterInfo == null)
             *      {
             *              xmlReader.Skip();
             *              continue;
             *      }
             *      var parameterName = parameterInfo.Name;
             *      var parameterNs = parameterInfo.Namespace;
             *      ...
             * }*/

            // Find the element for the operation's data
            if (!operation.IsMessageContractRequest)
            {
                xmlReader.ReadStartElement(operation.Name, operation.Contract.Namespace);

                foreach (var parameterInfo in operation.InParameters)
                {
                    var parameterType = parameterInfo.Parameter.ParameterType;

                    if (parameterType == typeof(HttpContext))
                    {
                        arguments[parameterInfo.Index] = httpContext;
                    }
                    else
                    {
                        var argumentValue = _serializerHelper.DeserializeInputParameter(xmlReader, parameterType, parameterInfo.Name, operation.Contract.Namespace, parameterInfo);

                        //fix https://github.com/DigDes/SoapCore/issues/379 (hack, need research)
                        if (argumentValue == null)
                        {
                            argumentValue = _serializerHelper.DeserializeInputParameter(xmlReader, parameterType, parameterInfo.Name, parameterInfo.Namespace, parameterInfo);
                        }

                        arguments[parameterInfo.Index] = argumentValue;
                    }
                }
            }
            else
            {
                // MessageContracts are constrained to having one "InParameter". We can do special logic on
                // for this
                Debug.Assert(operation.InParameters.Length == 1, "MessageContracts are constrained to having one 'InParameter'");

                var parameterInfo = operation.InParameters[0];
                var parameterType = parameterInfo.Parameter.ParameterType;

                var messageContractAttribute = parameterType.GetCustomAttribute <MessageContractAttribute>();

                Debug.Assert(messageContractAttribute != null, "operation.IsMessageContractRequest should be false if this is null");

                var @namespace = parameterInfo.Namespace ?? operation.Contract.Namespace;

                if (messageContractAttribute.IsWrapped && !parameterType.GetMembersWithAttribute <MessageHeaderAttribute>().Any())
                {
                    // It's wrapped so we treat it like normal!
                    arguments[parameterInfo.Index] = _serializerHelper.DeserializeInputParameter(xmlReader, parameterInfo.Parameter.ParameterType, parameterInfo.Name, @namespace, parameterInfo);
                }
                else
                {
                    var messageHeadersMembers = parameterType.GetPropertyOrFieldMembers().Where(x => x.GetCustomAttribute <MessageHeaderAttribute>() != null).ToArray();

                    var wrapperObject = Activator.CreateInstance(parameterInfo.Parameter.ParameterType);

                    for (var i = 0; i < requestMessage.Headers.Count; i++)
                    {
                        var header = requestMessage.Headers[i];
                        var member = messageHeadersMembers.FirstOrDefault(x => x.Name == header.Name);

                        if (member != null)
                        {
                            var messageHeaderAttribute = member.GetCustomAttribute <MessageHeaderAttribute>();
                            var reader = requestMessage.Headers.GetReaderAtHeader(i);

                            var value = _serializerHelper.DeserializeInputParameter(reader, member.GetPropertyOrFieldType(), messageHeaderAttribute.Name ?? member.Name, messageHeaderAttribute.Namespace ?? @namespace);

                            member.SetValueToPropertyOrField(wrapperObject, value);
                        }
                    }

                    // This object isn't a wrapper element, so we will hunt for the nested message body
                    // member inside of it
                    var messageBodyMembers = parameterType.GetPropertyOrFieldMembers().Where(x => x.GetCustomAttribute <MessageBodyMemberAttribute>() != null).Select(mi => new
                    {
                        Member = mi,
                        MessageBodyMemberAttribute = mi.GetCustomAttribute <MessageBodyMemberAttribute>()
                    }).OrderBy(x => x.MessageBodyMemberAttribute.Order);

                    if (messageContractAttribute.IsWrapped)
                    {
                        xmlReader.Read();
                    }

                    foreach (var messageBodyMember in messageBodyMembers)
                    {
                        var messageBodyMemberAttribute = messageBodyMember.MessageBodyMemberAttribute;
                        var messageBodyMemberInfo      = messageBodyMember.Member;

                        var innerParameterName = messageBodyMemberAttribute.Name ?? messageBodyMemberInfo.Name;
                        var innerParameterNs   = messageBodyMemberAttribute.Namespace ?? @namespace;
                        var innerParameterType = messageBodyMemberInfo.GetPropertyOrFieldType();

                        //xmlReader.MoveToStartElement(innerParameterName, innerParameterNs);
                        var innerParameter = _serializerHelper.DeserializeInputParameter(xmlReader, innerParameterType, innerParameterName, innerParameterNs, parameterInfo);

                        messageBodyMemberInfo.SetValueToPropertyOrField(wrapperObject, innerParameter);
                    }

                    arguments[parameterInfo.Index] = wrapperObject;
                }
            }

            foreach (var parameterInfo in operation.OutParameters)
            {
                if (arguments[parameterInfo.Index] != null)
                {
                    // do not overwrite input ref parameters
                    continue;
                }

                if (parameterInfo.Parameter.ParameterType.Name == "Guid&")
                {
                    arguments[parameterInfo.Index] = Guid.Empty;
                }
                else if (parameterInfo.Parameter.ParameterType.Name == "String&" || parameterInfo.Parameter.ParameterType.GetElementType().IsArray)
                {
                    arguments[parameterInfo.Index] = null;
                }
                else
                {
                    var type = parameterInfo.Parameter.ParameterType.GetElementType();
                    arguments[parameterInfo.Index] = Activator.CreateInstance(type);
                }
            }

            return(arguments);
        }