Как изменить полный ответ (из строки) перед ответом в webService (asmx) - PullRequest
0 голосов
/ 26 апреля 2019

Мне нужно заменить полный ответ перед ответом в WebService.

У меня есть webService, который принимает и возвращает пользовательский класс.Когда я получаю запрос, мне нужно создать ответ, подписать его цифровой подписью и отправить подписанный ответ.Все сообщение подписано на другом сервисе и возвращается в виде строки.Теперь мне нужно заменить стандартный ответ подписанным ответом перед ответом.

Я создал инспектор сообщений на основе SoapExtensionAttribute, который перехватывает сообщение перед ответным ответом.Но я не знаю, как заменить стандартный ответ другим.

WebService:

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class ActualizationSub : System.Web.Services.WebService, IUniversalServiceSyncServiceSoapBinding
{
    [WebMethod]
    [MessageInspector.MessageInspectorSoapExtension(ServiceName = "PERSON_SYNCHRONIZATION_AUTO", TracingPath = @"~/MessageInspected")]
    SyncSendMessageResponse IUniversalServiceSyncServiceSoapBinding.SendMessage(SyncSendMessageRequest request)
    {
        //do somethings

        //create and send response
        SyncSendMessageResponse simpleResponse = CreateSyncSendMessageResponse();

        //sign response
        string signResponse = SignResponse(simpleResponse);

        return simpleResponse;
    }
}

Инспектор Mesaage:

[AttributeUsage(AttributeTargets.Method)]
public class MessageInspectorSoapExtensionAttribute : SoapExtensionAttribute
{
    public string ServiceName { get; set; }
    public string TracingPath { get; set; }

    private int priority = 1;
    public override Type ExtensionType => typeof (MessageInspectorSoapExtension);

    public override int Priority { get => priority; set => priority = value; }
}
public class MessageInspectorSoapExtension : SoapExtension
{
    Stream oldStream;
    Stream newStream;

    public string ServiceName { get; set; }
    public string TracingPath { get; set; }

    public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
    {
        if (attribute is MessageInspectorSoapExtensionAttribute)
        {
            var miAttr = attribute as MessageInspectorSoapExtensionAttribute;

            return new Model.MessageInspectorSoapProperties
            {
                ServiceName = miAttr.ServiceName,
                TracingPath = miAttr.TracingPath
            };
        }

        return null;
    }

    public override object GetInitializer(Type serviceType)
    {
        return null;
    }

    public override void Initialize(object initializer)
    {
        if (initializer is Model.MessageInspectorSoapProperties)
        {
            var miInit = initializer as Model.MessageInspectorSoapProperties;
            ServiceName = miInit.ServiceName;
            TracingPath = Helper.PathBuilder.Build(miInit.TracingPath);
        }
    }

    public override Stream ChainStream(Stream stream)
    {
        oldStream = stream;
        newStream = new MemoryStream();
        return newStream;
    }

    public override void ProcessMessage(SoapMessage message)
    {
        switch (message.Stage)
        {

            case SoapMessageStage.BeforeSerialize:
                //SetStream(message);

                break;

            case SoapMessageStage.AfterSerialize:
                //WriteOutput(message);
                Helper.TracingMessage.TraceSoap(message, ServiceName, TracingPath, Enums.MessageType.REPLY, ref newStream);
                //Log(message, "AfterSerialize");
                CopyStream(newStream, oldStream);
                newStream.Position = 0;
                break;

            case SoapMessageStage.BeforeDeserialize:
                //WriteInput(message);
                CopyStream(oldStream, newStream);
                Helper.TracingMessage.TraceSoap(message, ServiceName, TracingPath, Enums.MessageType.REQUEST, ref newStream);
                //Log(message, "BeforeDeserialize");
                break;

            case SoapMessageStage.AfterDeserialize:
                break;

            default:
                throw new Exception("invalid stage");
        }
    }

    void ReturnStream()
    {
        CopyAndReverse(newStream, oldStream);
    }

    void ReceiveStream()
    {
        CopyAndReverse(newStream, oldStream);
    }

    public void ReverseIncomingStream()
    {
        ReverseStream(newStream);
    }

    public void ReverseOutgoingStream()
    {
        ReverseStream(newStream);
    }

    public void ReverseStream(Stream stream)
    {
        TextReader tr = new StreamReader(stream);
        string str = tr.ReadToEnd();
        char[] data = str.ToCharArray();
        Array.Reverse(data);
        string strReversed = new string(data);

        TextWriter tw = new StreamWriter(stream);
        stream.Position = 0;
        tw.Write(strReversed);
        tw.Flush();
    }
    void CopyAndReverse(Stream from, Stream to)
    {
        TextReader tr = new StreamReader(from);
        TextWriter tw = new StreamWriter(to);

        string str = tr.ReadToEnd();
        char[] data = str.ToCharArray();
        Array.Reverse(data);
        string strReversed = new string(data);
        tw.Write(strReversed);
        tw.Flush();
    }

    private void CopyStream(Stream fromStream, Stream toStream)
    {
        try
        {
            StreamReader sr = new StreamReader(fromStream);
            StreamWriter sw = new StreamWriter(toStream);
            sw.WriteLine(sr.ReadToEnd());
            sw.Flush();
        }
        catch (Exception ex)
        {
            string message = String.Format("CopyStream failed because: {0}", ex.Message);
            //log.Error(message, ex);
        }
    }
}

Я думаю, чтозамена сообщения должна быть сделана в ProcessMessage :

public override void ProcessMessage(SoapMessage message)
    {
        switch (message.Stage)
        {

            ...

            case SoapMessageStage.AfterSerialize:
            //WriteOutput(message);
            Helper.TracingMessage.TraceSoap(message, ServiceName, TracingPath, Enums.MessageType.REPLY, ref newStream);
            //Log(message, "AfterSerialize");
            CopyStream(newStream, oldStream);
            newStream.Position = 0;
            break;

            ...
        }
    }

Пожалуйста, помогите мне, как это сделать ...

...