序列化一个通用类型的 FaultException
Serialize a FaultException of Generic Type
我们目前有一种在测试页面中调用网络服务的机制。但是,我正在尝试查看 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.
序列化时,需要将已知类型提供给 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();
}
}
我们目前有一种在测试页面中调用网络服务的机制。但是,我正在尝试查看 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.
序列化时,需要将已知类型提供给 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();
}
}