public void Tune(HttpContext httpContext, object serviceInstance, SoapCore.OperationDescription operation) { IsCalled = true; if ((serviceInstance != null) && (serviceInstance is TestService) && operation.Name.Equals("PingWithServiceOperationTuning")) { TestService service = serviceInstance as TestService; string result = string.Empty; StringValues pingValue; if (httpContext.Request.Headers.TryGetValue("ping_value", out pingValue)) { result = pingValue[0]; } service.SetPingResult(result); IsSetPingValue = true; } }
public void Tune(HttpContext httpContext, object serviceInstance, SoapCore.OperationDescription operation) { }
private object[] GetRequestArguments(Message requestMessage, OperationDescription operation, ref Dictionary <string, object> outArgs) { var parameters = operation.DispatchMethod.GetParameters().Where(x => !x.IsOut && !x.ParameterType.IsByRef).ToArray(); var arguments = new List <object>(); var requestMessageCopy = CopyMessage(ref requestMessage); // Deserialize request wrapper and object using (var xmlReader = requestMessage.GetReaderAtBodyContents()) { var xmlReaderCopy = requestMessageCopy.GetReaderAtBodyContents(); // Find the element for the operation's data xmlReader.ReadStartElement(operation.Name, operation.Contract.Namespace); xmlReaderCopy.ReadStartElement(operation.Name, operation.Contract.Namespace); //DuplicateReaders(xmlReader, out XmlReader xmlReaderClone1, out XmlReader xmlReaderClone2); //StringBuilder sb = new StringBuilder(); //while (xmlReaderClone1.Read()) // sb.AppendLine(xmlReader.ReadOuterXml()); //var str = sb.ToString(); for (int i = 0; i < parameters.Length; i++) { var elementAttribute = parameters[i].GetCustomAttribute <XmlElementAttribute>(); var parameterName = !string.IsNullOrEmpty(elementAttribute?.ElementName) ? elementAttribute.ElementName : parameters[i].GetCustomAttribute <MessageParameterAttribute>()?.Name ?? parameters[i].Name; var parameterNs = elementAttribute?.Namespace ?? operation.Contract.Namespace; if (xmlReader.IsStartElement(parameterName, parameterNs)) { xmlReader.MoveToStartElement(parameterName, parameterNs); xmlReaderCopy.MoveToStartElement(parameterName, parameterNs); if (xmlReader.IsStartElement(parameterName, parameterNs)) { var elementType = parameters[i].ParameterType.GetElementType(); if (elementType == null || parameters[i].ParameterType.IsArray) { elementType = parameters[i].ParameterType; } //Logging(xmlReaderCopy); switch (_serializer) { case SoapSerializer.XmlSerializer: { // see https://referencesource.microsoft.com/System.Xml/System/Xml/Serialization/XmlSerializer.cs.html#c97688a6c07294d5 var serializer = new XmlSerializer(elementType, null, new Type[0], new XmlRootAttribute(parameterName), parameterNs); arguments.Add(serializer.Deserialize(xmlReader)); } break; case SoapSerializer.DataContractSerializer: { var serializer = new DataContractSerializer(elementType); //, parameterName, parameterNs); //arguments.Add(serializer.ReadObject(xmlReader, verifyObjectName: true)); arguments.Add(serializer.ReadObject(xmlReader, false)); } break; default: throw new NotImplementedException(); } } //xmlReader.ReadStartElement(operation.Name, operation.Contract.Namespace); //xmlReader.MoveToStartElement(parameterName, parameterNs); //StringBuilder sb = new StringBuilder(); //while (xmlReader.Read()) // sb.AppendLine(xmlReader.ReadOuterXml()); //var str = sb.ToString(); } else { arguments.Add(null); } } } var outParams = operation.DispatchMethod.GetParameters().Where(x => x.IsOut || x.ParameterType.IsByRef).ToArray(); foreach (var parameterInfo in outParams) { if (parameterInfo.ParameterType.Name == "Guid&") { outArgs[parameterInfo.Name] = Guid.Empty; } else if (parameterInfo.ParameterType.Name == "String&" || parameterInfo.ParameterType.GetElementType().IsArray) { outArgs[parameterInfo.Name] = null; } else { var type = parameterInfo.ParameterType.GetElementType(); outArgs[parameterInfo.Name] = Activator.CreateInstance(type); } } return(arguments.ToArray()); }
private object[] GetRequestArguments(Message requestMessage, System.Xml.XmlDictionaryReader xmlReader, OperationDescription operation, ref Dictionary <string, object> outArgs) { var parameters = operation.NormalParameters; // avoid reallocation var arguments = new List <object>(parameters.Length + operation.OutParameters.Length); // Find the element for the operation's data xmlReader.ReadStartElement(operation.Name, operation.Contract.Namespace); for (int i = 0; i < parameters.Length; i++) { var parameterName = parameters[i].Name; var parameterNs = parameters[i].Namespace; if (xmlReader.IsStartElement(parameterName, parameterNs)) { xmlReader.MoveToStartElement(parameterName, parameterNs); if (xmlReader.IsStartElement(parameterName, parameterNs)) { var elementType = parameters[i].Parameter.ParameterType.GetElementType(); if (elementType == null || parameters[i].Parameter.ParameterType.IsArray) { elementType = parameters[i].Parameter.ParameterType; } switch (_serializer) { case SoapSerializer.XmlSerializer: { // see https://referencesource.microsoft.com/System.Xml/System/Xml/Serialization/XmlSerializer.cs.html#c97688a6c07294d5 var serializer = CachedXmlSerializer.GetXmlSerializer(elementType, parameterName, parameterNs); lock (serializer) arguments.Add(serializer.Deserialize(xmlReader)); } break; case SoapSerializer.DataContractSerializer: { var serializer = new DataContractSerializer(elementType, parameterName, parameterNs); arguments.Add(serializer.ReadObject(xmlReader, verifyObjectName: true)); } break; default: throw new NotImplementedException(); } } } else { arguments.Add(null); } } foreach (var parameterInfo in operation.OutParameters) { if (parameterInfo.Parameter.ParameterType.Name == "Guid&") { outArgs[parameterInfo.Name] = Guid.Empty; } else if (parameterInfo.Parameter.ParameterType.Name == "String&" || parameterInfo.Parameter.ParameterType.GetElementType().IsArray) { outArgs[parameterInfo.Name] = null; } else { var type = parameterInfo.Parameter.ParameterType.GetElementType(); outArgs[parameterInfo.Name] = Activator.CreateInstance(type); } } return(arguments.ToArray()); }
private object[] GetRequestArguments(Message requestMessage, System.Xml.XmlDictionaryReader xmlReader, OperationDescription operation, HttpContext httpContext) { var arguments = new object[operation.AllParameters.Length]; // Find the element for the operation's data if (!operation.IsMessageContractRequest) { xmlReader.ReadStartElement(operation.Name, operation.Contract.Namespace); } // 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; * ... * }*/ foreach (var parameterInfo in operation.InParameters) { var parameterName = parameterInfo.Name; var parameterNs = parameterInfo.Namespace ?? operation.Contract.Namespace; if (xmlReader.IsStartElement(parameterName, parameterNs)) { xmlReader.MoveToStartElement(parameterName, parameterNs); if (xmlReader.IsStartElement(parameterName, parameterNs)) { switch (_serializer) { case SoapSerializer.XmlSerializer: { // case [XmlElement("parameter")] int parameter // case int[] parameter // case [XmlArray("parameter")] int[] parameter if (!parameterInfo.Parameter.ParameterType.IsArray || (parameterInfo.ArrayName != null && parameterInfo.ArrayItemName == null)) { // see https://referencesource.microsoft.com/System.Xml/System/Xml/Serialization/XmlSerializer.cs.html#c97688a6c07294d5 var elementType = parameterInfo.Parameter.ParameterType.GetElementType(); if (elementType == null || parameterInfo.Parameter.ParameterType.IsArray) { elementType = parameterInfo.Parameter.ParameterType; } var serializer = CachedXmlSerializer.GetXmlSerializer(elementType, parameterName, parameterNs); lock (serializer) { arguments[parameterInfo.Index] = serializer.Deserialize(xmlReader); } } // case [XmlElement("parameter")] int[] parameter // case [XmlArray("parameter"), XmlArrayItem(ElementName = "item")] int[] parameter else { //if (parameterInfo.ArrayItemName != null) { xmlReader.ReadStartElement(parameterName, parameterNs); } var elementType = parameterInfo.Parameter.ParameterType.GetElementType(); var localName = parameterInfo.ArrayItemName ?? elementType.Name; if (parameterInfo.ArrayItemName == null && elementType.Namespace.StartsWith("System")) { localName = localName.ToLower(); } //localName = "ComplexModelInput"; var deserializeMethod = typeof(XmlSerializerExtensions) .GetGenericMethod(nameof(XmlSerializerExtensions.DeserializeArray), new[] { elementType }); var serializer = CachedXmlSerializer.GetXmlSerializer(elementType, localName, parameterNs); lock (serializer) { arguments[parameterInfo.Index] = deserializeMethod.Invoke(null, new object[] { serializer, localName, parameterNs, xmlReader }); } //if (parameterInfo.ArrayItemName != null) { xmlReader.ReadEndElement(); } } } break; case SoapSerializer.DataContractSerializer: { var elementType = parameterInfo.Parameter.ParameterType.GetElementType(); if (elementType == null || parameterInfo.Parameter.ParameterType.IsArray) { elementType = parameterInfo.Parameter.ParameterType; } var serializer = new DataContractSerializer(elementType, parameterName, parameterNs); arguments[parameterInfo.Index] = serializer.ReadObject(xmlReader, verifyObjectName: true); } break; default: throw new NotImplementedException(); } } } else if (parameterInfo.Parameter.ParameterType == typeof(HttpContext)) { arguments[parameterInfo.Index] = httpContext; } else { arguments[parameterInfo.Index] = null; } } 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); }
private object[] GetRequestArguments(Message requestMessage, System.Xml.XmlDictionaryReader xmlReader, OperationDescription operation) { var arguments = new object[operation.AllParameters.Length]; // Find the element for the operation's data if (!operation.IsMessageContractRequest) { xmlReader.ReadStartElement(operation.Name, operation.Contract.Namespace); } // 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; * ... * }*/ foreach (var parameterInfo in operation.InParameters) { var parameterName = parameterInfo.Name; var parameterNs = parameterInfo.Namespace; if (xmlReader.IsStartElement(parameterName, parameterNs)) { xmlReader.MoveToStartElement(parameterName, parameterNs); if (xmlReader.IsStartElement(parameterName, parameterNs)) { var elementType = parameterInfo.Parameter.ParameterType.GetElementType(); if (elementType == null || parameterInfo.Parameter.ParameterType.IsArray) { elementType = parameterInfo.Parameter.ParameterType; } switch (_serializer) { case SoapSerializer.XmlSerializer: { // see https://referencesource.microsoft.com/System.Xml/System/Xml/Serialization/XmlSerializer.cs.html#c97688a6c07294d5 var serializer = CachedXmlSerializer.GetXmlSerializer(elementType, parameterName, parameterNs); lock (serializer) { arguments[parameterInfo.Index] = serializer.Deserialize(xmlReader); } } break; case SoapSerializer.DataContractSerializer: { var serializer = new DataContractSerializer(elementType, parameterName, parameterNs); arguments[parameterInfo.Index] = serializer.ReadObject(xmlReader, verifyObjectName: true); } break; default: throw new NotImplementedException(); } } } else { arguments[parameterInfo.Index] = null; } } 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); }
private object[] GetRequestArguments(Message requestMessage, XmlDictionaryReader xmlReader, OperationDescription operation, HttpContext httpContext) { var arguments = new object[operation.AllParameters.Length]; IEnumerable <Type> serviceKnownTypes = operation .GetServiceKnownTypesHierarchy() .Select(x => x.Type); if (!operation.IsMessageContractRequest) { if (xmlReader != null) { xmlReader.ReadStartElement(operation.Name, operation.Contract.Namespace); while (!xmlReader.EOF) { var parameterInfo = operation.InParameters.FirstOrDefault(p => p.Name == xmlReader.LocalName); if (parameterInfo == null) { xmlReader.Skip(); continue; } var parameterType = parameterInfo.Parameter.ParameterType; var argumentValue = _serializerHelper.DeserializeInputParameter( xmlReader, parameterType, parameterInfo.Name, operation.Contract.Namespace, parameterInfo.Parameter.Member, serviceKnownTypes); //fix https://github.com/DigDes/SoapCore/issues/379 (hack, need research) if (argumentValue == null) { argumentValue = _serializerHelper.DeserializeInputParameter( xmlReader, parameterType, parameterInfo.Name, parameterInfo.Namespace, parameterInfo.Parameter.Member, serviceKnownTypes); } arguments[parameterInfo.Index] = argumentValue; } var httpContextParameter = operation.InParameters.FirstOrDefault(x => x.Parameter.ParameterType == typeof(HttpContext)); if (httpContextParameter != default) { arguments[httpContextParameter.Index] = httpContext; } } else { arguments = Array.Empty <object>(); } } 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()) { //https://github.com/DigDes/SoapCore/issues/385 if (operation.DispatchMethod.GetCustomAttribute <XmlSerializerFormatAttribute>()?.Style == OperationFormatStyle.Rpc) { var importer = new SoapReflectionImporter(@namespace); var map = new XmlReflectionMember { IsReturnValue = false, MemberName = parameterInfo.Name, MemberType = parameterType }; var mapping = importer.ImportMembersMapping(parameterInfo.Name, @namespace, new[] { map }, false, true); var serializer = XmlSerializer.FromMappings(new[] { mapping })[0]; var value = serializer.Deserialize(xmlReader); if (value is object[] o && o.Length > 0) { arguments[parameterInfo.Index] = o[0]; } } else { // It's wrapped so we treat it like normal! arguments[parameterInfo.Index] = _serializerHelper.DeserializeInputParameter( xmlReader, parameterInfo.Parameter.ParameterType, parameterInfo.Name, @namespace, parameterInfo.Parameter.Member, serviceKnownTypes); } } else { var messageHeadersMembers = parameterType.GetPropertyOrFieldMembers() .Where(x => x.GetCustomAttribute <MessageHeaderAttribute>() != null) .Select(mi => new { MemberInfo = mi, MessageHeaderMemberAttribute = mi.GetCustomAttribute <MessageHeaderAttribute>() }).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.MessageHeaderMemberAttribute.Name == header.Name || x.MemberInfo.Name == header.Name); if (member != null) { var reader = requestMessage.Headers.GetReaderAtHeader(i); var value = _serializerHelper.DeserializeInputParameter( reader, member.MemberInfo.GetPropertyOrFieldType(), member.MessageHeaderMemberAttribute.Name ?? member.MemberInfo.Name, member.MessageHeaderMemberAttribute.Namespace ?? @namespace, member.MemberInfo, serviceKnownTypes); member.MemberInfo.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.Parameter.Member, serviceKnownTypes); 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); }
private void ExecuteFiltersAndTune(HttpContext httpContext, IServiceProvider serviceProvider, OperationDescription operation, object[] arguments, object serviceInstance) { // Execute model binding filters object modelBindingOutput = null; foreach (var modelBindingFilter in serviceProvider.GetServices <IModelBindingFilter>()) { foreach (var modelType in modelBindingFilter.ModelTypes) { foreach (var parameterInfo in operation.InParameters) { var arg = arguments[parameterInfo.Index]; if (arg != null && arg.GetType() == modelType) { modelBindingFilter.OnModelBound(arg, serviceProvider, out modelBindingOutput); } } } } // Execute Mvc ActionFilters foreach (var actionFilterAttr in operation.DispatchMethod.CustomAttributes.Where(a => a.AttributeType.Name == "ServiceFilterAttribute")) { var actionFilter = serviceProvider.GetService(actionFilterAttr.ConstructorArguments[0].Value as Type); actionFilter.GetType().GetMethod("OnSoapActionExecuting")?.Invoke(actionFilter, new[] { operation.Name, arguments, httpContext, modelBindingOutput }); } // Invoke OnModelBound _soapModelBounder?.OnModelBound(operation.DispatchMethod, arguments); // Tune service instance for operation call var serviceOperationTuners = serviceProvider.GetServices <IServiceOperationTuner>(); foreach (var operationTuner in serviceOperationTuners) { operationTuner.Tune(httpContext, serviceInstance, operation); } }