private Message CreateResponseMessage(OperationDescription operation, object responseObject, Dictionary <string, object> resultOutDictionary, string soapAction, Message requestMessage) { Message responseMessage; // Create response message var bodyWriter = new ServiceBodyWriter(_serializer, operation, responseObject, resultOutDictionary); if (_messageEncoders[0].MessageVersion.Addressing == AddressingVersion.WSAddressing10) { responseMessage = Message.CreateMessage(_messageEncoders[0].MessageVersion, soapAction, bodyWriter); responseMessage = new CustomMessage(responseMessage); responseMessage.Headers.Action = operation.ReplyAction; responseMessage.Headers.RelatesTo = requestMessage.Headers.MessageId; responseMessage.Headers.To = requestMessage.Headers.ReplyTo?.Uri; } else { responseMessage = Message.CreateMessage(_messageEncoders[0].MessageVersion, null, bodyWriter); responseMessage = new CustomMessage(responseMessage); if (responseObject != null) { var messageHeaderMembers = responseObject.GetType().GetMembersWithAttribute <MessageHeaderAttribute>(); foreach (var messageHeaderMember in messageHeaderMembers) { var messageHeaderAttribute = messageHeaderMember.GetCustomAttribute <MessageHeaderAttribute>(); responseMessage.Headers.Add(MessageHeader.CreateHeader(messageHeaderAttribute.Name ?? messageHeaderMember.Name, operation.Contract.Namespace, messageHeaderMember.GetPropertyOrFieldValue(responseObject))); } } } return(responseMessage); }
private async Task <Message> ProcessOperation(HttpContext httpContext, IServiceProvider serviceProvider) { Message responseMessage; //Reload the body to ensure we have the full message var mstm = new MemoryStream((int)httpContext.Request.ContentLength.GetValueOrDefault(1024)); await httpContext.Request.Body.CopyToAsync(mstm).ConfigureAwait(false); mstm.Seek(0, SeekOrigin.Begin); httpContext.Request.Body = mstm; //Return metadata if no request if (httpContext.Request.Body.Length == 0) { return(ProcessMeta(httpContext)); } //Get the message var requestMessage = _messageEncoder.ReadMessage(httpContext.Request.Body, 0x10000, httpContext.Request.ContentType); // Get MessageFilters, ModelBindingFilters var messageFilters = serviceProvider.GetServices <IMessageFilter>(); var modelBindingFilters = serviceProvider.GetServices <IModelBindingFilter>(); // Execute request message filters try { foreach (var messageFilter in messageFilters) { messageFilter.OnRequestExecuting(requestMessage); } } catch (Exception ex) { responseMessage = WriteErrorResponseMessage(ex, StatusCodes.Status500InternalServerError, serviceProvider, httpContext); return(responseMessage); } var messageInspector = serviceProvider.GetService <IMessageInspector>(); var correlationObject = messageInspector?.AfterReceiveRequest(ref requestMessage); // for getting soapaction and parameters in body // GetReaderAtBodyContents must not be called twice in one request using (var reader = requestMessage.GetReaderAtBodyContents()) { var soapAction = GetSoapAction(httpContext, requestMessage, reader); requestMessage.Headers.Action = soapAction; var operation = _service.Operations.FirstOrDefault(o => o.SoapAction.Equals(soapAction, StringComparison.Ordinal) || o.Name.Equals(soapAction, StringComparison.Ordinal)); if (operation == null) { throw new InvalidOperationException($"No operation found for specified action: {requestMessage.Headers.Action}"); } _logger.LogInformation($"Request for operation {operation.Contract.Name}.{operation.Name} received"); try { //Create an instance of the service class var serviceInstance = serviceProvider.GetService(_service.ServiceType); var headerProperty = _service.ServiceType.GetProperty("MessageHeaders"); if (headerProperty != null && headerProperty.PropertyType == requestMessage.Headers.GetType()) { headerProperty.SetValue(serviceInstance, requestMessage.Headers); } // Get operation arguments from message Dictionary <string, object> outArgs = new Dictionary <string, object>(); var arguments = GetRequestArguments(requestMessage, reader, operation, ref outArgs); // Execute model binding filters object modelBindingOutput = null; foreach (var modelBindingFilter in modelBindingFilters) { foreach (var modelType in modelBindingFilter.ModelTypes) { foreach (var arg in arguments) { if (arg != null && arg.GetType() == modelType) { modelBindingFilter.OnModelBound(arg, serviceProvider, out modelBindingOutput); } } } } // avoid Concat() and ToArray() cost when no out args(this may be heavy operation) var allArgs = outArgs.Count != 0 ? arguments.Concat(outArgs.Values).ToArray() : arguments; // 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 object[] { operation.Name, allArgs, httpContext, modelBindingOutput }); } // Invoke Operation method var responseObject = operation.DispatchMethod.Invoke(serviceInstance, allArgs); if (operation.DispatchMethod.ReturnType.IsConstructedGenericType && operation.DispatchMethod.ReturnType.GetGenericTypeDefinition() == typeof(Task <>)) { var responseTask = (Task)responseObject; await responseTask; responseObject = responseTask.GetType().GetProperty("Result").GetValue(responseTask); } else if (responseObject is Task responseTask) { await responseTask; // VoidTaskResult responseObject = null; } int i = arguments.Length; var resultOutDictionary = new Dictionary <string, object>(); foreach (var outArg in outArgs) { resultOutDictionary[outArg.Key] = allArgs[i]; i++; } // Create response message var resultName = operation.ReturnName; var bodyWriter = new ServiceBodyWriter(_serializer, operation.Contract.Namespace, operation.Name + "Response", resultName, responseObject, resultOutDictionary); responseMessage = Message.CreateMessage(_messageEncoder.MessageVersion, null, bodyWriter); responseMessage = new CustomMessage(responseMessage); httpContext.Response.ContentType = httpContext.Request.ContentType; httpContext.Response.Headers["SOAPAction"] = responseMessage.Headers.Action; messageInspector?.BeforeSendReply(ref responseMessage, correlationObject); _messageEncoder.WriteMessage(responseMessage, httpContext.Response.Body); } catch (Exception exception) { _logger.LogWarning(0, exception, exception.Message); responseMessage = WriteErrorResponseMessage(exception, StatusCodes.Status500InternalServerError, serviceProvider, httpContext); } } // Execute response message filters try { foreach (var messageFilter in messageFilters) { messageFilter.OnResponseExecuting(responseMessage); } } catch (Exception ex) { responseMessage = WriteErrorResponseMessage(ex, StatusCodes.Status500InternalServerError, serviceProvider, httpContext); return(responseMessage); } return(responseMessage); }
private async Task <Message> ProcessOperation(HttpContext httpContext, IServiceProvider serviceProvider) { Message responseMessage; //Reload the body to ensure we have the full message var mstm = new MemoryStream((int)httpContext.Request.ContentLength.GetValueOrDefault(1024)); await httpContext.Request.Body.CopyToAsync(mstm).ConfigureAwait(false); mstm.Seek(0, SeekOrigin.Begin); httpContext.Request.Body = mstm; //Return metadata if no request if (httpContext.Request.Body.Length == 0) { return(ProcessMeta(httpContext)); } // Get the encoder based on Content Type var messageEncoder = _messageEncoders[0]; for (int i = 0; i < _messageEncoders.Length; i++) { if (_messageEncoders[i].IsContentTypeSupported(httpContext.Request.ContentType)) { messageEncoder = _messageEncoders[i]; break; } } //try //{ // //Get the message // var requestMessage1 = messageEncoder.ReadMessage(httpContext.Request.Body, 0x10000, httpContext.Request.ContentType); //} //catch(Exception ex) //{ // Console.WriteLine(ex.Message); //} //Get the message var requestMessage = messageEncoder.ReadMessage(httpContext.Request.Body, 0x10000, httpContext.Request.ContentType); // Get MessageFilters, ModelBindingFilters var messageFilters = serviceProvider.GetServices <IMessageFilter>(); var asyncMessageFilters = serviceProvider.GetServices <IAsyncMessageFilter>(); var modelBindingFilters = serviceProvider.GetServices <IModelBindingFilter>(); // Execute request message filters try { foreach (var messageFilter in messageFilters) { messageFilter.OnRequestExecuting(requestMessage); } foreach (var messageFilter in asyncMessageFilters) { await messageFilter.OnRequestExecuting(requestMessage); } } catch (Exception ex) { responseMessage = WriteErrorResponseMessage(ex, StatusCodes.Status500InternalServerError, serviceProvider, messageEncoder, requestMessage, httpContext); return(responseMessage); } var messageInspector = serviceProvider.GetService <IMessageInspector>(); var correlationObject = default(object); try { correlationObject = messageInspector?.AfterReceiveRequest(ref requestMessage); } catch (Exception ex) { responseMessage = WriteErrorResponseMessage(ex, StatusCodes.Status500InternalServerError, serviceProvider, messageEncoder, requestMessage, httpContext); return(responseMessage); } var messageInspector2s = serviceProvider.GetServices <IMessageInspector2>(); #pragma warning disable SA1009 // StyleCop has not yet been updated to support tuples var correlationObjects2 = default(List <(IMessageInspector2 inspector, object correlationObject)>); #pragma warning restore SA1009 try { #pragma warning disable SA1008 // StyleCop has not yet been updated to support tuples correlationObjects2 = messageInspector2s.Select(mi => (inspector: mi, correlationObject: mi.AfterReceiveRequest(ref requestMessage, _service))).ToList(); #pragma warning restore SA1008 } catch (Exception ex) { responseMessage = WriteErrorResponseMessage(ex, StatusCodes.Status500InternalServerError, serviceProvider, messageEncoder, requestMessage, httpContext); return(responseMessage); } // for getting soapaction and parameters in body // GetReaderAtBodyContents must not be called twice in one request using (var reader = requestMessage.GetReaderAtBodyContents()) { var soapAction = GetSoapAction(httpContext, requestMessage, reader); requestMessage.Headers.Action = soapAction; var operation = _service.Operations.FirstOrDefault(o => o.SoapAction.Equals(soapAction, StringComparison.Ordinal) || o.Name.Equals(soapAction, StringComparison.Ordinal)); if (operation == null) { throw new InvalidOperationException($"No operation found for specified action: {requestMessage.Headers.Action}"); } _logger.LogInformation($"Request for operation {operation.Contract.Name}.{operation.Name} received"); try { //Create an instance of the service class var serviceInstance = serviceProvider.GetRequiredService(_service.ServiceType); var headerProperty = _service.ServiceType.GetProperty("MessageHeaders"); if (headerProperty != null && headerProperty.PropertyType == requestMessage.Headers.GetType()) { headerProperty.SetValue(serviceInstance, requestMessage.Headers); } // Get operation arguments from message var arguments = GetRequestArguments(requestMessage, reader, operation, httpContext); // Execute model binding filters object modelBindingOutput = null; foreach (var modelBindingFilter in modelBindingFilters) { 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 object[] { 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); } var invoker = serviceProvider.GetService <IOperationInvoker>() ?? new DefaultOperationInvoker(); var responseObject = await invoker.InvokeAsync(operation.DispatchMethod, serviceInstance, arguments); var resultOutDictionary = new Dictionary <string, object>(); foreach (var parameterInfo in operation.OutParameters) { resultOutDictionary[parameterInfo.Name] = arguments[parameterInfo.Index]; } // Create response message var resultName = operation.ReturnName; var bodyWriter = new ServiceBodyWriter(_serializer, operation, resultName, responseObject, resultOutDictionary); if (messageEncoder.MessageVersion.Addressing == AddressingVersion.WSAddressing10) { responseMessage = Message.CreateMessage(messageEncoder.MessageVersion, soapAction, bodyWriter); responseMessage = new CustomMessage(responseMessage); responseMessage.Headers.Action = operation.ReplyAction; responseMessage.Headers.RelatesTo = requestMessage.Headers.MessageId; responseMessage.Headers.To = requestMessage.Headers.ReplyTo?.Uri; } else { responseMessage = Message.CreateMessage(messageEncoder.MessageVersion, null, bodyWriter); responseMessage = new CustomMessage(responseMessage); } httpContext.Response.ContentType = httpContext.Request.ContentType; httpContext.Response.Headers["SOAPAction"] = responseMessage.Headers.Action; correlationObjects2.ForEach(mi => mi.inspector.BeforeSendReply(ref responseMessage, _service, mi.correlationObject)); messageInspector?.BeforeSendReply(ref responseMessage, correlationObject); messageEncoder.WriteMessage(responseMessage, httpContext.Response.Body); } catch (Exception exception) { if (exception is TargetInvocationException targetInvocationException) { exception = targetInvocationException.InnerException; } _logger.LogWarning(0, exception, exception.Message); responseMessage = WriteErrorResponseMessage(exception, StatusCodes.Status500InternalServerError, serviceProvider, messageEncoder, requestMessage, httpContext); } } // Execute response message filters try { foreach (var messageFilter in messageFilters) { messageFilter.OnResponseExecuting(responseMessage); } foreach (var messageFilter in asyncMessageFilters.Reverse()) { await messageFilter.OnResponseExecuting(responseMessage); } } catch (Exception ex) { responseMessage = WriteErrorResponseMessage(ex, StatusCodes.Status500InternalServerError, serviceProvider, messageEncoder, requestMessage, httpContext); return(responseMessage); } return(responseMessage); }
private async Task <Message> ProcessOperation(HttpContext httpContext, IServiceProvider serviceProvider) { Message responseMessage; //Reload the body to ensure we have the full message using (var reader = new StreamReader(httpContext.Request.Body)) { var body = await reader.ReadToEndAsync(); var requestData = Encoding.UTF8.GetBytes(body); httpContext.Request.Body = new MemoryStream(requestData); } //Return metadata if no request if (httpContext.Request.Body.Length == 0) { return(ProcessMeta(httpContext)); } //Get the message var requestMessage = _messageEncoder.ReadMessage(httpContext.Request.Body, 0x10000, httpContext.Request.ContentType); var messageInspector = serviceProvider.GetService <IMessageInspector>(); messageInspector?.AfterReceiveRequest(requestMessage); // for getting soapaction and parameters in body // GetReaderAtBodyContents must not be called twice in one request using (var reader = requestMessage.GetReaderAtBodyContents()) { var soapAction = httpContext.Request.Headers["SOAPAction"].FirstOrDefault(); if (string.IsNullOrEmpty(soapAction)) { // action name is in body soap1.2 soapAction = reader.LocalName; } if (!string.IsNullOrEmpty(soapAction)) { soapAction = soapAction.Trim('/', '"'); requestMessage.Headers.Action = soapAction; } var operation = _service.Operations.FirstOrDefault(o => o.SoapAction.Equals(soapAction, StringComparison.Ordinal) || o.Name.Equals(soapAction, StringComparison.Ordinal)); if (operation == null) { throw new InvalidOperationException($"No operation found for specified action: {requestMessage.Headers.Action}"); } _logger.LogInformation($"Request for operation {operation.Contract.Name}.{operation.Name} received"); try { //Create an instance of the service class var serviceInstance = serviceProvider.GetService(_service.ServiceType); var headerProperty = _service.ServiceType.GetProperty("MessageHeaders"); if (headerProperty != null && headerProperty.PropertyType == requestMessage.Headers.GetType()) { headerProperty.SetValue(serviceInstance, requestMessage.Headers); } // Get operation arguments from message Dictionary <string, object> outArgs = new Dictionary <string, object>(); var arguments = GetRequestArguments(requestMessage, reader, operation, ref outArgs); var allArgs = arguments.Concat(outArgs.Values).ToArray(); // Invoke Operation method var responseObject = operation.DispatchMethod.Invoke(serviceInstance, allArgs); if (operation.DispatchMethod.ReturnType.IsConstructedGenericType && operation.DispatchMethod.ReturnType.GetGenericTypeDefinition() == typeof(Task <>)) { var responseTask = (Task)responseObject; await responseTask; responseObject = responseTask.GetType().GetProperty("Result").GetValue(responseTask); } int i = arguments.Length; var resultOutDictionary = new Dictionary <string, object>(); foreach (var outArg in outArgs) { resultOutDictionary[outArg.Key] = allArgs[i]; i++; } // Create response message var resultName = operation.DispatchMethod.ReturnParameter.GetCustomAttribute <MessageParameterAttribute>()?.Name ?? operation.Name + "Result"; var bodyWriter = new ServiceBodyWriter(_serializer, operation.Contract.Namespace, operation.Name + "Response", resultName, responseObject, resultOutDictionary); responseMessage = Message.CreateMessage(_messageEncoder.MessageVersion, null, bodyWriter); responseMessage = new CustomMessage(responseMessage); httpContext.Response.ContentType = httpContext.Request.ContentType; httpContext.Response.Headers["SOAPAction"] = responseMessage.Headers.Action; messageInspector?.BeforeSendReply(responseMessage); _messageEncoder.WriteMessage(responseMessage, httpContext.Response.Body); } catch (Exception exception) { _logger.LogWarning(0, exception, exception.Message); responseMessage = WriteErrorResponseMessage(exception, StatusCodes.Status500InternalServerError, serviceProvider, httpContext); } } return(responseMessage); }
public async Task Invoke(HttpContext httpContext, IServiceProvider serviceProvider) { Console.WriteLine($"Request for {httpContext.Request.Path} received ({httpContext.Request.ContentLength ?? 0} bytes)"); if (httpContext.Request.Path.Equals(_endpointPath, StringComparison.Ordinal)) { Message responseMessage; // Read request message var requestMessage = _messageEncoder.ReadMessage(httpContext.Request.Body, 0x10000, httpContext.Request.ContentType); var soapAction = httpContext.Request.Headers["SOAPAction"].ToString().Trim('\"'); if (!string.IsNullOrEmpty(soapAction)) { requestMessage.Headers.Action = soapAction; } var operation = _service.Operations.FirstOrDefault( o => o.SoapAction.Equals(requestMessage.Headers.Action, StringComparison.Ordinal)); if (operation == null) { throw new InvalidOperationException($"No operation found for specified action: {requestMessage.Headers.Action}"); } // Get service type var serviceInstance = serviceProvider.GetService(_service.ServiceType); // Get operation arguments from message Dictionary <string, object> outArgs = new Dictionary <string, object>(); var arguments = GetRequestArguments(requestMessage, operation, ref outArgs); var allArgs = arguments.Concat(outArgs.Values).ToArray(); // Invoke Operation method try { var responseObject = operation.DispatchMethod.Invoke(serviceInstance, allArgs); int i = arguments.Length; var resultOutDictionary = new Dictionary <string, object>(); foreach (var outArg in outArgs) { resultOutDictionary[outArg.Key] = allArgs[i]; i++; } // Create response message var resultName = operation.DispatchMethod.ReturnParameter.GetCustomAttribute <MessageParameterAttribute>()?.Name ?? operation.Name + "Result"; var bodyWriter = new ServiceBodyWriter(operation.Contract.Namespace, operation.Name + "Response", resultName, responseObject, resultOutDictionary); responseMessage = Message.CreateMessage(_messageEncoder.MessageVersion, null, bodyWriter); responseMessage = new CustomMessage(responseMessage); httpContext.Response.ContentType = httpContext.Request.ContentType; // _messageEncoder.ContentType; httpContext.Response.Headers["SOAPAction"] = responseMessage.Headers.Action; _messageEncoder.WriteMessage(responseMessage, httpContext.Response.Body); } catch (Exception exception) { // Create response message var errorText = exception.InnerException.Message; var transformer = serviceProvider.GetService <ExceptionTransformer>(); if (transformer != null) { errorText = transformer.Transform(exception.InnerException); } var bodyWriter = new FaultBodyWriter(new Fault { FaultString = errorText }); responseMessage = Message.CreateMessage(_messageEncoder.MessageVersion, null, bodyWriter); responseMessage = new CustomMessage(responseMessage); httpContext.Response.ContentType = httpContext.Request.ContentType; // _messageEncoder.ContentType; httpContext.Response.Headers["SOAPAction"] = responseMessage.Headers.Action; httpContext.Response.StatusCode = StatusCodes.Status500InternalServerError; _messageEncoder.WriteMessage(responseMessage, httpContext.Response.Body); } } else { await _next(httpContext); } }