WCF下抛出FaultException异常让客户的捕获的问题?
在做一个项目,我负责用Nhibernate写DAL层服务并用WCF+IIS方式对外发布
对于异常的处理WEB端同事说我这边只有抛出FaultException他们才能捕获到。
所以我现在的代码结构改为如下方式:
using (ISession session = SessionFactory.OpenSession())
{
using (ITransaction tx = session.BeginTransaction())
{
try
{
...//代码块
tx.Commit();
}
Catch(FaultException<ErrorInfo> fex) //ErrorInfo是一个自定义的错误类
{
tx.Rollback();
throw fex;
}
Catch(Exception ex)
{
tx.Rollback();
throw ex;
}
}
}
现在我有几个想不通的问题:
1.我有两个异常Catch,是不是只有我在TRY代码块里面主动抛出FaultException<ErrorInfo>,才能执行Catch(FaultException<ErrorInfo>
fex)的代码?否则任何异常都是到Catch(Exception ex)里面去执行?
2.CATCH的作用是为了在异常发生后回滚此次事务操作,可以看到我写了一句tx.Rollback();,但之后我又为了让客户端知道方法执行失败,
所以又抛出了异常,因为网上很多关于异常处理的都建议不要在异常里面再抛出异常,那有没有比这更好的代码写法?
3.既然是客户端只接收FaultException异常,那如果执行到Catch(Exception ex),是不是我需要在里面抛一个FaultException<ErrorInfo>
才行啊?
在数据访问层 抛出的异常不应该用 FaultException 来封装、只有需要把异常消息传递给 WCF 客户端才需要把 异常封装成FaultException。也就是说,你需要先在服务层捕获所有的异常,并将需要传递给客户端的异常封装成 FaultException ,抛出;然后在客户端捕获异常。
为什么需要使用 FaultException 来封装异常给客户端呢、是因为 只有继承自 FaultExeption 的异常才能够传送给客户端、而其他 Exception 异常都会导致 WCF 通道因发生异常而无法传递任何消息。
你一下提了好多问题,比如“只有抛出FaultException他们才能捕获到”,这些都是错误的认识。
还有wcf的异常处理,多种多样,我只能简单的告诉你最佳实践的做法:
你服务端的代码,无法 catch FaultException<ErrorInfo>,这是客户端 catch 的东西。
你的服务方法都写成下面的模式:
try
{
tx.Commit();
}
catch
{
tx.Rollback();
throw;
}
然后写一个这样的扩展:
public class CustomerErrorHandler : IErrorHandler
{
#region IErrorHandler 成员
public bool HandleError(Exception error)
{
// 在这里处理捕获到的异常,根据异常的类型,确定是以FaultException<Exception> 形式抛给客户端,还是自定异常信息内容后再以FaultException的形式抛给客户端(基于安全考虑,该方法用于屏蔽异常的关键信息)。
return false;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
}
#endregion
}
把异常定义一个序列化的类,然后传输给client,处理一下就可以了
WCF的方法
public void DoNothing()
{
throw new FaultException<DataContracts.SomeError>(new DataContracts.SomeError()
{
Message = "我是自定义异常信息"
});
}
客户端方法
try
{
client.DoNothing();
}
catch (FaultException<DataContracts.SomeError> ex)
{
Console.WriteLine("捕获到了自定义异常: {0}",ex.Detail.Message );
}
catch (FaultException ex)
{
Console.WriteLine("捕获到了自定义异常: {0}", ex.CreateMessageFault().GetDetail<DataContracts.SomeError>().Message );
}
catch
{
Console.WriteLine("捕获到了非自定义异常");
}