在c#控制台应用程序中使用WCF皇家邮政API

本文关键字:皇家 WCF API 控制台 应用程序 | 更新日期: 2023-09-27 18:28:25

我试图在我的C#控制台应用程序中使用皇家邮政运输的API,但我被卡住了。当我调用API时,它会显示"无效请求"。。

这就是我到目前为止所做的

RoyalMailMessage.cs

 class RoyalMailMessage : Message
    {
        private readonly Message message;
        public RoyalMailMessage(Message message)
        {
            this.message = message;
        }
        public override MessageHeaders Headers
        {
            get
            {
                return this.message.Headers;
            }
        }
        public override MessageProperties Properties
        {
            get
            {
                return this.message.Properties;
            }
        }
        public override MessageVersion Version
        {
            get
            {
                return this.message.Version;
            }
        }
        protected override void OnWriteStartBody(XmlDictionaryWriter writer)
        {
            writer.WriteStartElement("Body", "http://schemas.xmlsoap.org/soap/envelope/");
        }
        protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
        {
            this.message.WriteBodyContents(writer);
        }
        protected override void OnWriteStartEnvelope(XmlDictionaryWriter writer)
        {
            writer.WriteStartElement("s", "Envelope", "http://schemas.xmlsoap.org/soap/envelope/");
            writer.WriteAttributeString("xmlns", "v2", null, "http://www.royalmailgroup.com/api/ship/V2");
            writer.WriteAttributeString("xmlns", "v1", null, "http://www.royalmailgroup.com/integration/core/V1");
            writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
            writer.WriteAttributeString("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema");
            writer.WriteAttributeString("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema");
        }
    }

RoyalMailMessageFormatter.cs

public class RoyalMailMessageFormatter : IClientMessageFormatter
    {
        private readonly IClientMessageFormatter formatter;
        public RoyalMailMessageFormatter(IClientMessageFormatter formatter)
        {
            this.formatter = formatter;
        }
        public object DeserializeReply(Message message, object[] parameters)
        {
            return this.formatter.DeserializeReply(message, parameters);
        }
        public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
        {
            var message = this.formatter.SerializeRequest(messageVersion, parameters);
            return new RoyalMailMessage(message);
        }
    }

RoyalMailIEndpointBehavior.cs

 class RoyalMailIEndpointBehavior : IOperationBehavior
    {
        public RoyalMailIEndpointBehavior() { }
        public void ApplyClientBehavior(OperationDescription description, ClientOperation proxy)
        {
            IClientMessageFormatter currentFormatter = proxy.Formatter;
            proxy.Formatter = new RoyalMailMessageFormatter(currentFormatter);
        }
        public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
        {
        }
        public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
        {
        }
        public void Validate(OperationDescription operationDescription)
        {
        }
    }

程序.cs

class Program
    {
        static void Main(string[] args)
        {
            try
            {
                using (var shippingService = new shippingAPIPortTypeClient())
                {
                    shippingService.ClientCredentials.UserName.UserName = "xxxx";
                    shippingService.ClientCredentials.UserName.Password = "xxxxx";
                    foreach (OperationDescription od in shippingService.Endpoint.Contract.Operations)
                    {
                        od.Behaviors.Add(new RoyalMailIEndpointBehavior());
                    }

                    var createShipment = new createShipmentRequest()
                    {
                        integrationHeader = new integrationHeader()
                        {
                            dateTime = DateTime.Now,
                            dateTimeSpecified = true,
                            debugFlag = false,
                            debugFlagSpecified = false,
                            identification = new identificationStructure()
                            {
                                applicationId = "xxxx",
                                endUserId = "Sandra",
                                intermediaryId = "null",
                                transactionId = "123456789"
                            },
                            performanceFlag = false,
                            performanceFlagSpecified = false,
                            testFlag = false,
                            testFlagSpecified = false,
                            version = 1,
                            versionSpecified = false

                        },
                        requestedShipment = new requestedShipment()
                        {
                            bfpoFormat = new bFPOFormatType()
                            {
                                bFPOFormatCode = null,
                            },
                            customerReference = "",
                            departmentReference = "",
                        }
                    };
                    shippingService.createShipment(null, createShipment);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }

应用程序配置

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="shippingAPISoapBinding">
          <security mode="Transport">
            <transport clientCredentialType="Certificate"></transport>
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="https://api.royalmail.com/shipping/onboarding" binding="basicHttpBinding"
          bindingConfiguration="shippingAPISoapBinding" contract="ShippingService.shippingAPIPortType"
          name="shippingAPIPort" behaviorConfiguration="CustomBehavior" />
    </client>
    <behaviors>
      <endpointBehaviors>
        <behavior name="CustomBehavior">
          <clientCredentials>
            <clientCertificate findValue="RM10001815" x509FindType="FindBySubjectName"
              storeLocation="CurrentUser" storeName="My" />
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

现在,当我调用API时,它会显示"无效请求"。。我不确定我是否遗漏了什么,可能是在Soap Envelop标头中添加凭据,如下所示?

<soapenv:Header>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>xxxx</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">xxxx</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">xWstjXG0iUxbv3NH/fX+kw==</wsse:Nonce>
<wsu:Created>2014-08-16T15:29:42</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>

在c#控制台应用程序中使用WCF皇家邮政API

首先,您丢失了已经识别的安全标头,以及createShipment请求中的一大堆其他字段,如地址、服务代码等。我强烈建议使用fiddler来捕获您的SOAP请求和响应,它们会让您更深入地了解正在发生的事情。您还可以将您生成的请求与皇家邮件入职提供的示例请求进行比较。

查看您的代码,您没有附加安全令牌(wsse),它需要对您发出的每个请求都是唯一的(即nonce令牌)。您还缺少createShipemt请求所需的各种其他字段,如地址、服务代码和类型等。

我必须将证书和密钥附加到请求中才能使其正常工作。以下是我为实现这一目标而创建的一些代码片段,它不是一个复制粘贴解决方案,但比您在皇家邮政和C#方面发现的任何其他解决方案都要好,应该会为您指明正确的方向。

请注意,我有一个配置类,它从sqlite数据库加载了很多设置(未发布)。createShipment请求的值来自一个表单(未发布),该表单预先填充了数据,但允许我们仓库中的用户进行相应的更改和调整。您已经使用了我在post中的自定义消息格式化程序示例(C#WCF(Royal Mail SOAP API)Declare Namespace In Header)来处理命名空间问题。皇家邮政API在C#中不容易实现,我花了将近2天的时间才得到有效的请求和响应,正如我所说,你真的需要捕获请求和响应来了解发生了什么。

private X509Certificate2 certificate;
private Config config;
    public RoyalMail() {
        // Load The Config
        config = new Config();
        config.loadConfig();
        // Load The SSL Certificate (Check The File Exists)
        String certificatePath = (Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + @"'" + config.GetCertificateName());
        if (!System.IO.File.Exists(certificatePath))
        {
            throw new Exception(@"The Royal Mail Certificate Is Missing From The Plugins Directory. Please Place The File " + config.GetCertificateName() + " In The Same Directory As The Plugin DLL File & Relaunch FileMaker.'n'n" + certificatePath);
        }
        certificate = new X509Certificate2(certificatePath, config.GetCertificatePassword());
        // Check It's In The Certificate 
        X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
        store.Open(OpenFlags.ReadWrite);
        if (!store.Certificates.Contains(certificate))
        {
            store.Add(certificate);
            MessageBox.Show("Certificate Was Installed Into Computer Trust Store");
        }
        store.Close(); 
    }

    /*
     * 
     * SOAP Service & Methods
     * 
     */
    private shippingAPIPortTypeClient GetProxy()
    {
        BasicHttpBinding myBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
        myBinding.MaxReceivedMessageSize = 2147483647;
        myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
        shippingClient = new shippingAPIPortTypeClient(myBinding, new EndpointAddress(new Uri(config.GetEndpointURL()), EndpointIdentity.CreateDnsIdentity("api.royalmail.com"), new AddressHeaderCollection()));
        shippingClient.ClientCredentials.ClientCertificate.Certificate = certificate;
        foreach (OperationDescription od in shippingClient.Endpoint.Contract.Operations)
        {
            od.Behaviors.Add(new RoyalMailIEndpointBehavior());
        }
        return shippingClient;
    }

    private SecurityHeaderType GetSecurityHeaderType()
    {
        SecurityHeaderType securityHeader = new SecurityHeaderType();
        DateTime created = DateTime.Now;
        string creationDate;
        creationDate = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
        string nonce = nonce = (new Random().Next(0, int.MaxValue)).ToString();
        byte[] hashedPassword;
        hashedPassword = GetSHA1(config.GetPassword());
        string concatednatedDigestInput = string.Concat(nonce, creationDate, Encoding.Default.GetString(hashedPassword));
        byte[] digest;
        digest = GetSHA1(concatednatedDigestInput);
        string passwordDigest;
        passwordDigest = Convert.ToBase64String(digest);
        string encodedNonce;
        encodedNonce = Convert.ToBase64String(Encoding.Default.GetBytes(nonce));
        XmlDocument doc = new XmlDocument();
        using (XmlWriter writer = doc.CreateNavigator().AppendChild())
        {
            writer.WriteStartDocument();
            writer.WriteStartElement("Security");
            writer.WriteStartElement("UsernameToken", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
            writer.WriteElementString("Username", config.GetUsername());
            writer.WriteElementString("Password", passwordDigest);
            writer.WriteElementString("Nonce", encodedNonce);
            writer.WriteElementString("Created", creationDate);
            writer.WriteEndElement();
            writer.WriteEndElement();
            writer.WriteEndDocument();
            writer.Flush();
        }
        doc.DocumentElement.RemoveAllAttributes();
        System.Xml.XmlElement[] headers = doc.DocumentElement.ChildNodes.Cast<XmlElement>().ToArray<XmlElement>();
        securityHeader.Any = headers;
        return securityHeader;
    }
    private integrationHeader GetIntegrationHeader()
    {
        integrationHeader header = new integrationHeader();
        DateTime created = DateTime.Now;
        String createdAt = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
        header.dateTime = created;
        header.version = Int32.Parse(config.GetVersion());
        header.dateTimeSpecified = true;
        header.versionSpecified = true;
        identificationStructure idStructure = new identificationStructure();
        idStructure.applicationId = config.GetApplicationID();
        string nonce = nonce = (new Random().Next(0, int.MaxValue)).ToString();
        idStructure.transactionId = CalculateMD5Hash(nonce + createdAt);
        header.identification = idStructure;
        return header;
    }
    private static byte[] GetSHA1(string input)
    {
        return SHA1Managed.Create().ComputeHash(Encoding.Default.GetBytes(input));
    }
    public string CalculateMD5Hash(string input)
    {
        // step 1, calculate MD5 hash from input
        MD5 md5 = System.Security.Cryptography.MD5.Create();
        byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
        byte[] hash = md5.ComputeHash(inputBytes);
        // step 2, convert byte array to hex string
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < hash.Length; i++)
        {
            sb.Append(hash[i].ToString("X2"));
        }
        return sb.ToString();
    }

    /*
     * Check Response Footer For Errors & Warnings From Service
     * If Error Return True So We Can Inform Filemaker Of Error
     * Ignore Warnings For Now
     * 
     */
    private bool checkErrorsAndWarnings(integrationFooter integrationFooter)
    {
        if (integrationFooter != null)
        {
            if (integrationFooter.errors != null && integrationFooter.errors.Length > 0)
            {
                errorDetail[] errors = integrationFooter.errors;
                for (int i = 0; i < errors.Length; i++)
                {
                    errorDetail error = errors[i];
                    MessageBox.Show("Royal Mail Request Error: " + error.errorDescription + ". " + error.errorResolution, "Royal Mail Request Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
                }
                if (errors.Length > 0)
                {
                    return true;
                }
            }
            if (integrationFooter.warnings != null && integrationFooter.warnings.Length > 0)
            {
                warningDetail[] warnings = integrationFooter.warnings;
                for (int i = 0; i < warnings.Length; i++)
                {
                    warningDetail warning = warnings[i];
                    //MessageBox.Show("Royal Mail Request Warning: " + warning.warningDescription + ". " + warning.warningResolution, "Royal Mail Request Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
                }
            }
        }
        return false;
    }
    /*
     * Show Message Box With SOAP Error If We Receive A Fault Code Back From Service
     *
     */
    private void showSoapException(FaultException e)
    {
        MessageFault message = e.CreateMessageFault();
        XmlElement errorDetail = message.GetDetail<XmlElement>();
        XmlNodeList errorDetails = errorDetail.ChildNodes;
        String fullErrorDetails = "";
        for (int i = 0; i < errorDetails.Count; i++)
        {
            fullErrorDetails += errorDetails.Item(i).Name + ": " + errorDetails.Item(i).InnerText + "'n";
        }
        MessageBox.Show("An Error Occured With Royal Mail Service: " + message.Reason.ToString() + "'n'n" + fullErrorDetails, "Royal Mail SOAP Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
    }
    public createShipmentResponse SendCreateShipmentRequest(CreateShipmentForm shippingForm)
    {
        shippingAPIPortTypeClient client = GetProxy();
        try
        {
            createShipmentRequest request = new createShipmentRequest();
            request.integrationHeader = GetIntegrationHeader();
            requestedShipment shipment = new requestedShipment();
            // Shipment Type Code (Delivery or Return)
            referenceDataType shipmentType = new referenceDataType();
            shipmentType.code = shippingForm.GetShippingType();
            shipment.shipmentType = shipmentType;
            // Service Occurence (Identifies Agreement on Customers Account) Default to 1. Not Required If There Is There Is Only 1 On Account
            shipment.serviceOccurrence = config.GetServiceOccurance();
            // Service Type Code (1:24H 1st Class, 2: 48H 2nd Class, D: Special Delivery Guaranteed, H: HM Forces (BFPO), I: International, R: Tracked Returns, T: Tracked Domestic)
            referenceDataType serviceType = new referenceDataType();
            serviceType.code = shippingForm.GetServiceType().GetServiceTypeCode();
            shipment.serviceType = serviceType;
            // Service Offering (See Royal Mail Service Offering Type Codes. Too Many To List)
            serviceOfferingType serviceOfferingTypeContainer = new serviceOfferingType();
            referenceDataType serviceOffering = new referenceDataType();
            serviceOffering.code = shippingForm.GetServiceOffering().GetCode();
            serviceOfferingTypeContainer.serviceOfferingCode = serviceOffering;
            shipment.serviceOffering = serviceOfferingTypeContainer;
            // Service Format Code
            serviceFormatType serviceFormatTypeContainer = new serviceFormatType();
            referenceDataType serviceFormat = new referenceDataType();
            serviceFormat.code = shippingForm.GetServiceFormat().GetFormat();
            serviceFormatTypeContainer.serviceFormatCode = serviceFormat;
            shipment.serviceFormat = serviceFormatTypeContainer;
            // Shipping Date
            shipment.shippingDate = shippingForm.GetShippingDate();
            shipment.shippingDateSpecified = true;
            // Signature Required (Only Available On Tracked Services)
            if (shippingForm.IsSignatureRequired())
            {
                shipment.signature = true;
            }
            else
            {
                shipment.signature = false;
                // Leave In Safe Place (Available On Tracked Non Signature Service Offerings)
                shipment.safePlace = shippingForm.GetSafePlaceText();
            }
            shipment.signatureSpecified = true;
            // Sender Reference Number (e.g. Invoice Number or RA Number)
            shipment.senderReference = shippingForm.GetInvoiceNumber();
            /*
             * Service Enhancements
            */
            List<serviceEnhancementType> serviceEnhancements = new List<serviceEnhancementType>();
            List<dataObjects.ServiceEnhancement> selectedEnhancements = shippingForm.GetServiceEnhancements();
            for (int i = 0; i < selectedEnhancements.Count; i++)
            {
                serviceEnhancementType enhancement = new serviceEnhancementType();
                referenceDataType enhancementCode = new referenceDataType();
                enhancementCode.code = selectedEnhancements.ElementAt(i).GetEnhancementType().ToString();
                enhancement.serviceEnhancementCode = enhancementCode;
                serviceEnhancements.Add(enhancement);
            }
            shipment.serviceEnhancements = serviceEnhancements.ToArray();

            /*
             * Recipient Contact Details
            */
            contact recipientContact = new contact();
            recipientContact.complementaryName = shippingForm.GetCompany();
            recipientContact.name = shippingForm.GetName();
            if(!shippingForm.GetEmailAddress().Equals("")) {
                digitalAddress email = new digitalAddress();
                email.electronicAddress = shippingForm.GetEmailAddress();
                recipientContact.electronicAddress = email;
            }
            if(!shippingForm.GetMobileNumber().Equals("")) {
                telephoneNumber tel = new telephoneNumber();
                Regex phoneRegex = new Regex(@"[^'d]");
                tel.telephoneNumber1 = phoneRegex.Replace(shippingForm.GetMobileNumber(), "");
                tel.countryCode = "00" + shippingForm.GetCountry().GetDialingCode();
                recipientContact.telephoneNumber = tel;
            }
            shipment.recipientContact = recipientContact;
            /*
             * Recipient Address
             * 
            */
            address recipientAddress = new address();
            recipientAddress.addressLine1 = shippingForm.GetAddressLine1();
            recipientAddress.addressLine2 = shippingForm.GetAddressLine2();
            recipientAddress.addressLine3 = shippingForm.GetAddressLine3();
            recipientAddress.addressLine4 = shippingForm.GetCounty();
            recipientAddress.postTown = shippingForm.GetTown();
            countryType country = new countryType();
            referenceDataType countryCode = new referenceDataType();
            countryCode.code = shippingForm.GetCountry().getCountryCode();
            country.countryCode = countryCode;
            recipientAddress.country = country;
            recipientAddress.postcode = shippingForm.GetPostCode();
            recipientAddress.stateOrProvince = new stateOrProvinceType();
            recipientAddress.stateOrProvince.stateOrProvinceCode = new referenceDataType();
            shipment.recipientAddress = recipientAddress;
            // Shipment Items
            List<RoyalMailAPI.RoyalMailShippingAPI.item> items = new List<RoyalMailAPI.RoyalMailShippingAPI.item> ();
            foreach(dataObjects.Item i in shippingForm.GetItems()) {
                RoyalMailAPI.RoyalMailShippingAPI.item item = new RoyalMailAPI.RoyalMailShippingAPI.item();
                item.numberOfItems = i.GetQty().ToString();
                item.weight = new dimension();
                item.weight.value = (float) (i.GetWeight() * 1000);
                item.weight.unitOfMeasure = new unitOfMeasureType();
                item.weight.unitOfMeasure.unitOfMeasureCode = new referenceDataType();
                item.weight.unitOfMeasure.unitOfMeasureCode.code = "g";
                items.Add(item);
            }
            if (shippingForm.GetServiceType().GetDescription().ToLower().Contains("international"))
            {
                internationalInfo InternationalInfo = new internationalInfo();
                InternationalInfo.shipperExporterVatNo = "GB945777273";
                InternationalInfo.documentsOnly = false;
                InternationalInfo.shipmentDescription = "Invoice Number: " + shippingForm.GetInvoiceNumber();
                InternationalInfo.invoiceDate = DateTime.Now;
                InternationalInfo.termsOfDelivery = "EXW";
                InternationalInfo.invoiceDateSpecified = true;
                InternationalInfo.purchaseOrderRef = shippingForm.GetInvoiceNumber();
                List<RoyalMailShippingAPI.parcel> parcels = new List<parcel>();
                foreach (dataObjects.Item i in shippingForm.GetItems())
                {
                    parcel Parcel = new parcel();
                    Parcel.weight = new dimension();
                    Parcel.weight.value = (float)(i.GetWeight() * 1000);
                    Parcel.weight.unitOfMeasure = new unitOfMeasureType();
                    Parcel.weight.unitOfMeasure.unitOfMeasureCode = new referenceDataType();
                    Parcel.weight.unitOfMeasure.unitOfMeasureCode.code = "g";
                    Parcel.invoiceNumber = shippingForm.GetInvoiceNumber();
                    Parcel.purposeOfShipment = new referenceDataType();
                    Parcel.purposeOfShipment.code = "31";
                    List<contentDetail> Contents = new List<contentDetail>();
                    foreach (RoyalMailAPI.dataObjects.ProductDetail product in i.GetProducts())
                    {
                        contentDetail ContentDetail = new contentDetail();
                        ContentDetail.articleReference = product.Sku;
                        ContentDetail.countryOfManufacture = new countryType();
                        ContentDetail.countryOfManufacture.countryCode = new referenceDataType();
                        ContentDetail.countryOfManufacture.countryCode.code = product.CountryOfManufacture;
                        ContentDetail.currencyCode = new referenceDataType();
                        ContentDetail.currencyCode.code = product.CurrencyCode;
                        ContentDetail.description = product.Name;
                        ContentDetail.unitQuantity = product.Qty.ToString();
                        ContentDetail.unitValue = Convert.ToDecimal(product.Price);
                        ContentDetail.unitWeight = new dimension();
                        ContentDetail.unitWeight.value = Convert.ToSingle(product.Weight * 1000);
                        ContentDetail.unitWeight.unitOfMeasure = new unitOfMeasureType();
                        ContentDetail.unitWeight.unitOfMeasure.unitOfMeasureCode = new referenceDataType();
                        ContentDetail.unitWeight.unitOfMeasure.unitOfMeasureCode.code = "g";

                        Contents.Add(ContentDetail);
                    }
                    //Parcel.contentDetails = Contents.ToArray();
                    parcels.Add(Parcel);
                }
                InternationalInfo.parcels = parcels.ToArray();
                shipment.internationalInfo = InternationalInfo;
            }
            else
            {
                shipment.items = items.ToArray();
            }
            request.requestedShipment = shipment;
            createShipmentResponse response = client.createShipment(GetSecurityHeaderType(), request);
            // Show Errors And Warnings
            checkErrorsAndWarnings(response.integrationFooter);
            return response;
        }
        catch (TimeoutException e)
        {
            client.Abort();
            MessageBox.Show("Request Timed Out: " + e.Message, "Request Timeout", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
        }
        catch (FaultException e)
        {
            client.Abort();
            showSoapException(e);
        }
        catch (CommunicationException e)
        {
            client.Abort();
            MessageBox.Show("A communication error has occured: " + e.Message + " - " + e.StackTrace, "Communication Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
        }
        catch (Exception e)
        {
            client.Abort();
            MessageBox.Show(e.Message, "Royal Mail Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
        }
        return null;
    }