C# 如何处理SoapExtension中的超时异常
我有一个分机。它记录我所有的Web服务请求和响应。我认为在这个项目中有超过一千个Web服务调用。我的问题是,如果我的webservice调用以超时或HttpException(如403404)结束,我就无法记录请求。我也需要记录这些异常 这是我的分机C# 如何处理SoapExtension中的超时异常,c#,exception,soap,asmx,soap-extension,C#,Exception,Soap,Asmx,Soap Extension,我有一个分机。它记录我所有的Web服务请求和响应。我认为在这个项目中有超过一千个Web服务调用。我的问题是,如果我的webservice调用以超时或HttpException(如403404)结束,我就无法记录请求。我也需要记录这些异常 这是我的分机 public class SoapLogger : SoapExtension { Stream orgStream; Stream newStream; LogItem logItem; // When the
public class SoapLogger : SoapExtension
{
Stream orgStream;
Stream newStream;
LogItem logItem;
// When the SOAP extension is accessed for the first time, the XML Web
// service method it is applied to is accessed to store the file
// name passed in, using the corresponding SoapExtensionAttribute.
public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
{
return 0;
}
// The SOAP extension was configured to run using a configuration file
// instead of an attribute applied to a specific XML Web service
// method.
public override object GetInitializer(Type WebServiceType)
{
return 0;
}
// Receive the file name stored by GetInitializer and store it in a
// member variable for this specific instance.
public override void Initialize(object initializer)
{
logItem = new LogItem();
}
// Save the Stream representing the SOAP request or SOAP response into
// a local memory buffer.
public override Stream ChainStream(Stream stream)
{
orgStream = stream;
newStream = new MemoryStream();
return newStream;
}
// If the SoapMessageStage is such that the SoapRequest or
// SoapResponse is still in the SOAP format to be sent or received,
// save it out to a file.
public override void ProcessMessage(SoapMessage message)
{
switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
WriteOutput();
break;
case SoapMessageStage.BeforeDeserialize:
WriteInput(message);
break;
case SoapMessageStage.AfterDeserialize:
CheckException(message);
break;
default:
throw new Exception("invalid soap stage");
}
}
public void CheckException(SoapMessage message)
{
logItem.WebClassName = message.MethodInfo.DeclaringType.FullName;
logItem.WebMethodName = message.MethodInfo.Name;
MethodBase method = FindMethod(logItem.WebMethodName);
logItem.MethodName = method != null ? method.Name : "";
logItem.ClassName = method != null ? method.DeclaringType.Name : "";
logItem.Exception = message.Exception != null ? message.Exception.Message : "";
LogToDB(logItem);
}
MethodBase FindMethod(string webMethodName)
{
try
{
StackFrame[] stackFrames = new StackTrace().GetFrames();
int i;
for (i = 0; i < stackFrames.Length; i++)
{
if (stackFrames[i].GetMethod().Name == webMethodName) break;
}
return i < stackFrames.Length - 1 ? stackFrames[i + 1].GetMethod() : null;
}
catch
{
return null;
}
}
void LogToDB(LogItem logItem)
{
// I am logging logItem to db
}
public void WriteOutput()
{
newStream.Position = 0;
logItem.Request = CopyString(newStream);
logItem.StartTime = DateTime.Now;
newStream.Position = 0;
Copy(newStream, orgStream);
newStream.Position = 0;
}
public void WriteInput(SoapMessage message)
{
Copy(orgStream, newStream);
newStream.Position = 0;
logItem.Response = CopyString(newStream);
logItem.EndTime = DateTime.Now;
newStream.Position = 0;
}
void Copy(Stream from, Stream to)
{
TextReader reader = new StreamReader(from);
TextWriter writer = new StreamWriter(to);
writer.WriteLine(reader.ReadToEnd());
writer.Flush();
}
string CopyString(Stream from)
{
TextReader reader = new StreamReader(from);
return reader.ReadToEnd();
}
}
public类SoapLogger:SoapExtension
{
溪流或溪流;
流新闻流;
LogItem LogItem;
//当第一次访问SOAP扩展时,XML Web
//访问应用它的服务方法以存储文件
//使用相应的SoapExtensionAttribute传入的名称。
公共重写对象GetInitializer(LogicalMethodInfo methodInfo,SoapExtensionAttribute属性)
{
返回0;
}
//SOAP扩展已配置为使用配置文件运行
//而不是应用于特定XML Web服务的属性
//方法。
公共重写对象GetInitializer(类型WebServiceType)
{
返回0;
}
//接收GetInitializer存储的文件名并将其存储在
//此特定实例的成员变量。
公共重写无效初始化(对象初始值设定项)
{
logItem=新logItem();
}
//将表示SOAP请求或SOAP响应的流保存到
//本地内存缓冲区。
公共覆盖流链流(Stream-Stream)
{
orgStream=流;
newStream=newmemoryStream();
返回新闻流;
}
//如果SoapMessageStage使SoapRequest或
//SoapResponse仍然是要发送或接收的SOAP格式,
//将其保存到文件中。
公共覆盖无效ProcessMessage(SoapMessage消息)
{
开关(消息阶段)
{
案例SoapMessageStage.BeforeSerialize:
打破
案例SoapMessageStage.AfterSerialize:
WriteOutput();
打破
案例SoapMessageStage.BeforeDeserialize:
写入输入(消息);
打破
案例SoapMessageStage.After反序列化:
检查异常(消息);
打破
违约:
抛出新异常(“无效soap阶段”);
}
}
公共无效检查异常(SoapMessage消息)
{
logItem.WebClassName=message.MethodInfo.DeclaringType.FullName;
logItem.WebMethodName=message.MethodInfo.Name;
MethodBase method=FindMethod(logItem.WebMethodName);
logItem.MethodName=method!=null?方法。名称:“”;
logItem.ClassName=method!=null?method.DeclaringType.Name:“”;
logItem.Exception=message.Exception!=null?message.Exception.message:;
LogToDB(logItem);
}
MethodBase FindMethod(字符串webMethodName)
{
尝试
{
StackFrame[]stackFrames=新StackTrace().GetFrames();
int i;
对于(i=0;i
以下文字可能会帮助您解决问题
“SoapExtension解决方案
解决这个问题最常用的方法(我到目前为止已经发现)是编写一个自定义的SoapExtension子类,它在web服务请求和响应的不同阶段为您提供对SoapMessage的底层访问权限。当发生未处理的异常时,SoapException可以在响应SoapMessage中捕获(通过Exception属性)。然后,SoapException的InnerException属性包含实际未处理的异常。此时,您可以在异常出门时记录该异常,这样当您从技术支持部门收到该电子邮件时,您就有事情要做了
但如果您曾经开发过真正面向公众的web服务(就像我们的一样),您很快就会同意,仅仅记录异常是不够的。通常,您希望对发送回调用方的SoapException本身的内容有更多的控制。SoapExtension子类方法使您能够修改SoapException,但级别非常低。具体来说,它已经被反序列化了插入到其代表性的SOAP错误XML中,您必须执行一些奇特的流操作,以将任何自定义内容插入到该错误中(例如:添加细节元素)。在我看来,这是一个黑客攻击,不是一个非常优雅的解决方案。相反,我们应该在引发SoapException之前对其进行更多的控制。理想情况下,如果我们能够自己创建并引发SoapException,我们就可以对产生的SOAP错误的内容进行更多的控制(如错误代码和细节)那我们就不用麻烦了