I have single queue with more than message and i want to consume that message sequencial in
order for another transaction with parse payload foreach message
the problem is when i loop all payload list after get the first paylod why first message
is always still count on list after being loop and always being proceed
and the second message and so on not being consumed
my sample list messsage array is "
first message : ["test123#gmail.com","smtp.email.io","admin","2525","123","Test_200999#yahoo.com","Email Confirmation","Hello World"]
second message :
["test123#gmail.com","smtp.email.io","admin","2525","123","Test_200998#yahoo.com","Email Confirmation","Hello World"]
third message
["test123#gmail.com","smtp.email.io","admin","2525","123","Test_200997#yahoo.com","Email Confirmation","Hello World"]
here's my code
private static async void ExcecutePayload(CancellationToken cancellationToken)
{
var factory = new ConnectionFactory
{
HostName = "localhost"
};
var connection = factory.CreateConnection();
using var channel = connection.CreateModel();
channel.QueueDeclare("email_confirmation_notifications", durable: true, exclusive: false, autoDelete: false,arguments: null);
channel.BasicQos(0, 1, false);
var consumer = new EventingBasicConsumer(channel);
EmailModel _model = new EmailModel();
var s1 = new List<string>();
string s2 = "";
bool
first = false,
second = false;
var random = new Random();
consumer.Received += (model, eventArgs) =>
{
var processingtime = random.Next(1, 10);
var body = eventArgs.Body.ToArray();
var message = Encoding.UTF8.GetString(body);
foreach (char c in message)
{
if (second)
{
s1.Add(s2);
s2 = "";
first = false;
second = false;
}
if (first)
{
if (c == '"')
{
second = true;
}
else
{
s2 += c;
}
}
if (c == '"' && !first && !second)
{
first = true;
}
}
if (second && first)
{
s1.Add(s2);
}
foreach (var item in s1.Select((value, i) => new { i, value }).ToList())
{
var value = item.value;
var index = item.i;
if (index == 0) { _model.Sender = value; };
if (index == 1) { _model.Host = value; };
if (index == 2) { _model.UserName = value; };
if (index == 3) { _model.Port = value; };
if (index == 4) { _model.Password = value; };
if (index == 5) { _model.To = value; };
if (index == 6) { _model.Subject = value; };
if (index == 7) { _model.Body = value; };
}
try
{
InsertTransaction(_model, cancellationToken);
SendEmailAsync(_model, cancellationToken);
}
catch (Exception ex)
{
throw ex;
}
Console.WriteLine($"Notification email has sent to: {string.Join(", ", _model.To)}");
Task.Delay(TimeSpan.FromSeconds(processingtime), cancellationToken).Wait();
channel.BasicAck(deliveryTag: eventArgs.DeliveryTag, multiple: false);
};
await Task.CompletedTask;
channel.BasicConsume(queue: "email_confirmation_notifications", autoAck: false, consumer: consumer);
Console.ReadKey();
}
I'm working on an application based on .NET Framework 4.8. I'm using Microsoft Batching API. The below are code snippets
public async Task<List<BatchResponse>> UpdateEventsInBatchAsync(string accessToken, Dictionary<int, Tuple<string, OfficeEvent>> absEvents)
{
var httpMethod = new HttpMethod("PATCH");
var batches = GetUpdateRequestBatches(absEvents, httpMethod);
var graphClient = GetGraphClient(accessToken);
var batchResponses = new List<BatchResponse>();
foreach (var batch in batches)
{
try
{
var batchResponseList = await ExecuteBatchRequestAsync(graphClient, batch).ConfigureAwait(false);
batchResponses.AddRange(batchResponseList);
}
catch (ClientException exc)
{
_logService.LogException("Error while processing update batch", exc);
batchResponses.Add(new BatchResponse
{ StatusCode = HttpStatusCode.InternalServerError, ReasonPhrase = exc.Message });
}
catch (Exception exc)
{
_logService.LogException("Error while processing update batch", exc);
batchResponses.Add(new BatchResponse { StatusCode = HttpStatusCode.InternalServerError, ReasonPhrase = exc.Message });
}
}
return batchResponses;
}
The respective methods used in the above code are mentioned below in respective order-
GetUpdateRequestBatches
private IEnumerable<BatchRequestContent> GetUpdateRequestBatches(Dictionary<int, Tuple<string, OfficeEvent>> absEvents, HttpMethod httpMethod)
{
var batches = new List<BatchRequestContent>();
var batchRequestContent = new BatchRequestContent();
const int maxNoBatchItems = 20;
var batchItemsCount = 0;
foreach (var kvp in absEvents)
{
System.Diagnostics.Debug.Write($"{kvp.Key} --- ");
System.Diagnostics.Debug.WriteLine(_serializer.SerializeObject(kvp.Value.Item2));
var requestUri = $"{_msOfficeBaseApiUrl}/me/events/{kvp.Value.Item1}";
var httpRequestMessage = new HttpRequestMessage(httpMethod, requestUri)
{
Content = _serializer.SerializeAsJsonContent(kvp.Value.Item2)
};
var requestStep = new BatchRequestStep(kvp.Key.ToString(), httpRequestMessage);
batchRequestContent.AddBatchRequestStep(requestStep);
batchItemsCount++;
// Max number of 20 request per batch. So we need to send out multiple batches.
if (batchItemsCount > 0 && batchItemsCount % maxNoBatchItems == 0)
{
batches.Add(batchRequestContent);
batchRequestContent = new BatchRequestContent();
batchItemsCount = 0;
}
}
if (batchRequestContent.BatchRequestSteps.Count < maxNoBatchItems)
{
batches.Add(batchRequestContent);
}
if (batches.Count == 0)
{
batches.Add(batchRequestContent);
}
return batches;
}
GetGraphClient
private static GraphServiceClient GetGraphClient(string accessToken)
{
var graphClient = new GraphServiceClient(new DelegateAuthenticationProvider(requestMessage =>
{
requestMessage
.Headers
.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
return Task.FromResult(0);
}));
return graphClient;
}
ExecuteBatchRequestAsync
private async Task<List<BatchResponse>> ExecuteBatchRequestAsync(IBaseClient graphClient, BatchRequestContent batch)
{
BatchResponseContent response = await graphClient.Batch.Request().PostAsync(batch);
Dictionary<string, HttpResponseMessage> responses = await response.GetResponsesAsync();
var batchResponses = new List<BatchResponse>();
var failedReqKeys = new Dictionary<string, TimeSpan>();
foreach (var key in responses.Keys)
{
using (HttpResponseMessage httpResponseMsg = await response.GetResponseByIdAsync(key))
{
var responseContent = await httpResponseMsg.Content.ReadAsStringAsync();
string eventId = null;
var reasonPhrase = httpResponseMsg.ReasonPhrase;
if (!string.IsNullOrWhiteSpace(responseContent))
{
var eventResponse = JObject.Parse(responseContent);
eventId = (string)eventResponse["id"];
// If still null, then might error have occurred
if (eventId == null)
{
var errorResponse = _serializer.DeserializeObject<ErrorResponse>(responseContent);
var error = errorResponse?.Error;
if (error != null)
{
if (httpResponseMsg.StatusCode == (HttpStatusCode)429)
{
System.Diagnostics.Debug.WriteLine($"{httpResponseMsg.StatusCode} {httpResponseMsg.Content}");
var executionDelay = httpResponseMsg.Headers.RetryAfter.Delta ?? TimeSpan.FromSeconds(5);
failedReqKeys.Add(key, executionDelay);
continue;
}
reasonPhrase = $"{error.Code} - {error.Message}";
}
}
}
var batchResponse = new BatchResponse
{
Key = key,
EventId = eventId,
StatusCode = httpResponseMsg.StatusCode,
ReasonPhrase = reasonPhrase
};
batchResponses.Add(batchResponse);
}
}
if (failedReqKeys.Count == 0) return batchResponses;
return await HandleFailedRequestsAsync(graphClient, failedReqKeys, batch, batchResponses).ConfigureAwait(false);
}
HandleFailedRequestsAsync
private async Task<List<BatchResponse>> HandleFailedRequestsAsync(IBaseClient graphClient, Dictionary<string, TimeSpan> failedReqKeys, BatchRequestContent batch, List<BatchResponse> batchResponses)
{
// Sleep for the duration as suggested in RetryAfter
var sleepDuration = failedReqKeys.Values.Max();
Thread.Sleep(sleepDuration);
var failedBatchRequests = batch.BatchRequestSteps.Where(b => failedReqKeys.Keys.Contains(b.Key)).ToList();
var failedBatch = new BatchRequestContent();
foreach (var kvp in failedBatchRequests)
{
failedBatch.AddBatchRequestStep(kvp.Value);
}
var failedBatchResponses = await ExecuteBatchRequestAsync(graphClient, failedBatch);
batchResponses.AddRange(failedBatchResponses);
return batchResponses;
}
I'm getting an error as on the first line in method ExecuteBatchRequestAsync as
Microsoft.Graph.ClientException: Code: invalidRequest
Message: Unable to deserialize content.
---> System.ObjectDisposedException: Cannot access a closed Stream.
Can anyone nudge me where I'm doing wrong?
I am using ASP.Net MVC.
using (ExchangeServiceBinding exchangeServer = new ExchangeServiceBinding())
{
ICredentials creds = new NetworkCredential("username", "password");
exchangeServer.Credentials = creds;
exchangeServer.Url = "https://myexchangeserver.com/EWS/Exchange.asmx";
FindItemType findItemRequest = new FindItemType();
findItemRequest.Traversal = ItemQueryTraversalType.Shallow;
// define which item properties are returned in the response
ItemResponseShapeType itemProperties = new ItemResponseShapeType();
itemProperties.BaseShape = DefaultShapeNamesType.AllProperties;
findItemRequest.ItemShape = itemProperties;
// identify which folder to search
DistinguishedFolderIdType[] folderIDArray = new DistinguishedFolderIdType[1];
folderIDArray[0] = new DistinguishedFolderIdType();
folderIDArray[0].Id = DistinguishedFolderIdNameType.inbox;
// add folders to request
findItemRequest.ParentFolderIds = folderIDArray;
// find the messages
FindItemResponseType findItemResponse = exchangeServer.FindItem(findItemRequest);
// read returned
FindItemResponseMessageType folder = (FindItemResponseMessageType)findItemResponse.ResponseMessages.Items[0];
ArrayOfRealItemsType folderContents = new ArrayOfRealItemsType();
folderContents = (ArrayOfRealItemsType)folder.RootFolder.Item;
ItemType[] items = folderContents.Items;
// if no messages were found, then return null -- we're done
if (items == null || items.Count() <= 0)
{ return null; }
// FindItem never gets "all" the properties, so now that we've found them all, we need to get them all.
BaseItemIdType[] itemIds = new BaseItemIdType[items.Count()];
for (int i = 0; i < items.Count(); i++)
{
itemIds[i] = items[i].ItemId;
}
GetItemType getItemType = new GetItemType();
getItemType.ItemIds = itemIds;
getItemType.ItemShape = new ItemResponseShapeType();
getItemType.ItemShape.BaseShape = DefaultShapeNamesType.AllProperties;
getItemType.ItemShape.BodyType = BodyTypeResponseType.HTML;
getItemType.ItemShape.BodyTypeSpecified = true;
GetItemResponseType getItemResponse = exchangeServer.GetItem(getItemType);
ItemType[] messages = new ItemType[getItemResponse.ResponseMessages.Items.Count()];
List<MailRecipientModel> model = new List<MailRecipientModel>();
for (int j = 0; j < messages.Count(); j++)
{
messages[j] = ((ItemInfoResponseMessageType)getItemResponse.ResponseMessages.Items[j]).Items.Items[0];
MailRecipientModel model1 = new MailRecipientModel();
model1.Subject = messages[j].Subject;
model1.FromAddress = messages[j].Sender.Item.EmailAddress;
model1.DisplayName = messages[j].Sender.Item.Name;
model1.Date = messages[j].DateTimeReceived.Date.ToString();
model1.MailBody = messages[j].Body.Value;
model1.MsgId = messages[j].ItemId.Id;
if (messages[j].Attachments != null) {
//
}
model.Add(model1);
}
return model;
}
This my code I wanna download attachment file and if attachment file is image so its display in browser.
I am using Microsoft ActiveSync Exchange Server.
If you know how to do so please help me.
public List<FileAttachment> getAttachmentFromExchangeAccount( ExchangeAccounts exchangeAccount, String attachmentId, String itemId) {
ExchangeService service = obtainExchangeService(exchangeAccount);
List<FileAttachment> fileAttachmentsEWS = new ArrayList<>();
try {
EmailMessage message = EmailMessage.bind(service, new ItemId(attachmentId), new PropertySet(ItemSchema.Attachments));
message.load();
for (Attachment attachment : message.getAttachments()) {
attachment.load();
if (attachment.getId().equals(itemId)) {
FileAttachment fileAttachment = (FileAttachment) attachment;
fileAttachment.load();
fileAttachmentsEWS.add(fileAttachment);
}
}
} catch (ServiceLocalException e) {
LOG.debug("OUT NOK loadAttachmentFile ServiceLocalException");
LOG.debug(e.getMessage());
} catch (Exception e) {
LOG.debug("OUT NOK loadAttachmentFile Exception");
LOG.debug(e.getMessage());
}
return fileAttachmentsEWS;
}
You should be using the GetAttachment operation https://msdn.microsoft.com/en-us/library/office/aa494316(v=exchg.150).aspx . There is a Proxy code sample https://blogs.msdn.microsoft.com/vikas/2007/10/15/howto-ews-use-getattachment-to-download-attachments-off-mailappointment/
public async Task<IActionResult> Contact1()
{
if (Convert.ToBoolean(HttpContext.Session.GetString("login")))
{
var pass = new ContactViewModel();
var username = HttpContext.Session.GetString("username");
Program.readname(HttpContext.Session.GetString("username"));
var names = HttpContext.Session.GetString("studentnames");
var obj1 = JsonConvert.DeserializeObject<Program.Data>(names);
if (Program.datecheck(username, DateTime.Today.Date))
{
try{
var handler = new HttpClientHandler { Credentials = new NetworkCredential(user, password) };
using (var client = Program.CreateHttpClient(handler, user, database3))
{
string check = username + Convert.ToString(DateTime.Today.Date);
var readresponse = client.GetStringAsync(check).Result;
var obj2 = JsonConvert.DeserializeObject<Program.Data>(readresponse);
}
catch(Exception ee)
{ ViewBag.m6 = ee.Message; ViewBag.attendance = "Attendace is not take yet";}
}
pass.studentattend = obj2.studentattend1;
}
}
else { ViewBag.attendance = "Attendace is not take yet"; }
pass.studentname = obj1.studentname1;
pass.studentrollno = obj1.studentrollno1;
pass.date = DateTime.Today.Date;
HttpContext.Session.SetInt32("classselect", 1);
ViewData["Message"] = "Student Attendance of Class: " + HttpContext.Session.GetString("classname1");
ViewBag.Login = HttpContext.Session.GetString("login");
ViewBag.name = HttpContext.Session.GetString("name");
ViewBag.classname1 = HttpContext.Session.GetString("classname1");
ViewBag.classname2 = HttpContext.Session.GetString("classname2");
ViewBag.classname3 = HttpContext.Session.GetString("classname3");
ViewBag.classname4 = HttpContext.Session.GetString("classname4");
return View("/Views/Home/Contact.cshtml", pass);
}
else
{
ViewData["Message"] = "Please Login First!!";
return View("/Views/Home/Login.cshtml");
}
}
The above code is runnig well in my local ISS server but when i run this on bluemix then i am getting blank page. I tried to find out the problem and get to the conclusion that if the control does not enter in the if part of that code:
if (Program.datecheck(username, DateTime.Today.Date))
{
var handler = new HttpClientHandler { Credentials = new NetworkCredential(user, password) };
using (var client = Program.CreateHttpClient(handler, user, database3))
{
string check = username + Convert.ToString(DateTime.Today.Date);
var readresponse = client.GetStringAsync(check).Result;
var obj2 = JsonConvert.DeserializeObject<Program.Data>(readresponse);
pass.studentattend = obj2.studentattend1;
}
}
else { ViewBag.attendance = "Attendace is not take yet"; }
then it will run fine.I am unable to find what is wrong in that query.
I'm trying to integrate the Royal Mail SOAP API into my .NET Code. I have followed the advice here Consume WCF Royal Mail API in c# Console Application and here C# WCF Namespaces Move To Header & Use NS Prefix.
I have created a custom IClientMessageFormatter to be able to attach the namespaces to the beginning of the soap envelope, but I still can't seem to get this to work. I keep receiving the following error. Could not establish trust relationship for the SSL/TLS secure channel with authority 'api.royalmail.com', and the inner exception is: The remote certificate is invalid according to the validation procedure.
I am using Visual Studio 13 and .Net version 3.5, I've tried numerous other versions but with no further progress. When I debug I can see that the normal message been passed into the RoyalMailMessage but when it runs OnWriteStartEnvelope I can't see any changes to the _message object. I've created a trace to see what soap request is been sent.
I have sent my XML request to Royal Mail support who validate that the reason it is failing is due to the namespaces not been declared in the envelope and the missing prefixes.
RoyalMail.cs
internal class RoyalMail
{
private readonly X509Certificate2 _certificate;
private readonly Config _config;
public RoyalMail()
{
_config = new Config();
_config.LoadConfig();
// Load The SSL Certificate (Check The File Exists)
var certificatePath = (Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + #"\" + _config.GetCertificateName());
if (!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
var 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()
{
var myBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport)
{
MaxReceivedMessageSize = 2147483647
};
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
var uri = new Uri(_config.GetEndpointUrl());
var endpointIdentity = EndpointIdentity.CreateDnsIdentity("api.royalmail.com");
var shippingClient = new shippingAPIPortTypeClient(myBinding, new EndpointAddress(uri, endpointIdentity, new AddressHeaderCollection()));
if (shippingClient.ClientCredentials != null)
shippingClient.ClientCredentials.ClientCertificate.Certificate = _certificate;
foreach (var od in shippingClient.Endpoint.Contract.Operations)
{
od.Behaviors.Add(new RoyalMailIEndpointBehavior());
}
return shippingClient;
}
private SecurityHeaderType GetSecurityHeaderType()
{
var securityHeader = new SecurityHeaderType();
var creationDate = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
var nonce = (new Random().Next(0, int.MaxValue)).ToString();
var hashedPassword = GetSha1(_config.GetPassword());
var concatednatedDigestInput = string.Concat(nonce, creationDate, Encoding.Default.GetString(hashedPassword));
var digest = GetSha1(concatednatedDigestInput);
var passwordDigest = Convert.ToBase64String(digest);
var encodedNonce = Convert.ToBase64String(Encoding.Default.GetBytes(nonce));
var doc = new XmlDocument();
using (var writer = doc.CreateNavigator().AppendChild())
{
writer.WriteStartDocument();
writer.WriteStartElement("wsse", "Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
writer.WriteStartElement("wsse", "UsernameToken", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
writer.WriteElementString("wsse", "Username", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", _config.GetUsername());
writer.WriteElementString("wsse", "Password", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", passwordDigest);
writer.WriteElementString("wsse", "Nonce", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", encodedNonce);
writer.WriteElementString("wsse", "Created", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", creationDate);
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Flush();
}
if (doc.DocumentElement != null)
{
doc.DocumentElement.RemoveAllAttributes();
var headers = doc.DocumentElement.ChildNodes.Cast<XmlElement>().ToArray();
securityHeader.Any = headers;
}
return securityHeader;
}
private integrationHeader GetIntegrationHeader()
{
var header = new integrationHeader();
var created = DateTime.Now;
var createdAt = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
header.dateTime = created;
header.version = int.Parse(_config.GetVersion());
header.dateTimeSpecified = true;
header.versionSpecified = true;
var idStructure = new identificationStructure {applicationId = _config.GetApplicationId()};
var 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
var md5 = MD5.Create();
var inputBytes = Encoding.ASCII.GetBytes(input);
var hash = md5.ComputeHash(inputBytes);
// step 2, convert byte array to hex string
var sb = new StringBuilder();
foreach (var t in hash)
{
sb.Append(t.ToString("X2"));
}
return sb.ToString();
}
/*
* Check Response Footer For Errors & Warnings From Service
* If Error Return True So We Can Inform File maker Of Error
* Ignore Warnings For Now
*
*/
private static void CheckErrorsAndWarnings(integrationFooter integrationFooter)
{
if (integrationFooter != null)
{
if (integrationFooter.errors != null && integrationFooter.errors.Length > 0)
{
var errors = integrationFooter.errors;
foreach (var error in errors)
{
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;
}
}
if (integrationFooter.warnings != null && integrationFooter.warnings.Length > 0)
{
var warnings = integrationFooter.warnings;
foreach (var warning in warnings)
{
MessageBox.Show("Royal Mail Request Warning: " + warning.warningDescription + ". " + warning.warningResolution, "Royal Mail Request Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1);
}
}
}
}
/*
* Show Message Box With SOAP Error If We Receive A Fault Code Back From Service
*
*/
private static void ShowSoapException(FaultException e)
{
var message = e.CreateMessageFault();
var errorDetail = message.GetDetail<XmlElement>();
var errorDetails = errorDetail.ChildNodes;
var fullErrorDetails = "";
for (var i = 0; i < errorDetails.Count; i++)
{
var xmlNode = errorDetails.Item(i);
if (xmlNode != null)
fullErrorDetails += xmlNode.Name + ": " + xmlNode.InnerText + "\n";
}
MessageBox.Show("An Error Occured With Royal Mail Service: " + message.Reason + "\n\n" + fullErrorDetails, "Royal Mail SOAP Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
}
public createShipmentResponse SendCreateShipmentRequest(CreateShipmentForm shippingForm)
{
var client = GetProxy();
try
{
var request = new createShipmentRequest {integrationHeader = GetIntegrationHeader()};
var shipment = new requestedShipment();
// Shipment Type Code (Delivery or Return)
var shipmentType = new referenceDataType {code = shippingForm.ShippingType};
shipment.shipmentType = shipmentType;
// 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)
var serviceType = new referenceDataType {code = shippingForm.ServiceType};
shipment.serviceType = serviceType;
// Service Offering (See Royal Mail Service Offering Type Codes. Too Many To List)
var serviceOfferingTypeContainer = new serviceOfferingType();
var serviceOffering = new referenceDataType {code = shippingForm.ServiceOffering};
serviceOfferingTypeContainer.serviceOfferingCode = serviceOffering;
shipment.serviceOffering = serviceOfferingTypeContainer;
// Service Format Code
var serviceFormatTypeContainer = new serviceFormatType();
var serviceFormat = new referenceDataType {code = shippingForm.ServiceFormat};
serviceFormatTypeContainer.serviceFormatCode = serviceFormat;
shipment.serviceFormat = serviceFormatTypeContainer;
// Shipping Date
shipment.shippingDate = shippingForm.ShippingDate;
shipment.shippingDateSpecified = true;
shipment.signature = true;
shipment.signatureSpecified = true;
// Sender Reference Number (e.g. Invoice Number or RA Number)
shipment.senderReference = shippingForm.InvoiceNumber;
/*
* Service Enhancements
*/
var serviceEnhancements = new List<serviceEnhancementType>();
shipment.serviceEnhancements = serviceEnhancements.ToArray();
/*
* Recipient Contact Details
*/
var recipientContact = new contact();
recipientContact.complementaryName = shippingForm.Company;
recipientContact.name = shippingForm.Name;
if(!shippingForm.EmailAddress.Equals("")) {
var email = new digitalAddress {electronicAddress = shippingForm.EmailAddress};
recipientContact.electronicAddress = email;
}
if(!shippingForm.MobileNumber.Equals("")) {
var tel = new telephoneNumber();
var phoneRegex = new Regex(#"[^\d]");
tel.telephoneNumber1 = phoneRegex.Replace(shippingForm.MobileNumber, "");
tel.countryCode = "00" + shippingForm.CountryDiallingCode;
recipientContact.telephoneNumber = tel;
}
shipment.recipientContact = recipientContact;
/*
* Recipient Address
*
*/
var recipientAddress = new address
{
addressLine1 = shippingForm.AddressLine1,
addressLine2 = shippingForm.AddressLine2,
addressLine3 = shippingForm.AddressLine3,
addressLine4 = shippingForm.County,
postTown = shippingForm.Town
};
var country = new countryType();
var countryCode = new referenceDataType { code = shippingForm.CountryCode };
country.countryCode = countryCode;
recipientAddress.country = country;
recipientAddress.postcode = shippingForm.PostCode;
recipientAddress.stateOrProvince = new stateOrProvinceType {stateOrProvinceCode = new referenceDataType()};
shipment.recipientAddress = recipientAddress;
// Shipment Items
var items = new List<item> ();
foreach(var i in shippingForm.Items) {
var item = new item
{
numberOfItems = i.Products.Count.ToString(),
weight = new dimension
{
value = i.Weight*1000,
unitOfMeasure = new unitOfMeasureType {unitOfMeasureCode = new referenceDataType {code = "g"}}
}
};
items.Add(item);
}
if (shippingForm.ServiceType.Contains("international"))
{
var internationalInfo = new internationalInfo
{
shipperExporterVatNo = _config.GetVatNumber(),
documentsOnly = false,
shipmentDescription = "Invoice Number: " + shippingForm.InvoiceNumber,
invoiceDate = DateTime.Now,
termsOfDelivery = "EXW",
invoiceDateSpecified = true,
purchaseOrderRef = shippingForm.InvoiceNumber
};
var parcels = new List<parcel>();
foreach (var i in shippingForm.Items)
{
var parcel = new parcel
{
weight = new dimension
{
value = i.Weight*1000,
unitOfMeasure = new unitOfMeasureType
{
unitOfMeasureCode = new referenceDataType {code = "g"}
}
},
invoiceNumber = shippingForm.InvoiceNumber,
purposeOfShipment = new referenceDataType {code = "31"}
};
var contents = new List<contentDetail>();
foreach (var product in i.Products)
{
var contentDetail = new contentDetail
{
articleReference = product.Sku,
countryOfManufacture = new countryType
{
countryCode = new referenceDataType
{
code = product.CountryOfManufacture
}
},
currencyCode = new referenceDataType {code = product.CurrencyCode},
description = product.Name,
unitQuantity = product.Qty.ToString(),
unitValue = product.Price,
unitWeight = new dimension
{
value = Convert.ToSingle(product.Weight*1000),
unitOfMeasure = new unitOfMeasureType
{
unitOfMeasureCode = new referenceDataType {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;
var 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 occurred: " + 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;
}
}
RoyalmailMessage.cs
class RoyalMailMessage : Message
{
public Message _message;
public RoyalMailMessage(Message message)
{
_message = message;
}
public override MessageHeaders Headers
{
get
{
return _message.Headers;
}
}
public override MessageProperties Properties
{
get
{
return _message.Properties;
}
}
public override MessageVersion Version
{
get
{
return _message.Version;
}
}
protected override void OnWriteStartBody(XmlDictionaryWriter writer)
{
writer.WriteStartElement("Body", "http://schemas.xmlsoap.org/soap/envelope/");
}
protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
{
_message.WriteBodyContents(writer);
}
protected override void OnWriteStartEnvelope(XmlDictionaryWriter writer)
{
writer.WriteStartElement("soapenv", "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");
}
}
RoyalMailMessageFormatter.cs
public class RoyalMailMessageFormatter : IClientMessageFormatter
{
private readonly IClientMessageFormatter _formatter;
public RoyalMailMessageFormatter(IClientMessageFormatter formatter)
{
_formatter = formatter;
}
public object DeserializeReply(Message message, object[] parameters)
{
return _formatter.DeserializeReply(message, parameters);
}
public Message SerializeRequest(MessageVersion messageVersion, object[] parameters)
{
var message = _formatter.SerializeRequest(messageVersion, parameters);
return new RoyalMailMessage(message);
}
}
RoyalMailIEndpointBehavior.cs
internal class RoyalMailIEndpointBehavior : IOperationBehavior
{
public void ApplyClientBehavior(OperationDescription description, ClientOperation proxy)
{
proxy.Formatter = new RoyalMailMessageFormatter(proxy.Formatter);
}
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
}
public void Validate(OperationDescription operationDescription)
{
}
}
The error you are getting is basically because of the certificate.
Having said that, I think you should use the v2 of the API as although it is still awful, there are examples out there and you don't need to use a cert.
Rick Strahl has successfully changed the namespaces in the v2 version, see here https://weblog.west-wind.com/posts/2016/Apr/02/Custom-Message-Formatting-in-WCF-to-add-all-Namespaces-to-the-SOAP-Envelope .
There is one new Royal Mail Shipping API 2 available , after I've lost many hours try development the integration with Royal Mail I finally found a way. I'm sharing my project in the git.
https://github.com/americoa/RoyalMailShippingAPIV2