How to add <detail> field to the exception in .net 6 SoapCore

416 Views Asked by At

I'm upgrading the soap service originally written in .net framework to .net 6. Since there is no native support I'm using SoapCore library for it. Communication works fine, but I encountered a problem with error messages. In the original solution the SoapException(string message, XmlQualifiedName code, string actor, XmlNode detail) was used to throw the error message to the client. It allows to add XmlNode with detailed information about the exception which the client reads and shows to the end user. I tried to replace it with FaultException and add additional details to it but nothing leads to the required outcome.

As I mentioned I already tried to create a custom exception that inheritance from FaultExcepion and add additional fields but they were not present in the response. I also tried to add the original SoapException object from the old .net framework but the returned exception still doesn't contain the required detail field even if they are present in SoapException object itself.

This is the outcome which the server returns now:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <s:Body>
        <s:Fault>
            <faultcode>s:Server</faultcode>
            <faultstring>Unknown session.</faultstring>
        </s:Fault>
    </s:Body>
</s:Envelope>

Original required response:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
        <soap:Fault>
            <faultcode>soap:Server</faultcode>
            <faultstring>Unknown session.</faultstring>
            <faultactor>http://MyUrl/SoapEndpoint</faultactor>
            <detail>
                //Custom XmlNode 
                <NoSuchSessionException xmlns="http://mySoapNamespace/">
                    <ResidualText>Unknown session.</ResidualText>
                    <LoggedReason>Unknown session.</LoggedReason>
                </NoSuchSessionException>
                //
            </detail>
        </soap:Fault>
    </soap:Body>
</soap:Envelope>

Do I miss something? I would be glad for any help.

1

There are 1 best solutions below

0
Selim Balci On BEST ANSWER

I know OP, you said you tried custom exception class, but give this one a go still. In SoapCore, to add a <detail> field to the SOAP fault response in .NET 6, you can create a custom fault contract type that includes the desired additional information. Try these steps:

Define a custom fault contract type that represents the <detail> section of the SOAP fault response. This type should include the required additional fields. For example:

[DataContract(Namespace = "http://mySoapNamespace/")]
public class MyFancyExceptionDetail
{
    [DataMember]
    public string ResidualText { get; set; }

    [DataMember]
    public string LoggedReason { get; set; }
}

Then in your service operation, throw a FaultException<TDetail> where TDetail is your custom fault contract type. Pass an instance of your custom fault contract type containing the additional information, i.e:

throw new FaultException( new MyFancyExceptionDetail { ResidualText = "Unknown session.", LoggedReason = "Unknown session." }, "Unknown session.");

In your SoapEndpoint implementation, you can catch the FaultException and handle it by returning a custom SOAP fault response.

using SoapCore.Extensibility;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;

public class CustomFaultDispatcher : DefaultFaultBodyWriter
{
    public CustomFaultDispatcher(MessageFault messageFault, string defaultFaultReason) 
        : base(messageFault, defaultFaultReason) { }

    protected override void WriteDetail(XmlDictionaryWriter writer, EnvelopeVersion version)
    {
        // Get the custom fault detail from the MessageFault
        var detail = MessageFault.GetDetail<MyFancyExceptionDetail>();

        // Write the custom detail XML
        writer.WriteStartElement("detail", version.Namespace);
        writer.WriteStartElement("NoSuchSessionException", "http://mySoapNamespace/");
        writer.WriteElementString("ResidualText", detail.ResidualText);
        writer.WriteElementString("LoggedReason", detail.LoggedReason);
        writer.WriteEndElement(); // NoSuchSessionException
        writer.WriteEndElement(); // detail
    }
}

Register the custom fault dispatcher in the SOAP endpoint configuration. Here's an example:

using SoapCore.ServiceModel;
using SoapCore.ServiceModel.Dispatcher;

app.UseSoapEndpoint<IMyService>("/SoapEndpoint.svc", new SoapEncoderOptions(), SoapSerializer.XmlSerializer, new CustomFaultDispatcherPolicy());

By following these steps, you should be able to include the <detail> field with the desired additional information in the SOAP fault response in .NET 6 using SoapCore, and that should be giving you a better understanding of what's going on.

Working with legacy code is just great, isn't it...

Hope this helps at all.