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); } }
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 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.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); // 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); // Invoke Operation method var responseObject = operation.DispatchMethod.Invoke(serviceInstance, arguments); 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; } 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); 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); }