如何在webService(asmx)中回复之前更改完整响应(来自字符串)

时间:2019-04-26 09:15:16

标签: c# asmx

在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;
    }
}

消息检查器:

[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;

            ...
        }
    }

请帮助我,该怎么做...

0 个答案:

没有答案