代码之家  ›  专栏  ›  技术社区  ›  Andez

序列化泛型类型的FaultException

  •  2
  • Andez  · 技术社区  · 7 年前

    我们目前有一种在测试页面中调用web服务的机制。然而,我试图研究WCF服务和使用FaultException的更好实践。

    因此,当我们的服务引发FaultException时,我想将故障序列化为xml并显示在页面上。

    我已经看过了 XmlSerializer DataContractSerializer 目前为止

    因此,考虑一下代码:

    public SomeResponse DoSomething()
    {
        throw new FaultException<AuthenticationFault>(
                    new AuthenticationFault(), 
                    new FaultReason("BooHoo"), 
                    new FaultCode("1234"));
    }
    

    以及徒劳的连载尝试:

    DataContractSerializer

    public static string Serialize(object obj)
    {
        using (MemoryStream memoryStream = new MemoryStream())
        using (StreamReader reader = new StreamReader(memoryStream))
        {
            DataContractSerializer serializer = new DataContractSerializer(obj.GetType());
            serializer.WriteObject(memoryStream, obj);
            memoryStream.Position = 0;
            return reader.ReadToEnd();
        }
    }
    

    XmlSerializer

    public string Serialize<TObject>(TObject obj)
    {
        if (obj == null)
        {
            return string.Empty;
        }
    
        XmlSerializer serializer = new XmlSerializer(obj.GetType());
        XmlWriterSettings settings = new XmlWriterSettings()
        {
            Encoding = new UnicodeEncoding(false, false), string
            Indent = true,
            OmitXmlDeclaration = true
        };
    
        using (StringWriter textWriter = new StringWriter())
        {
            using (XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings))
            {
                serializer.Serialize(xmlWriter, obj);
            }
            return textWriter.ToString();
        }
    }
    

    测试呼叫和捕捉

    public override string Invoke(string request)
    {
        try
        {
            var service = new AcmeService();
            return Serialize(service.DoSomething());
        }
        catch (FaultException ex)
        {
            return Serialize(ex);
        }
    }
    

    身份验证错误

    [DataContract]
    public class AuthenticationFault
    {
    }
    

    例外情况

    在上述场景中会出现以下例外情况。然而,我很欣赏通用FaultException没有无参数构造函数。运行时必须能够通过连接重新序列化。

    DataContractSerializer

    System.Runtime.Serialization.SerializationException occurred
      HResult=0x8013150C
      Message=Type 'BuyerAcmeApp.Services.Faults.AuthenticationFault' with data contract name 'AuthenticationFault:http://schemas.acme.com/p4/services/2017/11' is not expected. Consider using a DataContractResolver if you are using DataContractSerializer or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to the serializer.
      Source=<Cannot evaluate the exception source>
      StackTrace:
    <Cannot evaluate the exception stack trace>
    

    XmlSerializer

    System.InvalidOperationException occurred
      HResult=0x80131509
      Message=There was an error reflecting type 'System.ServiceModel.FaultException'.
      Source=App_Code.etbsvkgf
      StackTrace:
       at AcmeApp.WebServices.Tests.WebServiceMethodItem`2.Serialize[TObject](TObject obj) in T:\acmejpa\AcmeAppTemplate\dev\solution\AcmeApp.Template\src\AcmeApp\App_Code\WebServices\Tests\WebServiceMethodItemBase.cs:line 70
       at AcmeApp.WebServices.Tests.WebServiceMethodItemWithError`2.Invoke(String request) in T:\acmejpa\AcmeAppTemplate\dev\solution\AcmeApp.Template\src\AcmeApp\App_Code\WebServices\Tests\WebServiceMethodItemBase.cs:line 104
       at AcmeApp.Diagnostics.WebServiceTestPage.CallMethodButton_OnClick(Object sender, EventArgs e) in T:\acmejpa\AcmeAppTemplate\dev\solution\AcmeApp.Template\src\AcmeApp\Diagnostics\WebServiceTestPage.aspx.cs:line 44
    
    Inner Exception 1:
    NotSupportedException: Cannot serialize member System.Exception.Data of type System.Collections.IDictionary, because it implements IDictionary.
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Andez    7 年前

    序列化时,需要将已知类型提供给 DataContractSerializer .

    public static string Serialize(object obj)
    {
        var settings = new XmlWriterSettings { Indent = true };
    
        using (MemoryStream memoryStream = new MemoryStream())
        using (StreamReader reader = new StreamReader(memoryStream))
        {
            DataContractSerializer serializer = new DataContractSerializer(
            obj.GetType(), new Type[]
            {
                typeof(AuthenticationFault)
            });
    
            serializer.WriteObject(memoryStream , obj);
            memoryStream.Position = 0;
            return reader.ReadToEnd();
        }
    }
    
    推荐文章