SOAP service client, "No update available" - c#

I am writing an application to consume SOAP service. The work flow is like this:
Pull in order from SOAP server (Request Order)
POST/Response with changes to SOAP server (Response to Order)
Request PO changes from server (Request order changes)
The third party server already set up a testing environment for us. The first thing
I am trying to do is request and download the order from server. But seems the problem is that I can only download/pull the order per application once. After the first time I requested the order, I will get the exception: "System.Web.Services.Protocols.SoapException: No order updates available". If I create another application do the same thing, it will be able to request the order again, but only for once. Is there any place I can set/config so that my application could pull order regardless it is an newer order or not, or it's something to do with the server side?
The test code I am pulling order:
/// <summary>
/// Used by supplier to check Order
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnRequestPO_Click(object sender, EventArgs e)
{
string t_return;
SupplierServices supplierServices = new SupplierServices();
LoginDetails lgDetails = new LoginDetails();
lgDetails.UserName = "user";
lgDetails.Password = "password";
supplierServices.LoginDetailsValue = lgDetails;
RequestPurchaseOrder requestPO = new RequestPurchaseOrder();
requestPO.SupplierCode = "1234";
try
{
Order returned_order = supplierServices.SupplierRequestPO(requestPO);
if (returned_order != null)
{
t_return = returned_order.ToString();
MessageBox.Show(t_return);
}
else
MessageBox.Show("Returned order is empty!");
}
catch (Exception ex)
{
String responseFromServer = ex.Message.ToString() + " ";
if (ex!= null)
{
MessageBox.Show(responseFromServer);
}
}

It appears from your code that the response "No order updates available" is being returned from the third party. You are going to have to ask them why you are getting that error.

Related

FluentFtp validate server cert against fingerprint

I have a powershell script using WinScp that allows me to authenticate the server cert against a fingerprint stored as a string "a1:ec:72:18:8b:c3:dc:12:9b:77:b0:6d:f4:c1:a6:cf:db:47:8f:66:66:15:14:39:c4:62:85:a7:b2:73:f7:93"
I am attempting to implement FluentFtp inside the main data processing app so we no longer need the script. _ftpsOptions is an object containing various ftps relevant settings from Configuration. I've read that I need to implement a callback handler to ValidateCertificate so, in my ftps method:
client.Config.ValidateAnyCertificate = _ftpsOptions.IgnoreCertificateErrors;
client.ValidateCertificate += new FtpSslValidation(OnValidateCertificate); //this is ignored if ValidateAnyCertificate is true
and then.
/// <summary>
/// Callback handler for FtpSslValidation
/// </summary>
/// <param name="control"><see cref="BaseFtpClient"/> A base Ftp Client</param>
/// <param name="e"><see cref="FtpSslValidationEventArgs"/> options</param>
private void OnValidateCertificate(BaseFtpClient control, FtpSslValidationEventArgs e)
{
X509Certificate2 serverCert = (X509Certificate2)e.Certificate;
if (serverCert.Thumbprint == _ftpsOptions.FingerPrint)
{
e.PolicyErrors = SslPolicyErrors.None;
}
else
{
e.PolicyErrors = SslPolicyErrors.RemoteCertificateNameMismatch;
}
if (e.PolicyErrors != System.Net.Security.SslPolicyErrors.None)
{
// invalid cert, do you want to accept it?
e.Accept = false;
}
else
{
e.Accept = true;
}
}
To access the Thumbprint property I have to cast to X509Certificate2 as mentioned in several blog posts. There is no 'bad server cert' option in the SslPolicyErrors enum, so picking the closest.
Problem is: check is failing. I can't see the Thumbprint value in VS because its being optimized away. Tried adding [MethodImpl(MethodImplOptions.NoOptimization] to the method, but it didn't help. I think it would need adding to the X509Certificate2 class. Added a Log.Debug and that worked.
[10:50:49 DBG] [FtpsFluent.OnValidateCertificate] Server Thumbprint: 679B8B251C541FA0CCF3734B25A7C523635B9360
[10:50:49 DBG] [FtpsFluent.OnValidateCertificate] Validate Against: a1:ec:72:18:8b:c3:dc:12:9b:77:b0:6d:f4:c1:a6:cf:db:47:8f:66:66:15:14:39:c4:62:85:a7:b2:73:f7:93
These look different enough that I don't think I'm comparing the same thing. Should I change my config to store the 679B... value? Should I be going about this differently?

Redirect to a different aspx page and run the next code in background (.NET 4.5.2)

I am working on an ASP.NET Webform project (legacy code).On my button_click event i am sending sms message to all the datas populated in this.
var customerSMS = BusinessLayer.SMS.SmsSetup.GetAllCustomerSMS(OfficeId);
This takes around 15seconds to do all the computing and get the data(1000rows)
from the Db.And for each data it runs through the loop and does validation and
sends the sms and it does take time.I want to do this task in background and
redirect the user to the index page and the background process continues till it
gets out of the loop.I am new to this and still learning this beautiful
language C#.I did go through this amazing Asynchronous Programming async/await
and Multithreading approach and got hold of it only in simple WindowsForm
applications.Any reference/code snippet/best approach with a simple explanation for my case would be helpful.
My button click event code :
protected void ReturntoDashboard_Click(object sender, EventArgs e)
{
sms = Everest.Net.BusinessLayer.SMS.SmsSetup.GetSmsSetUp(OfficeId);
if (sms.EnableSmsData && sms.SmsCount > 0)
{
#region Loan Section
var smsLoan = Everest.Net.BusinessLayer.SMS.SmsSetup.GetLoanId(s.Sms_AccountNumber);
var loanId =
BusinessLayer.SMS.SmsSetup.GetLoanIdValue(s.Sms_AccountNumber);
var dateexceeded =
BusinessLayer.SMS.SmsSetup.IsDateExceeded(loanId);
if (smsLoan != null && dateexceeded == true)
{
foreach (Common.SMS.SMSSetup sm in smsLoan)
{
var smsClosingBalanceLoan = BusinessLayer.SMS.SmsSetup.GetAmountForLoanAlert( sm.LoanId,
BusinessLayer.Core.DateConversion
.GetCurrentServerDate()
.AddDays(sms.DaysbeforeLoanalerts).ToString());
if (smsClosingBalanceLoan != null)
{
if (smsClosingBalanceLoan.LoanAmountToPay > 0)
{
int smsSentAlertCount = sms.LoanAlertCount;
var logCount = BusinessLayer.SMS.SmsSetup.GetLoanSmsAlertSentCount(DateTime.Now.AddDays(-smsSentAlertCount).ToString("yyyy-MM-dd"), DateTime.Now.ToString("yyyy-MM-dd"), sm.LoanAccountNumber);
if (logCount < smsSentAlertCount)
{
smsLog = new Everest.Net.Common.SMS.SMSSetup();
finalMessage = "Dear Member, Your Loan accnt " + sm.LoanAccountNumber + " with Principal"+ "+" + "Int Amnt: Rs." + smsClosingBalanceLoan.LoanAmountToPay + " need to be payed.Thank You," + officeName.OfficeName;
smsLog.LogServiceType = "Loan";
smsLog.LogSmsType = s.Sms_SmsType;
smsLog.LogSmsMessage = finalMessage;
smsLog.LogCustomerId = s.CustomerId.ToString();
smsLog.LogAccountNumber = s.Sms_AccountNumber;
smsLog.LogAccountType = s.Sms_AccountType;
smsLog.LogSmsSentDate = BusinessLayer.Core.DateConversion.GetCurrentServerDate();
smsLog.LogSmsFailedDate = "";
smsLog.LogSentStatus = true;
smsLog.LogUserId = UserId;
smsLog.LogSmsFailedMessage = "";
try
{
var result = Everest.Net.BusinessLayer.SMS.smsParameters.SendSMS(sms.FromNum, sms.Token, sms.Url, cellNum, finalMessage);
}
catch (Exception ex)
{
smsLog.LogSmsFailedDate = System.DateTime.Now.ToString("MM/dd/yyyy HHmmss");
smsLog.LogSentStatus = false;
smsLog.LogSmsFailedMessage = ex.Message;
Everest.Net.BusinessLayer.SMS.SmsSetup.InsertSMSLog(smsLog);
}
sms = Everest.Net.BusinessLayer.SMS.SmsSetup.GetSmsSetUp(OfficeId);
sms.SmsCount = sms.SmsCount - 1;
Everest.Net.BusinessLayer.SMS.SmsSetup.UpdateSmsSetup(sms);
Everest.Net.BusinessLayer.SMS.SmsSetup.InsertSMSLog(smsLog);
}
}
}
}
}
}
}
}
catch (Exception ex)
The ideal solution would remove the responsibility of sending the SMS from the web application itself. Instead, the web application should create a database record containing the message and recipient addresses, and a separate background job (e.g. a Windows Service) should poll the database and send SMS messages when neeeded. This is the best solution in terms of fault tolerance and auditability, because there is a permanent record of the messaging job which can be resumed if the system fails.
That being said, maybe you don't want to go to all that trouble. If you feel strongly that you wish to send the SMS directly from the ASP.NET application, you will need to create a Task and queue it to run using QueueBackgroundWorkitem. You will need to refactor your code a bit.
Move all the logic for sending the SMS into a separate function that accepts all the information needed as parameters. For example,
static void SendSMS(string[] addresses, string messagetext)
{
//Put your SMS code here
}
When you need to call the function, queue it as a background item
HostingEnvironment.QueueBackgroundWorkItem(a => SendSMS(addresses, messageText));
If your worker task needs to access its own cancellation token (e.g. if it is supposed to loop until cancelled), it is passed as an argument to the lambda expression. So you could modify the prototype
static void SendSMS(string[] addresses, string messagetext, CancellationToken token)
{
while (!token.IsCancellationRequested)
{
//Put your code here
}
}
and pass it thus:
HostingEnvironment.QueueBackgroundWorkItem(token => SendSMS(addresses, messageText, token));
Placing the task in the background queue ensures that ASP.NET keeps track of the thread, doesn't try to garbage collect it, and shuts it down properly when the application pool needs to shut down.
After queuing the background operation, your page can render is content per usual and conclude the HTTP response while the task continues to execute.

Debugging Program Keeps Sending Emails After Exit

I have the below code which I use as part of a program which reads some event logs.
After stepping through the code this morning to test something out, I keep getting error messages emailed to me:
EventLogHelper error occurred in QueryEvents
Exception: The RPC server is unavailable
User:
Client: D7-089
The process is not running on my machine, and I only stepped through the method in question once or twice. However The messages just keep coming. The space of time between each message seems to vary, and I have received at least 15 now.
How is this possible? I feel that if the program is sending me emails, it must be executing somewhere, but I cannot see it in the Processes tab in Task Manager, and I tried ending all Visual Studio related processes without any joy.
I restarted the PC on which VS was running, but I am still receiving the emails.
Main()
public static void Main()
{
var eh = new EventLogHelper();
var eventFired = eh.CheckEvents();
}
EventLogHelper.cs
public readonly string PcName;
private readonly int Timespan;
private readonly string Filter;
private static EventLogSession Session;
/// <summary>
/// ctor
/// </summary>
public EventLogHelper()
{
Timespan = 30000; // 30 seconds
PcName = "D7-089"; // This is usually "Environment.MachineName", but specified it here for testing
Filter = $"*[System[(EventID='5061' or EventID='5058') and TimeCreated[timediff(#SystemTime) <= {Timespan}]]]";
}
CheckEvents
/// <summary>
/// Checks the event logs for remote pc and returns true if any of the events we are interested in fired
/// </summary>
/// <returns></returns>
public bool CheckEvents()
{
var query = BuildQuery(PcName, Filter);
for (var i = 0; i < 60; i++)
{
var logs = QueryEvents(query);
var events = ReadLogs(logs);
if (events > 0)
{
return true;
}
System.Threading.Thread.Sleep(1000);
}
return false;
}
BuildQuery
/// <summary>
/// Builds an EventLogQuery for the given pcname and filter. This should be set up with a user who has admin rights
/// </summary>bh
private static EventLogQuery BuildQuery(string pcName, string filter)
{
try
{
using (var pw = GetPassword())
{
Session = new EventLogSession(
pcName,
"DOMAIN",
"USER",
pw,
SessionAuthentication.Default);
}
return new EventLogQuery("Security", PathType.LogName, filter)
{ Session = Session };
}
catch (Exception ex)
{
Email.Send($"EventLogHelper error occurred in BuildQuery \n\n Exception: {ex.Message} \n\n User: {Program.UserName} \n\n Client: {pcName}");
Environment.Exit(Environment.ExitCode);
return null;
}
}
QueryEvents
This is where the error is occurring. I stepped through this method 2 times at most and as I type this question I am still getting error emails through.
/// <summary>
/// Execute the given EventLogQuery
/// </summary>
private EventLogReader QueryEvents(EventLogQuery query)
{
try
{
return new EventLogReader(query);
}
catch (Exception ex)
{
Email.Send($"EventLogHelper error occurred in QueryEvents \n\n Exception: {ex.Message} \n\n User: {Program.UserName} \n\n Client: {PcName}");
Environment.Exit(Environment.ExitCode);
return null;
}
}
ReadLogs
/// <summary>
/// Read the given EventLogReader and return the amount of events that match the IDs we are looking for
/// </summary>
/// <param name="logReader"></param>
/// <returns></returns>
private int ReadLogs(EventLogReader logReader)
{
var count5058 = 0;
var count5061 = 0;
EventRecord entry;
try
{
while ((entry = logReader.ReadEvent()) != null)
{
if (entry.Id == 5058)
{
count5058++;
}
else
{
count5061++;
}
}
}
catch (Exception ex)
{
Email.Send($"EventLogHelper error occurred in ReadLogs \n\n Exception: {ex.Message} \n\n User: {Program.UserName} \n\n Client: {PcName}");
Environment.Exit(Environment.ExitCode);
}
return count5058 + count5061;
}
It turns out that this was being caused by a stupid mistake on my part.
This program has a Post-Build Event which is called with:
if $(ConfigurationName) == Release ("$(ProjectDir)PostBuildRelease.bat" "$(TargetDir)" #(VersionNumber) "$(TargetFileName)" "$(TargetName)")
So it only runs when VS build configuration is set to Release.
PostBuildRelease.bat simply copies the resuling assembly to the live location, ready for users to have copied to their desktops at logon.
Whilst testing my app, I foolishly edited the source code to query a specific PC, and then stepped through the code.
However, the build configuration was set to Release, So once the assembly was built ready to be debugged, it was automatically copied into the live executable location and therefore also copied to user's desktops at logon.
If the code is run with a hard-coded PcName where that PC is not the current machine, the event query appears to fail with the above error message.
So all of the emails I receiving were being sent out because the program was actually being executed on user PCs. However because PcName was hard-coded in, it always looked like it was coming from my instance of the program!
The lesson here is to always be aware of which build configuration is currently selected, especially if a Post-Build event is specified.

How to read Post Parameters from Payment Gateway API After Successful Transaction

I am using a Payment Gateway Which will send the response to the Success page. Their documentation indicates they are sending response as POST parameters. I tried to Read these parameters but i am not able to get the parameters. I had sent a mail to support and they said they will send the data from their server to our server prior redirection to success page. I implemented my code in success page. Where I should Implement and how to save these values in my code for further use.
My code is Here
protected void Page_Load(object sender, EventArgs e)
{
/// store all the posted form variables in an object to use later
response notifyresponse = new response();
notifyresponse.CreditVouchersTransactionId = Request["CreditVouchersTransactionId"];
notifyresponse.MerchantName = GetFormVariableOrNull(Request["MerchantName"]);
notifyresponse.AmountToPay = GetFormVariableOrNull(Request["AmountToPay"]);
notifyresponse.PaymentOKURL = GetFormVariableOrNull(Request["PaymentOKURL"]);
notifyresponse.OrderId = GetFormVariableOrNull(Request["OrderId"]);
notifyresponse.AmountCurrency = GetFormVariableOrNull(Request["AmountCurrency"]);
notifyresponse.PaymentType = GetFormVariableOrNull(Request["AmountType"]);
notifyresponse.PaymentStatus = GetFormVariableOrNull(Request["PaymentStatus"]);
string[] keys = Request.Form.AllKeys;
for (int i = 0; i < keys.Length; i++)
{
Session["amountpay"]=keys[i] ;
}
}
protected string GetFormVariableOrNull(object formvariable)
{
if (formvariable != null)
{
try
{
return formvariable.ToString();
}
catch (Exception ex)
{
/// log the exception in file or DB
Console.WriteLine(ex.Message);/// just for an example
return null;
}
}
else
return null;
}
Thanks
Use Fiddler, it will show you all the traffic going back forth and provide a more accurate picture as to whats going on between those transactions
https://www.telerik.com/download/fiddler
Edit
A HTTP message can be composed of two part, first is the header, the other is the body.
When making a GET request to a server, it won't contain a body. A POST request on the other hand, will. There are line breaks in between the headers and the body... I've demonstrated a POST request below

Windows Phone 8 Raw Notification with Windows Azure Mobile Services

I'm trying to get a raw push notification to work from Azure Mobile Services to Windows Phone 8.
I've only signed up with Windows Azure for the free mobile services which comes with the free 20mb database and free mobile services.
The site to manage Windows Azure services has a link to an example of how to send a push notification to an app to update a flip tile which can be found here.
On insert into a table a script runs which sends the notification.
There's another example on MSDN which provides an example of how to create an ASP page that sends a raw notification to a WP8 app. That example is here.
I've gotten both examples to work but I need the first example to send a raw notification instead so the code in the second example works.
This is the code I have:
In my Windows Phone 8 app I have this to receive notifications, in App.xaml.cs:
private void AcquirePushChannel()
{
/// Holds the push channel that is created or found.
HttpNotificationChannel pushChannel;
// The name of our push channel.
string channelName = "RawSampleChannel";
// Try to find the push channel.
pushChannel = HttpNotificationChannel.Find(channelName);
if (pushChannel == null)
{
pushChannel = new HttpNotificationChannel(channelName);
// Register for all the events before attempting to open the channel.
pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);
pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);
pushChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(PushChannel_HttpNotificationReceived);
pushChannel.Open();
}
else
{
// The channel was already open, so just register for all the events.
pushChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(PushChannel_ChannelUriUpdated);
pushChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(PushChannel_ErrorOccurred);
pushChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(PushChannel_HttpNotificationReceived);
// Display the URI for testing purposes. Normally, the URI would be passed back to your web service at this point.
System.Diagnostics.Debug.WriteLine(pushChannel.ChannelUri.ToString());
//MessageBox.Show(String.Format("Channel Uri is {0}",
// pushChannel.ChannelUri.ToString()));
}
}
void PushChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
{
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
// Display the new URI for testing purposes. Normally, the URI would be passed back to your web service at this point.
System.Diagnostics.Debug.WriteLine(e.ChannelUri.ToString());
MessageBox.Show(String.Format("Channel Uri is {0}",
e.ChannelUri.ToString()));
});
}
void PushChannel_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e)
{
// Error handling logic for your particular application would be here.
Deployment.Current.Dispatcher.BeginInvoke(() =>
MessageBox.Show(String.Format("A push notification {0} error occurred. {1} ({2}) {3}",
e.ErrorType, e.Message, e.ErrorCode, e.ErrorAdditionalData))
);
}
/// <summary>
/// Event handler for when a raw notification arrives. For this sample, the raw
/// data is simply displayed in a MessageBox.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void PushChannel_HttpNotificationReceived(object sender, HttpNotificationEventArgs e)
{
string message;
using (System.IO.StreamReader reader = new System.IO.StreamReader(e.Notification.Body))
{
message = reader.ReadToEnd();
}
Deployment.Current.Dispatcher.BeginInvoke(() =>
MessageBox.Show(String.Format("Received Notification {0}:\n{1}",
DateTime.Now.ToShortTimeString(), message))
);
}
In Application Launching it calls AcquirePushChannel:
private void Application_Launching(object sender, LaunchingEventArgs e)
{
AcquirePushChannel();
}
My issue is in my Windows Azure Mobile Services database, where I have the following code on insert to a table to send the raw push notification, which doesn't work:
function insert(item, user, request) {
request.execute({
success: function () {
// Write to the response and then send the notification in the background
request.respond();
// for testing I'm manually putting in the channel ID where it says <channelID> below
push.mpns.sendRaw(<channelID>,
'test', {
success: function (pushResponse) {
console.log("Sent push:", pushResponse);
}
});
}
});
}
There is doc on this here, so I'm sure it's correct, but it just doesn't work.
And there's an example here.
One other question is, how can I view console.log via Windows Azure?
I was able to find out from the logs that my code wasn't sending the notification and worked out that it was my method of testing which was causing it and so I've fixed it. I've found out that the insert script only fires when I use the code:
private MobileServiceCollection<TodoItem, TodoItem> items;
private IMobileServiceTable<TodoItem> todoTable = App.MobileService.GetTable<TodoItem>();
private async void InsertTodoItem(TodoItem todoItem)
{
// This code inserts a new TodoItem into the database. When the operation completes
// and Mobile Services has assigned an Id, the item is added to the CollectionView
await todoTable.InsertAsync(todoItem);
items.Add(todoItem);
}
The insert script for example doesn't run if you use Management Studio and insert a row manually.

Categories