如何捕获 WCF 中的所有异常但包括自定义数据?
How to catch all exceptions in WCF but include custom data?
我正在处理一个使用多个 WCF 调用来执行过程的项目。第一个调用 returns 一个唯一的 ID (Guid),以下所有调用都必须提供该 ID。服务器端,每个调用都与该唯一 ID 一起记录,以便可以观察单个过程的过程 (假设客户端可以同时开始其中的几个过程,并且它们是线程安全的).
客户端示例如下所示:
string clientName = GetClientName();
Guid uniqueId = wcfClient.Begin(clientName);
object data = wcfClient.GetData(clientName, uniqueId);
object processedData = ProcessDataLocally(data);
bool success = wcfClient.confirmDataValidity(clientName, uniqueId, processedData);
// ...
wcfClient.End(clientName, uniqueId);
如果服务器端出现问题,我也希望使用为出错的调用提供的 uniqueId 将其记录下来。为此,我使服务的所有方法都使用如下函数:
private T DoProcess<T>(Guid uniqueId, Func<T> process)
{
try
{
return process();
}
catch(Exception ex)
{
Log(ex, uniqueId);
throw; // or throw the same thing every time, if the client
// shouldn't know the details
}
}
public object GetData(string clientName, Guid uniqueId)
{
return DoProcess(uniqueId, () =>
{
object data;
// Generate data
return data;
});
}
但是,这样做似乎并不能捕获所有可能的错误(例如,如果连接超时)。
我阅读了有关实现 IErrorHandler
接口并将其附加到服务的信息。虽然这似乎捕获了所有错误,但似乎没有办法将信息传递给它,除了异常,例如 uniqueId。因此无法记录 ID。
是否可以捕获所有异常并包含已传递给抛出异常的方法的数据?
连接超时等异常不会到达服务,因此无法在服务端捕获。
话虽如此,您可以使用 IExtension 向当前的 OperationContext 添加额外的信息。基本模式是这样的:
public class OperationContextExtension : IExtension<OperationContext>
{
private readonly Dictionary<string, object> extraInfo;
public OperationContextExtension ()
{
extraInfo = new Dictionary<string, object>();
}
public static OperationContextExtension Current
{
get
{
OperationContextExtension c = OperationContext.Current.Extensions.Find<OperationContextExtension>();
if (c == null)
{
c = new OperationContextExtension ();
OperationContext.Current.Extensions.Add(c);
}
return c;
}
}
public Dictionary<string, object> Extras
{
get { return extraInfo; }
}
public void Attach(OperationContext owner) { }
public void Detach(OperationContext owner) { }
}
然后在 IErrorHandler 实现中使用 class :
class FaultErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
return false;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
Guid ID = OperationContextExtension.Current.Extras["uniqueId"] as Guid;
LogIt(error.ToString() + ID);
}
}
然后在GetData
public object GetData(string clientName, Guid uniqueId)
{
OperationContextExtension.Current.Extras["uniqueId"] = uniqueId;
return DoProcess(uniqueId, () =>
{
object data;
// Generate data
return data;
});
}
我正在处理一个使用多个 WCF 调用来执行过程的项目。第一个调用 returns 一个唯一的 ID (Guid),以下所有调用都必须提供该 ID。服务器端,每个调用都与该唯一 ID 一起记录,以便可以观察单个过程的过程 (假设客户端可以同时开始其中的几个过程,并且它们是线程安全的).
客户端示例如下所示:
string clientName = GetClientName();
Guid uniqueId = wcfClient.Begin(clientName);
object data = wcfClient.GetData(clientName, uniqueId);
object processedData = ProcessDataLocally(data);
bool success = wcfClient.confirmDataValidity(clientName, uniqueId, processedData);
// ...
wcfClient.End(clientName, uniqueId);
如果服务器端出现问题,我也希望使用为出错的调用提供的 uniqueId 将其记录下来。为此,我使服务的所有方法都使用如下函数:
private T DoProcess<T>(Guid uniqueId, Func<T> process)
{
try
{
return process();
}
catch(Exception ex)
{
Log(ex, uniqueId);
throw; // or throw the same thing every time, if the client
// shouldn't know the details
}
}
public object GetData(string clientName, Guid uniqueId)
{
return DoProcess(uniqueId, () =>
{
object data;
// Generate data
return data;
});
}
但是,这样做似乎并不能捕获所有可能的错误(例如,如果连接超时)。
我阅读了有关实现 IErrorHandler
接口并将其附加到服务的信息。虽然这似乎捕获了所有错误,但似乎没有办法将信息传递给它,除了异常,例如 uniqueId。因此无法记录 ID。
是否可以捕获所有异常并包含已传递给抛出异常的方法的数据?
连接超时等异常不会到达服务,因此无法在服务端捕获。
话虽如此,您可以使用 IExtension 向当前的 OperationContext 添加额外的信息。基本模式是这样的:
public class OperationContextExtension : IExtension<OperationContext>
{
private readonly Dictionary<string, object> extraInfo;
public OperationContextExtension ()
{
extraInfo = new Dictionary<string, object>();
}
public static OperationContextExtension Current
{
get
{
OperationContextExtension c = OperationContext.Current.Extensions.Find<OperationContextExtension>();
if (c == null)
{
c = new OperationContextExtension ();
OperationContext.Current.Extensions.Add(c);
}
return c;
}
}
public Dictionary<string, object> Extras
{
get { return extraInfo; }
}
public void Attach(OperationContext owner) { }
public void Detach(OperationContext owner) { }
}
然后在 IErrorHandler 实现中使用 class :
class FaultErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
return false;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
Guid ID = OperationContextExtension.Current.Extras["uniqueId"] as Guid;
LogIt(error.ToString() + ID);
}
}
然后在GetData
public object GetData(string clientName, Guid uniqueId)
{
OperationContextExtension.Current.Extras["uniqueId"] = uniqueId;
return DoProcess(uniqueId, () =>
{
object data;
// Generate data
return data;
});
}