Reputation: 195
I am having some trouble getting back the Detail from a custom Fault Exception within a C# program. When I execute the same call in Postman, I get the response fine, but when trying to do the same thing in c#, the detail all returns null.
My code in c#:
try
{
Client.Open();
var response = Client.findPerson(req);
Client.Close();
}
catch (FaultException<MIAPAPIException> e)
{
ErrorResponse error = new ErrorResponse
{
ErrorCode = e.Detail.ErrorCode,
ErrorActor = e.Detail.ErrorActor,
TimeStamp = e.Detail.ErrorTimestamp,
ErrorDescription = e.Detail.Description
};
}
The MIAPAPIException Class in the wsdl is define like this:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.8.4084.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://generic.url/exceptions")]
public partial class MIAPAPIException : object, System.ComponentModel.INotifyPropertyChanged {
private string errorCodeField;
private string errorActorField;
private string descriptionField;
private string furtherDetailsField;
private string errorTimestampField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true, Order=0)]
public string ErrorCode {
get {
return this.errorCodeField;
}
set {
this.errorCodeField = value;
this.RaisePropertyChanged("ErrorCode");
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true, Order=1)]
public string ErrorActor {
get {
return this.errorActorField;
}
set {
this.errorActorField = value;
this.RaisePropertyChanged("ErrorActor");
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true, Order=2)]
public string Description {
get {
return this.descriptionField;
}
set {
this.descriptionField = value;
this.RaisePropertyChanged("Description");
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true, Order=3)]
public string FurtherDetails {
get {
return this.furtherDetailsField;
}
set {
this.furtherDetailsField = value;
this.RaisePropertyChanged("FurtherDetails");
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true, Order=4)]
public string ErrorTimestamp {
get {
return this.errorTimestampField;
}
set {
this.errorTimestampField = value;
this.RaisePropertyChanged("ErrorTimestamp");
}
}
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName) {
System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
if ((propertyChanged != null)) {
propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
}
Which I can't see any issues with.
The response that I get in postman if i do the same request that i'm doing in c#:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<soapenv:Fault>
<faultcode>soapenv:Server</faultcode>
<faultstring>exceptions.MIAPAPIException</faultstring>
<detail>
<ns10:MIAPAPIException xmlns:ns10="http://generic.url/exceptions">
<ErrorCode>CODE</ErrorCode>
<ErrorActor>MSGValidator.validateSOAPMSG()</ErrorActor>
<Description>DESC</Description>
<FurtherDetails>DETAILS</FurtherDetails>
<ErrorTimestamp>2022-10-11 14:34:16</ErrorTimestamp>
</ns10:MIAPAPIException>
</detail>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
Im not sure what is causing this to be null when my code picks it up in c#. The ordering of the response in postman matches the ordering of the wsdl as well as the namespace matching in both.
I've tried updating the catch to be
catch (FaultException<MIAPAPIException[]> e)
But this doesn't catch the error at all. I thought this may be an array due to the <ns10:MIAPAPIException
namespace at the start of the details but i appear to be incorrect here.
Upvotes: 3
Views: 382
Reputation: 34421
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Globalization;
namespace ConsoleApplication49
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
XmlReader reader = XmlReader.Create(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(Envelope));
Envelope envelope = (Envelope)serializer.Deserialize(reader);
}
}
[XmlRoot(Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
public class Envelope
{
public Body Body { get; set; }
}
public class Body
{
public Fault Fault { get; set; }
}
public class Fault
{
[XmlElement(Namespace = "")]
public string faultcode { get; set; }
[XmlElement(Namespace = "")]
public string faultstring { get; set; }
[XmlArray(ElementName = "detail", Namespace = "")]
[XmlArrayItem(ElementName = "MIAPAPIException", Namespace = "http://generic.url/exceptions")]
public List<MIAPAPIException> MIAPAPIException { get; set; }
}
public class MIAPAPIException
{
[XmlElement(Namespace = "")]
public string ErrorCode { get; set; }
[XmlElement(Namespace = "")]
public string ErrorActor { get; set; }
[XmlElement(Namespace = "")]
public string Description { get; set; }
[XmlElement(Namespace = "")]
public string FurtherDetails { get; set; }
DateTime _ErrorTimestamp { get; set; }
[XmlElement(Namespace = "")]
public string ErrorTimestamp {
get{ return _ErrorTimestamp.ToString("yyyy-MM-dd HH:mm:ss");}
set{ _ErrorTimestamp = DateTime.ParseExact(value, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture) ;}
}
}
}
Upvotes: 0
Reputation: 540
Replace .Close() with .Abort(). Abort should be used when the proxy is in a faulted state. You could try the below.
if (client.State != CommunicationState.Faulted)
{
client.Close();
}
else
{
client.Abort();
}
Upvotes: 0