Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
            }
        }