如何在WCF中捕获自定义FaultException

时间:2016-09-07 11:43:19

标签: c# .net wcf

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

我目前正在尝试弄清楚如何从我的服务中抛出并捕获FaultException并从.Net客户端捕获它。

我遇到的问题是,在运行代码时(在VS 2015上的调试模式下),客户端没有捕获到异常,但VS最终在VS的代码位置显示异常。服务(Service.cs),它被抛出的地方。异常消息是:

  

WcfService.dll中出现'System.ServiceModel.FaultException`1'类型的异常,但未在用户代码中处理

     

附加信息:参数值不是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.Reentrant,                      InstanceContextMode = InstanceContextMode.Single)]     公共类服务:IService     {         私有字符串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:     公共类服务器     {         私人ServiceHost svh;         私人服务;

    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();
    }
}

3 个答案:

答案 0 :(得分:0)

如果使用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 :(得分:0)

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

1)VS - &gt; DEBUG - &gt;选项和设置 - &gt;调试 - &gt;一般

当异常跨越AppDomain时,UNTICK&#39;中断...&#39;

2)DEBUG - &gt;异常并取消选择公共语言运行库的异常(Thrown和user-unhandled)并再次尝试。如果这样可以解决问题,您可以在AppDomain上测试异常时查找要自定义的异常,或者只执行此操作。

答案 2 :(得分:0)

确定。幸运的是,我找到了问题的答案。该错误是由于在Visual Studio中以调试模式运行我的代码,其中VS在抛出异常时捕获异常。为了使其正常工作,您需要禁用某些设置。要执行此操作,请转到Tools->Option->Debugging->General并删除复选标记:

  • Enable the exception assistant
  • Enable just my code

我找到了这个解决方案here