What's wrong on using HttpWebRequest this way? - azure

This is the way I do server request to some endpoints from Azure:
public T SingleRead<T>(string url, string method, object entity = null)
{
T returnValue = default(T);
var resp = GetRESTResponse(url, method, entity);
string responseText = GetResponseText(resp);
try
{
returnValue = JsonConvert.DeserializeObject<T>(responseText);
}
catch (Exception ex)
{
return default(T);
}
return returnValue;
}
private HttpWebResponse GetRESTResponse(string url, string method, object entity = null)
{
var address;
if (!url.StartsWith("http"))
{
if (!url.StartsWith("/")) url = $"/{url}";
address = baseAddress + url;
}
else
{
address = url;
}
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(address);
req.Method = method;
if (entity != null)
{
byte[] byteArray = Encoding.Default.GetBytes(JsonConvert.SerializeObject(entity));
req.ContentLength = byteArray.Length;
req.ContentType = "application/json";
Stream dataStream = req.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Flush();
dataStream.Close();
}
HttpWebResponse resp;
try
{
resp = (HttpWebResponse)req.GetResponse();
}
catch (WebException e)
{
Log(e.Reponse);
resp = (HttpWebResponse)e.Response;
}
return resp;
}
private static string GetResponseText(HttpWebResponse resp)
{
var encoding = Encoding.ASCII;
string responseText = ".";
using (var reader = new StreamReader(resp.GetResponseStream(), encoding))
{
responseText = reader.ReadToEnd();
}
if (resp.StatusCode == HttpStatusCode.InternalServerError || resp.StatusCode == HttpStatusCode.BadRequest || resp.StatusCode == HttpStatusCode.NotFound)
{
return "";
}
return responseText;
}
It works quite often. Sometimes, it doesn't, and I get the a "A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond" error from the Log.
Is there some wrong in the procedure, or it could be a "timeout" by endpoint?
The called server users says "we don't have any problem, and we don't get the request".
Not sure if its the fault of the code above (maybe some stream not closed?). But I don't see any problem. Do you see any trouble in this?

It can be a network issue, which fails quite often. You need to remember there are several switches until the request goes outside the datacenter, and there are countless requests happening at the same time (you, and all other Azure customers).
This can be a transient fault, which may work if you send another request. You need to implement some retry logic to identify if the failure is transient or not.
More info:
https://learn.microsoft.com/en-us/azure/architecture/patterns/retry
And here's a sample using Polly, which is strongly recommended and even used inside Azure SDKs:
https://stackoverflow.com/a/66554740/1384539
https://learn.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/implement-http-call-retries-exponential-backoff-polly
https://github.com/App-vNext/Polly

Related

Getting 405 status Error when trying to consume POST method of web/Api in asp.net mvc5

I am trying to consume post method of web/api which takes string as parameter, but getting 405 Error : Api Controller Name: Getdata Action Method Name : postdata
please help to identify error.
public bool postdata(string fn)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:59968/api/Getdata");
var task = client.PostAsJsonAsync("Getdata", fn);
task.Wait();
var res = task.Result;
if(res.IsSuccessStatusCode)
{
return true;
}
}
return false;
}
[HttpPost]
public IHttpActionResult postdata(string p)
{
using (var context = new MediaEntities())
{
mediatable m = new mediatable()
{
media_path = p,
is_active = true
};
context.mediatable.Add(m);
context.SaveChanges();
return Ok();
}
}
I think you have used action method names instead of controller name else provide details of your api.
client.BaseAddress = new Uri("http://localhost:59968/api/{controller_name}");
//HTTP POST
var postTask = client.PostAsJsonAsync("controller_name", fn);
This link might help you.

enrollment error in using microsoft azure api during speaker enrollment

I am trying to use MS Azure Speaker recognition API (java) as per https://westus.dev.cognitive.microsoft.com/docs/services/563309b6778daf02acc0a508/operations/5645c3271984551c84ec6797 . I am able to get a identificationProfileId. The error occues when I try to enroll. Here is how I am enrolling
- get a wav file of the enrollment audio
- convert to base64 (thru online service)
- attach the base64 it as content to the call for enrollment along with identificationProfileId. I am doubtful about the b64 part
I am getting "Invalid Audio Format: Not a WAVE file - no RIFF header"
I am aware that the service needs the audio in PCM encoding as per doc.
Can someone pls let me know how to convert a wav audio to the required format that can be passed to the enrollment REST endpoint.
public class azureApiTest
{
public static String getID()
{
HttpClient httpclient = HttpClients.createDefault();
String ret = null;
try
{
URIBuilder builder = new URIBuilder("https://westus.api.cognitive.microsoft.com/spid/v1.0/identificationProfiles");
URI uri = builder.build();
HttpPost request = new HttpPost(uri);
request.setHeader("Content-Type", "application/json");
request.setHeader("Ocp-Apim-Subscription-Key", "fad541725xxxxxxx3362125790411");
// Request body
JsonObject locale = new JsonObject();
locale.addProperty("locale", "en-us");
StringEntity reqEntity = new StringEntity(locale.toString());
request.setEntity(reqEntity);
HttpResponse response = httpclient.execute(request);
HttpEntity entity = response.getEntity();
if (entity != null)
{
JsonParser parser = new JsonParser();
JsonObject o = parser.parse(EntityUtils.toString(entity)).getAsJsonObject();
ret = o.get("identificationProfileId").getAsString();
}
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
finally
{
return ret;
}
}
public static void main(String[] args)
{
HttpClient httpclient = HttpClients.createDefault();
try
{
String id = azureApiTest.getID();
System.out.println("ID created = "+id);
String enrollURL = "https://westus.api.cognitive.microsoft.com/spid/v1.0/identificationProfiles/" +id + "/enroll";
System.out.println("enrollURL = "+enrollURL);
URIBuilder builder = new URIBuilder(enrollURL);
builder.setParameter("shortAudio", "true");
URI uri = builder.build();
HttpPost request = new HttpPost(uri);
request.setHeader("Content-Type", "multipart/form-data");
request.setHeader("Ocp-Apim-Subscription-Key", "fad5417xxxxxxx3362125790411");
// Request body
File voiceb64 = new File("/Users/premnair/Desktop/vp/voice1b64.txt");
String data = FileUtils.readFileToString(voiceb64, "utf-8");
StringEntity reqEntity = new StringEntity(data);
request.setEntity(reqEntity);
HttpResponse response = httpclient.execute(request);
HttpEntity entity = response.getEntity();
if (entity != null)
{
System.out.println(EntityUtils.toString(entity));
}
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
}
}
If I pass the file like in the snippet below it works !
File file = new File("/Users/jdoe/Desktop/vp/v5.wav");
request.setEntity( new FileEntity(file, ContentType.APPLICATION_OCTET_STREAM) );
Don't use base 64, just raw byte array data will work.

Docusign .net send enevlope issue on one server

We've implement docusign api into our application and it works fine in development and on one of our production servers, but on particular production server it fails when running the following line
var scope = new OperationContextScope(client.InnerChannel);
The exception thrown is
Error: InvalidDataContractException: Message: Type 'System.Threading.Tasks.Task`1[DocuSign.DocuSignWeb.SetSharedAccessResult]' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.
Here is the complete method that is called
public DocuSignResponse SendEnvelope(Envelope envelope, string templateGUID)
{
var response = new DocuSignResponse();
var client = new DSAPIServiceSoapClient("DSAPIServiceSoap", URL);
try
{
var scope = new OperationContextScope(client.InnerChannel);
{
HttpRequestMessageProperty httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers.Add("X-DocuSign-Authentication", AuthHeader);
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
if (client.InnerChannel.State != System.ServiceModel.CommunicationState.Faulted)
{
// call service - everything's fine
}
else
{
// channel faulted - re-create your client and then try again
response.Success = false;
response.ErrorMessage = "Channel has faulted!!";
return response;
}
client.Open();
EnvelopeStatus envelopeStatus;
if (!string.IsNullOrEmpty(templateGUID))
{
DocuSignWeb.EnvelopeInformation envelopeInfo = new DocuSignWeb.EnvelopeInformation();
envelopeInfo.AccountId = AccountId;
envelopeInfo.EmailBlurb = envelope.EmailBlurb;
envelopeInfo.Subject = envelope.Subject;
// Configure the inline templates
DocuSignWeb.InlineTemplate inlineTemplate = new DocuSignWeb.InlineTemplate();
inlineTemplate.Sequence = "1";
inlineTemplate.Envelope = new DocuSignWeb.Envelope();
inlineTemplate.Envelope.Recipients = envelope.Recipients;
inlineTemplate.Envelope.AccountId = AccountId;
DocuSignWeb.CompositeTemplate template = new DocuSignWeb.CompositeTemplate();
template.InlineTemplates = new DocuSignWeb.InlineTemplate[] {inlineTemplate};
DocuSignWeb.ServerTemplate serverTemplate = new DocuSignWeb.ServerTemplate();
serverTemplate.Sequence = "1";
serverTemplate.TemplateID = templateGUID;
template.ServerTemplates = new[] {serverTemplate};
template.Document = envelope.Documents[0];
envelopeStatus = client.CreateEnvelopeFromTemplatesAndForms(envelopeInfo, new[] {template}, true);
}
else
{
envelopeStatus = client.CreateAndSendEnvelope(envelope);
}
// An envelope ID indicates that it succeeded
response.Success = true;
response.ResponseRef = envelopeStatus.EnvelopeID;
// No point doing this, as it wouldn't have been signed
// Request the status of that envelope
// response.Status = client.RequestStatus(envelopeStatus.EnvelopeID);
// Used if embed option being used
response.Envelope = envelope;
response.Status = envelopeStatus;
if (client.State != CommunicationState.Faulted)
{
client.Close();
}
else
{
client.Abort();
}
}
}
catch (InvalidDataContractException err)
{
err.LogError();
response.Success = false;
response.ErrorMessage = string.Format("InvalidDataContractException: Message: {0} StackTrace: {1} AuthHeader: {2}", err.Message, err.StackTrace, AuthHeader);
}
catch (CommunicationException err)
{
err.LogError();
response.Success = false;
response.ErrorMessage = string.Format("CommunicationException: Message: {0} StackTrace: {1}", err.Message, err.StackTrace);
client.Abort();
}
catch (TimeoutException err)
{
err.LogError();
response.Success = false;
response.ErrorMessage = string.Format("TimeoutException: Message: {0} StackTrace: {1}", err.Message, err.StackTrace);
client.Abort();
}
catch (Exception err)
{
err.LogError();
response.Success = false;
response.ErrorMessage = string.Format("Exception: Message: {0} StackTrace: {1}", err.Message, err.StackTrace);
client.Abort();
}
finally
{
client = null;
}
return response;
}
At the moment i'm at a loss as to what the issue is, given the same code and database works on another machines, so at present thinking it's environmental.
Any help greatly appreciated.
Looks like this turned out to be server issues on DocuSign side. Occasionally there are bugs and other issues that get rolled back in DocuSign's Demo sandbox environment.

using post throws IOExceptions on some phones

i have created an application in J2ME that uses the following method to connect to a server. php is used on the Server side to process the requests. the application works fine on some phones like NOkia asha 303 but throws IOException on other phones what could be the problem with this code. this method is called on a different thread. i also want to ask if you use post in j2me and set the
httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
do you have to urlencode the data before sending or that is handled automatically by j2me
public String sendData(String serverUrl, String dataToSend) {
String strResponse = "0"; //string to hold serverResponse
StringBuffer sb = new StringBuffer("");
HttpConnection httpConn = null;
InputStream inputStream = null;
OutputStream outStream = null;
try {
//convert the dataToSend to bytes
String strData = dataToSend; // get the data to Send and store it in a variable.
byte[] dataToSendBytes = strData.getBytes();
//open the Connection to the server.
httpConn = (HttpConnection) Connector.open(serverUrl, Connector.READ_WRITE, true);
if (httpConn != null) {
httpConn.setRequestMethod(HttpConnection.POST); // method used to send the data.
httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
httpConn.setRequestProperty("User-Agent", "Profile/MIDP-2.0 Configuration/CLDC-1.1");
//httpConn.setRequestProperty("Content-Language", "en-US"); //language to use.
//setRequestProperty("Connection", "close") ===> could generate or Solve IOExceptions on different mobile Phones.
//httpConn.setRequestProperty("Connection", "close");
//setting the Content-length could have issues with some Servers===>
//if the dataToSend is Empty String => contentLen = 0 , else get length of the dataBytes.
String contentLen = ((dataToSend.length() > 0) ? Integer.toString(dataToSendBytes.length) : Integer.toString(0));
//httpConn.setRequestProperty("Content-length", contentLen); //not working on Emulator ....enable on shipping application.
//open the output Stream to send data to the Server.
outStream = httpConn.openOutputStream();
// send the bytes of data to the Server.===>
//outStream.write(dataToSendBytes);
//send the data bytes to the Server.
int byteLen = dataToSendBytes.length; //length of byteToSend.
for (int k = 0; k < byteLen; k++) {
//send all the databytes to the Server.
outStream.write(dataToSendBytes[k]);
}
//close the outputStream ===immediately after sending the data bytes to the Server===>eliminates the IOExceptions.
closeOutStream(outStream);
//get response code on Sending Data===> getting response code automatically flushes the output data.
ntworkResponseCode = httpConn.getResponseCode();
if (ntworkResponseCode == HttpConnection.HTTP_OK) {
//connection to the Server was okay.
if (httpConn != null) {
//read the Response From the Server-----------
inputStream = httpConn.openInputStream(); // open the inputStream.
//get server Response Content length.
int contLen = (int) httpConn.getLength();
byte[] serverResponseBytes; //byte array to store the serverResponse.
if (contLen != -1) {
//store the serverResponse to a byte array.===> using a byte buffer could be faster.
serverResponseBytes = new byte[contLen];
inputStream.read(serverResponseBytes);
//convert the bytes to String and store them to the StringBuffer.
sb.append(new String(serverResponseBytes));
} else {
//serverResponse Length not available===> read character by character could be slower.
int read;
while ((read = inputStream.read()) != -1) {
sb.append((char) read);
}
}
//store the server response in a String.
strResponse = sb.toString();
}
} else {
//connection problem occured.
//throw new IOException("Http Response Code [" + ntworkResponseCode + "]");
}
}// the httpConnection Not null.--end.
} catch (IllegalArgumentException arge) {
strResponse = CONNECTION_EXCEPTION;
} catch (ConnectionNotFoundException cone) {
//a string to show we got an exception
strResponse = CONNECTION_EXCEPTION;
} catch (IOException ioe) {
//a string to show we got an exception
strResponse = CONNECTION_EXCEPTION;
} catch (SecurityException se) {
//user cancelled the Connection Request.
strResponse = CONNECTION_EXCEPTION;
} finally {
//close all the connection streams
try {
if (inputStream != null) {
//close the inputStream
inputStream.close();
inputStream = null;
}
if (outStream != null) {
//close the outStream.
outStream.close();
outStream = null;
}
if (httpConn != null) {
//close the connection object.
httpConn.close();
httpConn = null;
}
} catch (IOException ie) {
//show exception occured.
}
}
//return server Response to the Client.
return strResponse;
}

How to get DateTime from the internet?

How to get current date and time from internet or server using C#? I am trying to get time as follows:
public static DateTime GetNetworkTime (string ntpServer)
{
IPAddress[] address = Dns.GetHostEntry(ntpServer).AddressList;
if (address == null || address.Length == 0)
throw new ArgumentException("Could not resolve ip address from '" + ntpServer + "'.", "ntpServer");
IPEndPoint ep = new IPEndPoint(address[0], 123);
return GetNetworkTime(ep);
}
I am passing server IP address as netServer, but it does not work properly.
Here is code sample that you can use to retrieve time from NIST Internet Time Service
var client = new TcpClient("time.nist.gov", 13);
using (var streamReader = new StreamReader(client.GetStream()))
{
var response = streamReader.ReadToEnd();
var utcDateTimeString = response.Substring(7, 17);
var localDateTime = DateTime.ParseExact(utcDateTimeString, "yy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
}
Here is a quick code to get the time from the header, works without the need of port 13
public static DateTime GetNistTime()
{
var myHttpWebRequest = (HttpWebRequest)WebRequest.Create("http://www.microsoft.com");
var response = myHttpWebRequest.GetResponse();
string todaysDates = response.Headers["date"];
return DateTime.ParseExact(todaysDates,
"ddd, dd MMM yyyy HH:mm:ss 'GMT'",
CultureInfo.InvariantCulture.DateTimeFormat,
DateTimeStyles.AssumeUniversal);
}
Things could go wrong. All implements of the code founded above are prone to errors. Sometimes, it works and sometimes it trows a WebExpection error message.
A better implementation:
try{
using (var response =
WebRequest.Create("http://www.google.com").GetResponse())
//string todaysDates = response.Headers["date"];
return DateTime.ParseExact(response.Headers["date"],
"ddd, dd MMM yyyy HH:mm:ss 'GMT'",
CultureInfo.InvariantCulture.DateTimeFormat,
DateTimeStyles.AssumeUniversal);
}
catch (WebException)
{
return DateTime.Now; //In case something goes wrong.
}
Conclusion:
Having your web app depend on a service that provides accurate date information is critical. I have used one of the code founded here in my app and it really mess things up.
One more version of the same idea:
public static class InternetTime
{
public static DateTimeOffset? GetCurrentTime()
{
using (var client = new HttpClient())
{
try
{
var result = client.GetAsync("https://google.com",
HttpCompletionOption.ResponseHeadersRead).Result;
return result.Headers.Date;
}
catch
{
return null;
}
}
}
}
Here HttpCompletionOption.ResponseHeadersRead is used to prevent loading of the rest of the response, as we need only HTTP headers.
Use InternetTime.GetCurrentTime().Value.ToLocalTime() to get current local time.
Important: first check the avaible servers on
NIST Internet Time Servers.
public static DateTime GetServerTime()
{
var result = DateTime.Now;
// Initialize the list of NIST time servers
// http://tf.nist.gov/tf-cgi/servers.cgi
string[] servers = new string[] {
"time-c.nist.gov",
"time-d.nist.gov",
"nist1-macon.macon.ga.us",
"wolfnisttime.com",
"nist.netservicesgroup.com",
"nisttime.carsoncity.k12.mi.us",
"nist1-lnk.binary.net",
"wwv.nist.gov",
"time.nist.gov",
"utcnist.colorado.edu",
"utcnist2.colorado.edu",
"nist-time-server.eoni.com",
"nist-time-server.eoni.com"
};
Random rnd = new Random();
foreach (string server in servers.OrderBy(x => rnd.NextDouble()).Take(9))
{
try
{
// Connect to the server (at port 13) and get the response. Timeout max 1second
string serverResponse = string.Empty;
var tcpClient = new TcpClient();
if (tcpClient.ConnectAsync(server, 13).Wait(1000))
{
using (var reader = new StreamReader(tcpClient.GetStream()))
{
serverResponse = reader.ReadToEnd();
}
}
// If a response was received
if (!string.IsNullOrEmpty(serverResponse))
{
// Split the response string ("55596 11-02-14 13:54:11 00 0 0 478.1 UTC(NIST) *")
string[] tokens = serverResponse.Split(' ');
// Check the number of tokens
if (tokens.Length >= 6)
{
// Check the health status
string health = tokens[5];
if (health == "0")
{
// Get date and time parts from the server response
string[] dateParts = tokens[1].Split('-');
string[] timeParts = tokens[2].Split(':');
// Create a DateTime instance
DateTime utcDateTime = new DateTime(
Convert.ToInt32(dateParts[0]) + 2000,
Convert.ToInt32(dateParts[1]), Convert.ToInt32(dateParts[2]),
Convert.ToInt32(timeParts[0]), Convert.ToInt32(timeParts[1]),
Convert.ToInt32(timeParts[2]));
// Convert received (UTC) DateTime value to the local timezone
result = utcDateTime.ToLocalTime();
return result;
// Response successfully received; exit the loop
}
}
}
}
catch
{
// Ignore exception and try the next server
}
}
return result;
}
public static Nullable<DateTime> GetDateTime()
{
Nullable<DateTime> dateTime = null;
System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create("http://www.microsoft.com");
request.Method = "GET";
request.Accept = "text/html, application/xhtml+xml, */*";
request.UserAgent = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)";
request.ContentType = "application/x-www-form-urlencoded";
request.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore);
try
{
System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string todaysDates = response.Headers["date"];
dateTime = DateTime.ParseExact(todaysDates, "ddd, dd MMM yyyy HH:mm:ss 'GMT'",
System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat, System.Globalization.DateTimeStyles.AssumeUniversal);
}
}
catch
{
dateTime = null;
}
return dateTime;
}

Resources