我在WPF应用程序中托管了一个带有Begin / end方法的异步方法的服务,当我在服务中捕获异常时,我想抛出一个faultException来警告客户端。
但是,当我尝试抛出faultException时,主机应用程序崩溃,突然关机。
在我的存储库中,我捕获了UpdateException,然后,我创建了一个自定义异常,即UniqueKeyException,它抛出给调用者。调用者是一种辅助方法,在Begin方法中调用。
这个辅助方法,捕获UniqyeKeyException并且只执行" throw",这是在我的end方法的try / catch块中捕获的。这里有一些我不明白的东西,为什么最后这个异常会被AgregateException而不是UniqueKeyException阻塞。
好吧,无论如何,在end方法的catch块中,在AgregateException块中,我检查innerException是否为UniqueKeyException,如果为true,我创建一个对象UniqueKeyArgs(一个自定义类,其中包含要发送给它的信息)客户端),创建一个FaultException,最后抛出FaultException。正是在此步骤中,抛出,主机应用程序崩溃。
我认为我已正确配置,因为我的自定义类UniqueKeyArgs被装饰为Datacontract并且其属性为DataMember,在我的主机应用程序的app.config中我配置行为以包含异常详细信息并在合同中我装饰它带有faultContract。
为什么应用程序崩溃?
我的代码如下:
REPOSITORY
public List<Usuers> updateUsers(List<Users> paramUsers)
{
....
catch(UpdateException ex)
{
SqlException innerEx = (SqlException)ex.InnerException;
//Code 2627 is Unique Key exception from SQL Server.
if (innerEx != null && innerEx.Number == 2627)
{
//I create the conditions of searching
ConditionsUsers conditions = new conditions();
conditions.UserName = (Users)ex.StateEntries[0].Entity).userName;
//Search for the existing user
Users myUser = getUser(conditions);
string message = "the user " + conditions.userName + " exists.";
throw new UniqueKeyException(message, myUser);
}
throw;
}
服务实施
//This is my auxiliar method, called in the Begin method.
private submitUpdates()
{
....
catch(UniqueKeyException ex)
{
//The code enter here
throw;
}
}
public IAsyncResult BeginUpdateUsers(List<users> paramUsers, AsyncCallback callback, object state)
{
Task<List<Users>> myTask= Task<List<Users>>.Factory.StartNew(p => sumbmitUpdates(paramUsers), state);
return myTask.ContinueWith(res => callback(myTask));
}
public List<Users> EndUpdateusers(IAsyncResult result)
{
try
{
return ((Task<List<Users>>)result).Result;
}
//Why agregateException and not is catched in the UniqueKeyException ???
catch(AgregateException ex)
{
if (innerExceptions[0] is UsuariosValorUnicoException)
{
//I assign manually the data to debug, to discard other problems.
Users myUser = new Users();
myUser.UserName = "Jhon";
myUser.Password = "pass123";
UniqueKeyArgs myArgs = new UniqueUserArgs("unique key error", myUser);
FaultException<UniqueKeyArgs> myException = new FaultException<UniqueKeyArgs>(myArgs);
//Crash here, in the throw myException
throw myException;
}
}
throw;
}
我的合同
[FaultContract(typeof(UniqueKeyArgs))]
IAsyncResult BeginUpdateUsers(List<Users> paramUser, AsyncCallback callback, object state);
List<Users> EndUpdateUsers(IAsyncResult result);
在End方法中抛出myException时崩溃。
我在这个post中看到解决方案也是在主机应用程序中捕获异常,而不仅仅是在服务对象中。但是,此解决方案使用属于System.Windows.Forms命名空间的Application.ThreadException,并且我使用的是WPF应用程序。
如何从WPF应用程序中托管的服务向客户端发送异常?
感谢。
EDIT1:好吧,我在抛出异常的行中使用了try / catch块,我发现错误是我没有说明原因,所以当我创建FaultException时我会这样做:
FaultException<UniqueKeyArgs> myException = new FaultException<UniqueKeyArgs>(myArgs, new FaultReason("DummyReason");
在这种情况下,异常消息是&#34; DummyReason&#34;,我在FaultReason中设置的消息,所以它什么也没说。 FaultException不是throw,而是将泛型异常抛给客户端。
在这种情况下,主机应用程序不会关闭,但会关闭与客户端的连接,我必须重新连接。
似乎问题是FaultException的创造者,但我没有看到问题。
@Roeal建议也许只能使用带有synch方法的faultException,但是在这个link中我可以看到一个与异步方法一起使用的例子。我见过其他人的例子,并不是唯一的。
感谢。
EDIT2:我解决了我的问题。我的问题是在FaultException中,T是一个具有自我跟踪实体属性的对象,这是一个问题,如果我没有错,我只能使用基本类型作为异常的属性。
然后,在例外情况下,我发现了ISerialize。它需要能够将信息发送到客户端,如果没有这个,客户端会收到异常。具有null属性的详细信息。
答案 0 :(得分:1)
您是否还在服务合同中声明了同步操作?在这种情况下,这可能会有所帮助:
如果在服务运营合同中定义了故障合同,则
FaultContract
属性应仅在同步操作上应用。
- Juval Lowy,“编程WCF服务第3版”(第456页)
答案 1 :(得分:0)
我解决了我的问题。我的问题是在FaultException中,T是一个具有自我跟踪实体属性的对象,这是一个问题,如果我没有错,我只能使用基本类型作为异常的属性。
然后,在例外情况下,我发现了ISerialize。需要能够将信息发送到客户端,如果没有这个,客户端会收到异常。具有null属性的详细信息。