/// <summary>
        /// Calls service method which implements the X-Road operation.
        /// </summary>
        protected virtual void InvokeServiceMethod(XRoadContext context)
        {
            if (context.ServiceMap != null)
            {
                context.Result = InvokeMetaService(context);
                return;
            }

            context.ServiceMap          = context.Request.GetSerializer().GetServiceMap(context.Request.RootElementName);
            context.Response.BinaryMode = context.ServiceMap.OperationDefinition.OutputBinaryMode;

            var serviceObject = GetServiceObject(context);

            DeserializeMethodInput(context);

            try
            {
                var parameters = context.ServiceMap.RequestDefinition.ParameterInfo != null ? new[] { context.Parameters } : new object[0];
                context.Result = context.ServiceMap.OperationDefinition.MethodInfo.Invoke(serviceObject, parameters);
            }
            catch (Exception exception)
            {
                context.Exception = exception;
                OnInvocationError(context);

                if (context.Result == null)
                {
                    throw;
                }
            }
        }
        /// <summary>
        /// Handle incoming request.
        /// </summary>
        public virtual void ProcessRequest(HttpContext httpContext)
        {
            using (var context = new XRoadContext(httpContext))
            {
                try
                {
                    context.MessageFormatter = XRoadHelper.GetMessageFormatter(httpContext.Request.ContentType);

                    httpContext.Request.InputStream.Position = 0;
                    httpContext.Response.ContentType         = XRoadHelper.GetContentTypeHeader(context.MessageFormatter.ContentType);

                    HandleRequest(context);
                }
                catch (Exception exception)
                {
                    if (context.MessageFormatter == null)
                    {
                        context.MessageFormatter = new SoapMessageFormatter();
                    }

                    httpContext.Response.ContentType = XRoadHelper.GetContentTypeHeader(context.MessageFormatter.ContentType);

                    if (httpContext.Response.OutputStream.CanSeek)
                    {
                        httpContext.Response.OutputStream.Seek(0, SeekOrigin.Begin);
                        httpContext.Response.OutputStream.SetLength(0);
                    }

                    var fault = context.MessageFormatter.CreateFault(exception);

                    OnExceptionOccurred(context, exception, fault);
                }
            }
        }
        /// <summary>
        /// Deserializes X-Road request from SOAP message payload.
        /// </summary>
        protected virtual void DeserializeMethodInput(XRoadContext context)
        {
            var args = new BeforeDeserializationEventArgs();

            OnBeforeDeserialization(context, args);

            context.Request.ContentStream.Position = 0;
            var reader = XmlReader.Create(context.Request.ContentStream, args.XmlReaderSettings);

            context.MessageFormatter.MoveToPayload(reader, context.Request.RootElementName);

            context.Parameters = context.ServiceMap.DeserializeRequest(reader, context.Request);

            OnAfterDeserialization(context);
        }
        /// <summary>
        /// Serializes service result to a X-Road message response.
        /// </summary>
        protected virtual void SerializeXRoadResponse(XRoadContext context)
        {
            OnBeforeSerialization(context);

            context.Request.ContentStream.Position = 0;
            using (var reader = XmlReader.Create(context.Request.ContentStream, new XmlReaderSettings {
                CloseInput = false
            }))
            {
                var writer = new XmlTextWriter(context.Response.ContentStream, context.Response.ContentEncoding);

                writer.WriteStartDocument();

                var protocolDefinition = context.Response.ServiceManager?.ProtocolDefinition;

                if (context.MessageFormatter.TryMoveToEnvelope(reader))
                {
                    context.MessageFormatter.WriteStartEnvelope(writer, reader.Prefix);
                    writer.WriteAttributes(reader, true);
                    writer.WriteMissingAttributes(protocolDefinition);
                }
                else
                {
                    writer.WriteSoapEnvelope(context.MessageFormatter, protocolDefinition);
                }

                if (context.MessageFormatter.TryMoveToHeader(reader))
                {
                    writer.WriteNode(reader, true);
                }

                context.MessageFormatter.WriteStartBody(writer);
                if (context.MessageFormatter.TryMoveToBody(reader))
                {
                    writer.WriteAttributes(reader, true);
                }

                context.ServiceMap.SerializeResponse(writer, context.Result, context.Response, reader, CustomSerialization);

                writer.WriteEndDocument();
                writer.Flush();
            }

            context.Response.SaveTo(context.HttpContext, context.MessageFormatter);

            OnAfterSerialization(context);
        }
        /// <inheritdoc />
        protected override void HandleRequest(XRoadContext context)
        {
            if (context.HttpContext.Request.InputStream.Length == 0)
            {
                throw new InvalidQueryException("Empty request content");
            }

            context.Request.LoadRequest(context.HttpContext, context.MessageFormatter, StoragePath.GetValueOrDefault(Path.GetTempPath()), serviceManagers);
            if (context.Request.ServiceManager == null && context.Request.MetaServiceMap == null)
            {
                var supportedProtocolsString = string.Join(", ", serviceManagers.Select(x => $@"""{x.Name}"""));
                throw new InvalidQueryException($"Could not detect X-Road message protocol version from request message. Adapter supports following protocol versions: {supportedProtocolsString}.");
            }

            context.Response.Copy(context.Request);
            context.ServiceMap = context.Request.MetaServiceMap;

            OnRequestLoaded(context);
            InvokeServiceMethod(context);
            SerializeXRoadResponse(context);
        }
 /// <summary>
 /// Intercept X-Road service request handling after serialization of the response message.
 /// </summary>
 protected virtual void OnAfterSerialization(XRoadContext context)
 {
 }
 /// <summary>
 /// Intercept X-Road service request handling before serialization of the response message.
 /// </summary>
 protected virtual void OnBeforeSerialization(XRoadContext context)
 {
 }
 /// <summary>
 /// Customize XML reader settings before deserialization of the X-Road message.
 /// </summary>
 protected virtual void OnBeforeDeserialization(XRoadContext context, BeforeDeserializationEventArgs args)
 {
 }
 /// <summary>
 /// Handle exception that occurred on service method invokation.
 /// </summary>
 protected virtual void OnInvocationError(XRoadContext context)
 {
 }
 /// <summary>
 /// Intercept X-Road service request after request message is loaded.
 /// </summary>
 protected virtual void OnRequestLoaded(XRoadContext context)
 {
 }
 /// <summary>
 /// Get main service object which implements the functionality of
 /// the operation.
 /// </summary>
 protected abstract object GetServiceObject(XRoadContext context);
 /// <summary>
 /// Handle X-Road message protocol meta-service request.
 /// </summary>
 protected abstract object InvokeMetaService(XRoadContext context);
 /// <summary>
 /// Handles all exceptions as technical SOAP faults.
 /// </summary>
 protected virtual void OnExceptionOccurred(XRoadContext context, Exception exception, IFault fault)
 {
     using (var writer = new XmlTextWriter(context.HttpContext.Response.OutputStream, XRoadEncoding.Utf8))
         context.MessageFormatter.WriteSoapFault(writer, fault);
 }
 /// <summary>
 /// Handle current X-Road operation.
 /// </summary>
 protected abstract void HandleRequest(XRoadContext context);