如何在WCF中捕获自定义FaultException

本文关键字:自定义 FaultException WCF | 更新日期: 2023-09-27 18:05:57

我正在测试WCF是否有可能实现一个API,用于远程控制运行我们的控制器软件的设备(c#/。. Net 4.6.1)

我目前正试图找出如何抛出和捕获FaultException从我的服务,并从。net客户端捕获它。

我遇到的问题是,当运行代码时(在VS 2015调试模式下),异常没有被客户端捕获,但VS最终向我展示了VS内部的异常,在服务的代码位置(Service.cs),在那里它被抛出。异常消息为:

System.ServiceModel类型的异常。故障异常' 1'发生在WcfService.dll中,但未在用户代码中处理

附加信息:参数值不是1

其中The argument value was not 1是我提供的自定义消息。下面是我代码的相关部分。我希望有人能指出我做错了什么:

IService.cs:

[ServiceContract(CallbackContract = typeof(IMyEvents))]
public interface IService
{
    [OperationContract]
    [FaultContract(typeof(InvalidValueFault))]
    string ThrowsFaultIfArgumentValueIsNotOne(int value);
    ...
}
[DataContract]
public class InvalidValueFault
{
    private string _message;
    public InvalidValueFault(string message)
    {
        _message = message;
    }
    [DataMember]
    public string Message { get { return _message; } set { _message = value; } }
}   

Service.cs:[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.]可重入的,InstanceContextMode = InstanceContextMode. single)]公共类Service: IService{private string defaultString;

    public Service(string ctorTestValue)
    {
        this.defaultString = ctorTestValue;
    }
    public string ThrowsFaultIfArgumentValueIsNotOne(int value)
    {
        if (value == 1)
            return string.Format("Passed value was correct: {0}", value);
        // this is where the box with the exception is shown inside Visual Studio
        throw new FaultException<InvalidValueFault>(new InvalidValueFault("The argument value was not 1"), new FaultReason("The argument value was not 1"));
    }
    ...
}

Server.cs:公共类服务器{private ServiceHost svh;private Service Service;

    public Server()
    {
        service = new Service("A fixed ctor test value that the service should return.");
        svh = new ServiceHost(service);
    }
    public void Open(string ipAdress, string port)
    {
        svh.AddServiceEndpoint(
        typeof(IService),
        new NetTcpBinding(),
        "net.tcp://"+ ipAdress + ":" + port);
        svh.Open();
    }
    public void Close()
    {
        svh.Close();
    }
}

Client.cs:

public class Client : IMyEvents
{
    ChannelFactory<IService> scf;
    IService s;
    public void OpenConnection(string ipAddress, string port)
    {
        var binding = new NetTcpBinding();
        scf = new DuplexChannelFactory<IService>(
        new InstanceContext(this),
        binding,
        "net.tcp://" + ipAddress + ":" + port);
        s = scf.CreateChannel();
    }
    public void CloseConnection()
    {
        scf.Close();
    }
    public string ThrowsFaultIfArgumentValueIsNotOne(int value)
    {
        try
        {
            return s.ThrowsFaultIfArgumentValueIsNotOne(value);
        }
        catch (System.ServiceModel.FaultException<InvalidValueFault> fault)
        {
            Console.WriteLine("Exception thrown by ThrowsFaultIfArgumentValueIsNotOne(2):");
            Console.WriteLine("Exception message: " + fault.Message);
            //throw;
            return "Exception happend.";
        }
    }
    ...
}

Program.cs(使用服务器和客户端的测试程序):

class Program
{
    static void Main(string[] args)
    {
        // start server
        var server = new Server();
        server.Open("localhost", "6700");
        Console.WriteLine("Server started.");
        var client = new Client();
        client.OpenConnection("localhost", "6700");
        Console.ReadLine();
        Console.WriteLine("Result for client.ThrowsFaultIfArgumentValueIsNotOne(1): {0}", client.ThrowsFaultIfArgumentValueIsNotOne(1));
        Console.ReadLine();
        Console.WriteLine("Result for client.ThrowsFaultIfArgumentValueIsNotOne(2): {0}", client.ThrowsFaultIfArgumentValueIsNotOne(2));
        Console.ReadLine();
        client.CloseConnection();
        Thread.Sleep(1000);
        server.Close();
    }
}

如何在WCF中捕获自定义FaultException

如果您使用vs tools从wsdl生成SOAP代码,那么这里抛出的FaultException是通用的FaultException -这意味着它是FaultException<fault_contract>。您可以通过检查服务引用代码和检查[System.ServiceModel.FaultContractAttribute()]属性来确定泛型异常。这个属性的Type参数是你的泛型类型。

如果它看起来像这样

[System.ServiceModel.FaultContractAttribute(typeof(MyFaultContract)]
[System.ServiceModel.OperationContractAttribute(Action = "SoapAction", ReplyAction = "*")]
SoapResponse SoapAction(SoapRequest request);

那么你的catch子句应该像这样

try {
    soapClient.SoapAction(new SoapRequest());
}
catch (FaultException<MyFaultContract> e) {
}

我最近遇到了这个问题(如果我理解正确的话)

1) VS -> DEBUG -> Options and Settings -> Debugging -> General

There UNTICK 'Break when exceptions across AppDomain…'

2) DEBUG -> Exceptions并取消选择公共语言运行时(抛出和用户未处理)的异常,然后再试一次。如果这样可以解决问题,您可以查找想要自定义的异常,或者在跨AppDomain测试异常时这样做。

好的。我侥幸找到了问题的答案。错误是由于在Visual Studio的调试模式下运行我的代码,其中VS捕获异常抛出的那一刻。为了使其正常工作,您需要禁用一些设置。要做到这一点,请进入Tools->Option->Debugging->General并删除复选标记:

  • Enable the exception assistant
  • Enable just my code

我在这里找到了这个解决方案