【问题标题】:WCF Service throw custom exception to clientWCF 服务向客户端抛出自定义异常
【发布时间】:2023-03-19 17:40:02
【问题描述】:

我正在尝试从 WCF 服务向客户端应用程序抛出自定义异常。我将尽可能多地描述与此相关的代码。

例外:

using System.Runtime.Serialization;

namespace App.Exceptions
{
    /// <summary>
    /// General App exception
    /// </summary>
    [DataContract]
    public class AppException : System.Exception
    {
        private string strMessage = "An unknown exception occurred";

        /// <summary>
        /// Creates a new instance of a App Exception
        /// </summary>
        public AppException()
        { }

        /// <summary>
        /// Creates a new instance of a App Exception
        /// </summary>
        /// <param name="Message">Message to send as exception</param>
        public AppException(string Message)
        { strMessage = Message; }

        public override string Message
        { get { return strMessage; } }
    }
}

服务代码:

(...)
using App.Exceptions;

namespace App.Services
{
    public class Service1 : IService1
    {
        public Service1 () 
        { }

        public void TestFunction() 
        {
            throw new AppException();
        }
    }
}

服务接口:

(...)

namespace App.Services.Interfaces
{
    [ServiceContract]
    public interface IService1
    {   
        [OperationContract]
        void TestFunction();
    }
}

客户:

(...)
using App.Exceptions;
(...)

try 
{
    service.TestFunction();
}
catch (AppException ex) 
{

}

一切正常,在服务上调用函数并抛出异常。客户端和服务器上的引用完全相同。我已经检查过了,AppException 正在同一个名称空间中被引用,所以应该没问题。

我已经尝试在服务 app.config 上设置 &lt;serviceDebug includeExceptionDetailInFaults="True" /&gt; 并将其设置为 False 只是为了查看我是否得到不同的异常,实际上它是不同的,所以我不太明白为什么设置断点AppException 永远不会被击中。

编辑:

服务配置:

  <service name="App.Services.Service1">
    <endpoint address="" binding="basicHttpBinding" contract="App.Services.Interfaces.IService1">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:8733/Design_Time_Addresses/App.Services/Service1/" />
      </baseAddresses>
    </host>
  </service>

客户端配置:

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_IService1" />
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://localhost:8733/Design_Time_Addresses/App.Services/Service1/"
            binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1"
            contract="Services.IService1" name="BasicHttpBinding_IService1" />
    </client>
</system.serviceModel>

【问题讨论】:

  • 我也试过了。 AppException Catch 永远不会被命中。
  • 您使用的是 catch (AppException ex) 还是 catch (FaultException ex)?前者不行,后者应该。
  • 我刚刚重试了,在完全按照您提到的另一个问题完成后,我在更新服务引用时遇到了问题,错误 400 元数据包含无法解决的引用。我还注意到,当调试抛出错误异常时,它显示“System.ServiceModel.FaultException`1”这是预期的行为吗?我不这么认为。
  • @rgomez 为什么不使用 Exception ex 捕获并检查?

标签: c# wcf


【解决方案1】:

由于安全和互操作性的原因,您不能从服务器向客户端抛出任何未处理的异常或 .net 或任何类似的异常(如果客户端想知道异常),默认情况下,这些异常不会从wcf 服务。

WCF 不是传播异常,而是将它们序列化为 SOAP 错误并将 SOAP 错误发送给客户端。因此您需要将此自定义异常包含在 SOAP 错误中。

首先让 servicecontract 知道哪个操作可以抛出哪个 SOAP 错误。

namespace App.Services.Interfaces
{
    [ServiceContract]
    public interface IService1
    {   
        [FaultContract(typeOf(AppException))]
        [OperationContract]
        void TestFunction();
    }
}


using System.ServiceModel;
public class Service1 : IService1
    {
        public Service1 () 
        { }

        public void TestFunction() 
        {
            try
            {
             service.TestFunction();
            }
            catch(Exception ex)
             {
               AppException app=new AppException();
               app.strMessage =ex.Message;
               throw new FaultExcpetion<AppException>(app);
             }
        }
    }

另外,您可以有故障详情和故障错误。在客户端捕获上述异常。

//client side

     try
                {
                  //call wcf service contract.
                }
                catch (FaultException<ServiceReference.AppException> ex)
                {

                   label.Text=ex.Detail.strMessage ;
                }

另一种方法是使用自定义 WCF IErrorHandler 实现。请参阅此https://stackoverflow.com/a/8764782/6086968 以了解处理异常的集中方式。

Edit1:app.config 需要正确配置元数据。

    <service name="App.Services.Service1" behaviorConfiguration="mexendpoint">
        <endpoint address="" binding="basicHttpBinding" contract="App.Services.Interfaces.IService1">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8733/Design_Time_Addresses/App.Services/Service1/" />
          </baseAddresses>
        </host>
      </service>
<behaviors>
  <serviceBehaviors>  
    <behavior name="mexendpoint">
      <serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="true"/>
    </behavior>
     </serviceBehaviors>
</behaviors>
</system.serviceModel>

【讨论】:

  • 我将[FaultContract(typeof(AppException))] 添加到服务接口并构建该项目后,我无法更新客户端项目上的服务引用。我已尝试将服务项目添加为客户端的参考,但同样的错误 -> 错误 400 元数据包含无法解析的参考
  • 您是否能够构建服务器端代码?您可以将您的 app.config xml 发布到您为 wcf 服务定义绑定的位置吗?同时发布完整的错误消息。
  • 错误是。 Metadata contains a reference that cannot be resolved: 'address for service'. Content Type application/soap+xml; charset=utf-8 was not supported by service. The client and service bindings may be mismatched. The remote server returned an error (415) Cannot process the message because the content type 'application/soap+xml, charset=utf-8' was not the expected type 'text/xml; chartset-utf8'.. 我会更新问题,包括配置。
  • 我试过了。该服务会构建,但更新服务引用现在返回一个拒绝的连接。 There was no endpoint listening on address '&lt;address&gt;' that could accept the message. This is often caused by an incorrect address or SOAP action (..)
  • 那么在这些异常更改之前,您是否能够成功更新添加服务引用?也添加Service1实现代码。
猜你喜欢
  • 2010-11-25
  • 2021-03-19
  • 1970-01-01
  • 2011-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-11
  • 1970-01-01
相关资源
最近更新 更多