在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;
...
}
}
请帮助我,该怎么做...