I am sending a message to multiple phone numbers .
Mobile numbers are stored in an array .
string phNums = "91999999999,9199999998....";.
string[] phNos = phNums.Split(',');
But message doesn't reach all of the recipients , mostly to the numbers that are present near end of array.
The message are sent via a URL provided by SMS service provider in which the phone number and the message is embedded.
for (int i = 0; i < phNos.Length; i++)
{
url = #"http://aaa.bbb.ccc.dd/HTTPMTAPI?User=abc&Password=pqr&FromAddr=xyzSMS&DestNo=" + phNos[i] + "&msg=" + message;
Uri targetUri1 = new Uri(url);
System.Net.HttpWebRequest hwb1;
hwb1 = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(targetUri1);
hwb1.GetResponse();
}
As an alternate , I also used Webclient() but still successful message delivery is not guaranteed.
for (int i = 0; i < phNos.Length; i++)
{
WebClient cli= new WebClient();
url = #"http://aaa.bbb.ccc.dd/HTTPMTAPI?User=abc&Password=pqr&FromAddr=xyzSMS&DestNo=" + phNos[i] + "&msg=" + message;
cli.DownloadString(url);
}
How to ensure that message delivery is not skipped .
Like only if successful response is received on downloading the URL , the loop should progress to next mobile number and so on.
If there is any other possible mechanism , please do suggest. Thanks
I think this is what you want to do:
for (int i = 0; i < phNos.Length; i++)
{
url = #"http://aaa.bbb.ccc.dd/HTTPMTAPI?User=abc&Password=pqr&FromAddr=xyzSMS&DestNo=" + phNos[i] + "&msg=" + message;
Uri targetUri1 = new Uri(url);
System.Net.HttpWebRequest hwb1;
hwb1 = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(targetUri1);
System.Net.HttpWebResponse response = hwb1.GetResponse();
if (response != null)
{
int status = (int)response.StatusCode; // this changes the status
// from text response to the
// number, like 404
if (status == 404//or anything else you want to test//)
{
// put your retry logic here, make sure you add a way to break
// so you dont infinitely loop if the service is down or something
}
}
}
URLs have a length constraint. Your are likely hitting this limit and your are losing the trailing phone numbers as a result. Your best bet would be to break your requests into multiple requests of a certain size.
According to the following SO, it may be good practice to limit your request so that the url does not surpass 2000 characters.
What is the maximum length of a URL in different browsers?
Related
In ServiceNow, I am able to get only a maximum of 250 records in a SOAP request. How to get all the records?
Web Reference Url = https://*****.service-now.com/rm_story.do?WSDL
Code:
var url = "https://*****.service-now.com/rm_story.do?SOAP";
var userName = *****;
var password = *****;
var proxy = new ServiceNow_rm_story
{
Url = url,
Credentials = new NetworkCredential(userName, password)
};
try
{
var objRecord = new Namespace.WebReference.getRecords
{
// filters..
};
var recordResults = proxy.getRecords(objRecord);
}
catch (Exception ex)
{
}
In recordResults, I am getting only 250 records. How to get all the records ?
Also see this stack overflow answer which provides info.
Get ServiceNow Records Powershell - More than 250
Note that returning a large number of records can affect performance of the response and it may be more efficient to process your query in batches using offsets (i.e., get 1-100, then 101-200, ...). This can be achieved by using a sort order and offset. The ServiceNow REST Table API actually returns link headers from Get requests providing you links for the first, next and last set of records making it easy to know the url to query the next batch of records.
See: http://wiki.servicenow.com/index.php?title=Table_API#Methods
and look under 'Response Header'.
Have u tried to pass/override __limit parameter?
Google / wiki / Users manual / Release notes are always helpful
In your code snippet in line where it says //filter you should define __limit (and potentially __first_row and __last_row as explained in the example bellow)
int Skip = 0;
int Take = 250;
while (true)
{
using (var soapClient = new ServiceNowLocations.ServiceNow_cmn_location())
{
var cred = new System.Net.NetworkCredential(_user, _pass);
soapClient.Credentials = cred;
soapClient.Url = _apiUrl + "cmn_location.do?SOAP";
var getParams = new ServiceNowLocations.getRecords()
{
__first_row = Skip.ToString(),
__last_row = (Skip + Take).ToString(),
__limit = Take.ToString()
};
var records = soapClient.getRecords(getParams);
if (records != null)
{
if (records.Count() == 0)
{
break;
}
Skip += records.Count();
if (records.Count() != Take)
{
// last batch or everything in first batch
break;
}
}
else
{
// service now web service endpoint not configured correctly
break;
}
}
}
I made an library that handles interacting with ServiceNow Rest API much easier
https://emersonbottero.github.io/ServiceNow.Core/
I am using Mailgun API. There is a section that I need to provide a URL to them, then they are going to HTTP Post some data to me.
I provide this URL (http://test.com/MailGun/Webhook.aspx) to Mailgun, so they can Post data. I have a list of parameter names that they are sending like (recipient,domain, ip,...).
I am not sure how get that posted data in my page.
In Webhook.aspx page I tried some code as follows but all of them are empty.
lblrecipient.text= Request.Form["recipient"];
lblip.Text= Request.Params["ip"];
lbldomain.Text = Request.QueryString["domain"];
Not sure what to try to get the posted data?
This code will list out all the form variables that are being sent in a POST. This way you can see if you have the proper names of the post values.
string[] keys = Request.Form.AllKeys;
for (int i= 0; i < keys.Length; i++)
{
Response.Write(keys[i] + ": " + Request.Form[keys[i]] + "<br>");
}
This code reads the raw input stream from the HTTP request. Use this if the data isn't available in Request.Form or other model bindings or if you need access to the bytes/text as it comes.
using(var reader = new StreamReader(Request.InputStream))
content = reader.ReadToEnd();
You can simply use Request["recipient"] to "read the HTTP values sent by a client during a Web request"
To access data from the QueryString, Form, Cookies, or ServerVariables
collections, you can write Request["key"]
Source:
MSDN
Update: Summarizing conversation
In order to view the values that MailGun is posting to your site you will need to read them from the web request that MailGun is making, record them somewhere and then display them on your page.
You should have one endpoint where MailGun will send the POST values to and another page that you use to view the recorded values.
It appears that right now you have one page. So when you view this page, and you read the Request values, you are reading the values from YOUR request, not MailGun.
You are missing a step. You need to log / store the values on your server (mailgun is a client). Then you need to retrieve those values on your server (your pc with your web browser will be a client). These will be two totally different aspx files (or the same one with different parameters).
aspx page 1 (the one that mailgun has):
var val = Request.Form["recipient"];
var file = new File(filename);
file.write(val);
close(file);
aspx page 2:
var contents = "";
if (File.exists(filename))
var file = File.open(filename);
contents = file.readtoend();
file.close()
Request.write(contents);
Use this:
public void ShowAllPostBackData()
{
if (IsPostBack)
{
string[] keys = Request.Form.AllKeys;
Literal ctlAllPostbackData = new Literal();
ctlAllPostbackData.Text = "<div class='well well-lg' style='border:1px solid black;z-index:99999;position:absolute;'><h3>All postback data:</h3><br />";
for (int i = 0; i < keys.Length; i++)
{
ctlAllPostbackData.Text += "<b>" + keys[i] + "</b>: " + Request[keys[i]] + "<br />";
}
ctlAllPostbackData.Text += "</div>";
this.Controls.Add(ctlAllPostbackData);
}
}
In the web browser, open up developer console (F12 in Chrome and IE), then open network tab and watch the request and response data. Another option - use Fiddler (http://fiddler2.com/).
When you get to see the POST request as it is being sent to your page, look into query string and headers. You will see whether your data comes in query string or as form - or maybe it is not being sent to your page at all.
UPDATE: sorry, had to look at MailGun APIs first, they do not go through your browser, requests come directly from their server. You'll have to debug and examine all members of Request.Params when you get the POST from MailGun.
Try this
string[] keys = Request.Form.AllKeys;
var value = "";
for (int i= 0; i < keys.Length; i++)
{
// here you get the name eg test[0].quantity
// keys[i];
// to get the value you use
value = Request.Form[keys[i]];
}
In my case because I assigned the post data to the header, this is how I get it:
protected void Page_Load(object sender, EventArgs e){
...
postValue = Request.Headers["Key"];
This is how I attached the value and key to the POST:
var request = new NSMutableUrlRequest(url){
HttpMethod = "POST",
Headers = NSDictionary.FromObjectAndKey(FromObject(value), FromObject("key"))
};
webView.LoadRequest(request);
You can try to check the 'Request.Form.Keys'. If it will not works well, you can use 'request.inputStream' to get the soap string which will tell you all the request keys.
I want to read all messages from queue in AWS SQS without deleting them , using C# , but I am only getting the single last message.
Here is the code
ReceiveMessageRequest rmr = new ReceiveMessageRequest();
rmr.QueueUrl = url;
rmr.MaxNumberOfMessages = 10;
AmazonSQSClient sq = new AmazonSQSClient("xx", "yy");
ReceiveMessageResponse rmrep = sq.ReceiveMessage(rmr);
ReceiveMessageResult rmres = rmrep.ReceiveMessageResult;
//DeleteMessageRequest dmr = new DeleteMessageRequest();
string msgid = "";
string rephandle = "";
XmlDocument xl = new XmlDocument();
for (int i = 0; i < rmres.Message.Count;i++ )
{
rmrep = sq.ReceiveMessage(rmr);
rmres = rmrep.ReceiveMessageResult;
object y = JsonConvert.DeserializeObject<object>(rmres.Message[0].Body);
int z= y.add();
MessageBox.Show(z.ToString());
}
A queue is not a database table; you can't just 'read all the messages'. You tell SQS you want some messages, it picks some and sends them to you; you can't ask it, or expect it, to iterate thru a unique list of messages in the queue and present them to you, it is not intended for that purpose.
If you read 1 or messages, and delete them (or put them in another queue), then eventually you can 'read all the messages', but as long as you don't delete any, its likely that you will keep getting served back some messages multiple times.
You are calling receive message multiple times and thus are not seeing some of your messages. Change your code to something like this:
AmazonSQSClient sq = new AmazonSQSClient("xx", "yy");
while (true)
{
ReceiveMessageRequest rmr = new ReceiveMessageRequest();
rmr.QueueUrl = url;
rmr.MaxNumberOfMessages = 10;
ReceiveMessageResponse response= sq.ReceiveMessage(rmr);
foreach (Message message in response.ReceiveMessageResult.Message)
{
MessageBox.Show(message.ReceiptHandle + ": " + message.Body);
}
}
NOTE: If there are enough messages in the queue (the number depends on the queue and is not documented), you will not be able to receive any more because you will reach your maximum number of in-flight messages.
Another NOTE: If this runs longer than your visibility timeout you will start receiving the same messages again.
I am using a for loop in which Webclient class Downloadstring() method is used to load a external url .
The Url has been provided by SMS service provider in which Mobile number and the message to be transmitted is added.
But message is not being submitted to SMS gateway for all mobile numbers specified in phNos[] array ie downloading Url is skipped for some numbers . This occurs mostly for mobile numbers at end of array.
How can I ensure that program waits until url is loaded for particular number and then the program progresses forward.
WebClient cli = new WebClient();
for (i=0;i<phNos.Length;i++)
{
string url = #"http://example.com?DestNo=" + phNos[i] + "&msg=" + message;
cli.DownloadString(url);
}
Alternately I have also used System.Net.HttpWebRequest but the problem persist.
for (i=0;i<phNos.Length;i++)
{
string url = #"http://example.com?DestNo=" + phNos[i] + "&msg=" + message;
Uri targetUri = new Uri(url);
HttpWebRequest hwb = (HttpWebRequest)HttpWebRequest.Create(targetUri);
System.Net.HttpWebResponse response = hwb1.GetResponse();
int status = (int)response.StatusCode;
if (status == 200)
{
Response.Write("Successfully transmitted" + status);
}
}
Is there any other alternative method to ensure message is submitted 100 %.
Your code looks fine. DownloadString is blocking and if an error occurs it should raise an exception. How does the SMS gateway respond to your request? You should have a look at their documentation, because probably you can write a function that tests whether everything worked fine or not.
const int MAX_RETRY = 10;
WebClient cli= new WebClient();
for(i=0;i<phNos.Length;i++)
{
url = #"http://aaa.bbb.ccc.ddd?DestNo=" + phNos[i] + "&msg=" + message;
int cntRetry = 0;
while (!TestResult(cli.DownloadString(url)) && cntRetry < MAX_RETRY)
++cntRetry;
}
The problem could be that you are submitting too many requests to the gateway in a very short time. You could try to put some Thread.Sleep(1000) calls somewhere and see if things get any better.
WebClient cli= new WebClient();
for(i=0;i<phNos.Length;i++)
{
Thread.Sleep(1000);
url = #"http://aaa.bbb.ccc.ddd?DestNo=" + phNos[i] + "&msg=" + message;
cli.DownloadString(url);
}
You could also combine the two above examples, using maybe lower values for MAX_RETRY and Thread.Sleep.
const int MAX_RETRY = 5;
WebClient cli= new WebClient();
for(i=0;i<phNos.Length;i++)
{
url = #"http://aaa.bbb.ccc.ddd?DestNo=" + phNos[i] + "&msg=" + message;
int cntRetry = 0;
while (!TestResult(cli.DownloadString(url)) && cntRetry < MAX_RETRY) {
Thread.Sleep(500);
++cntRetry;
}
}
I would instantiate a webclient for every call and dispose it after downloadstring is called, like so
foreach(var phone in phNos)
{
using(WebClient cli= new WebClient())
{
url = String.Format(#"http://aaa.bbb.ccc.ddd?DestNo={0}&msg={1}", phone, message);
string result = cli.DownloadString(url);
// check if result has somekind of errorreport maybe?
Trace.WriteLine(result); // optionally write it to a trace file
}
}
Getting it disposed explicitely might help in also closing underlying networkconnections more quickly because I suspect the sheer number of connections are causing the issue. Throttling might also be an option (send less calls to the gateway per minute)
If this are 10000 or 100000 calls the network components between you and the sms gateway can be the culprit. Think off adsl modems/vpn software/routing issues or even the sms-gateway itself.
If that still doesn't resolve the issue: try Fiddler and or Wireshark to deeply inspect http traffic or even tcp/ip traffic.
For a school project, I have to create a Java Server that is able to service a .NET client that has a Service Reference to a WSDL. I have the .NET Client code:
using (var client = new MathServiceWSDLClient())
{
Console.WriteLine("Multiplying " + Num1 + " and " + Num2 + ": " + client.Multiply(Num1, Num2));
Console.WriteLine("Adding" + Num1 + " and " + Num2 + ": " + client.Add(Num1, Num2));
}
I have also written the Java Server:
Scanner sc = new Scanner(socket.getInputStream());
boolean clientExpectContinue = false;
int contentLength = -1;
String line;
while (!(line = sc.nextLine()).isEmpty()) {
System.out.println(line);
if (line.startsWith("Content-Length")) {
String[] elements = line.split(": ");
contentLength = Integer.parseInt(elements[1]);
} else if (line.startsWith("Expect")) {
clientExpectContinue = true;
}
}
int notEmpties = 0;
byte[] soapEnvelopeData = new byte[contentLength];
char[] soapChars = new char[contentLength];
for (int i = 0; i < contentLength; i++) {
soapChars[i] = (char) socket.getInputStream().read();
if (i == 0)
System.out.println("DFSDFSDf");
}
// System.out.println(socket.getInputStream().read(soapEnvelopeData));
System.out.println(soapEnvelopeData.length);
File file = new File("tempEnvelope.txt");
FileOutputStream fileOut = new FileOutputStream(file);
// fileOut.write(soapEnvelopeData);
System.out.println("Content!");
System.out.println(new String(soapChars));
fileOut.write(new String(soapChars).getBytes());
fileOut.flush();
fileOut.close();
/* Some fancy SOAP and Reflection stuff that works */
The gist of the server is as follows:
It gets the incomming request, reads through the headers and finds the content length. It parses and saves this. From here there are two versions. The first constructs a byte array the same size as the content length, and passes the array as a parameter into the socket.getInputStream().read() method. The second constructs a char array the same length of the content and then reads individual bytes from the stream and casts them to chars.
The issue comes into play when, as shown, I attempt to run the .NET client with multiple requests in one execution. The first request goes off without any sort of discernible issue. When the second one comes in, the server reads the headers, gets the content length and constructs the array. When it comes time to read from the socket, however, the program just waits. Using the char array method, I was able to learn that it waits when reading the first value. Once one minute has expired, .NET times out, and the rest of the program breaks.
If, however, I leave the server running, and only have one request per execution of the .NET client, everything is just fine; the response comes back just as it should.
I have tried some solutions already:
Creating a new MathServiceWSDLClient for every request
Putting every request in its own using() block.
Doing two of the same request at once: two Multiply() or Add() requests.
Any help is appreciated. Thank you all in advance.
~Ryno Janse van Rensburg
.net is probably keeping the socket open for subsequent requests. There may be a bug in your server-like java code related to this.
Are you able to use a framework instead for the Java server code? I would strongly recommend this, and recommend rmbedded Jetty without hesitation. This would mean you wouldn't have to work at the socket level in Java - you can let Jetty handle all of that complication.