Calling api by proxy takes 15+seconds - c#

In C # application, when calling API interface, it often takes 15+ seconds to access. API is deployed in another network segment of intranet and needs to be accessed by proxy. Some one said that it was a DNS problem, try to setting the host, which has no effect.
Environment: Windows Server 2012 R2, IIS v8.5
Code Script:
private string PostHttp(string url, string authHeader, string requestBody)
{
var webRequest = System.Net.WebRequest.Create(url);
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckValidationResult);
byte[] data = System.Text.Encoding.UTF8.GetBytes(requestBody);
webRequest.Method = "POST";
webRequest.Headers.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");
webRequest.Headers.Add("Accept-Encoding", "gzip, deflate");
webRequest.Headers.Add("Authorization", authHeader);
webRequest.ContentLength = data.Length;
webRequest.ContentType = "application/x-www-form-urlencoded";
System.Net.WebProxy proxy = new System.Net.WebProxy("http://myHttpProxyAddress", false);
proxy.Credentials = new System.Net.NetworkCredential("HttpProxyUser", "HttpProxyPassword");
webRequest.Proxy = proxy;
var writer = webRequest.GetRequestStream();
writer.Write(data, 0, data.Length);
writer.Close();
using (WebResponse webResponse = webRequest.GetResponse())
{
System.IO.StreamReader reader = null;
if (webResponse.Headers["Content-Encoding"] == "gzip")
reader = new System.IO.StreamReader(new GZipStream(webResponse.GetResponseStream(), CompressionMode.Decompress), System.Text.Encoding.UTF8);
else
reader = new System.IO.StreamReader(webResponse.GetResponseStream(), System.Text.Encoding.UTF8);
var result = reader.ReadToEnd();
reader.Close();
return result;
}
}

it's very difficult to point out by just hearing someone said one of the possibility (e.g DNS error) , try to use some http utility (e.g Curl) to check and measure that.
you can wrap the request above with below this guide and measure the timing detail.
How do I measure request and response times at once using cURL?

Related

Connecting to Tibco using Generated Soap WSDL

I have a WSDL generated from Tibco, the WSDL can be imported and run under SoapUI and I can connect without any issue with HTTPS even without Certificate however tried connecting to the same Endpoint using c# I can not connect with the following Code:
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.KeepAlive = true;
req.Accept = "gzip,deflate";
req.Headers.Add("SOAPAction", soapActionHeader);
req.ContentType = "text/xml;charset=UTF-8";
req.Method = "POST";
req.Timeout = requestTimeOut;
#endregion
#region Adding XML body to request
Stream strm = null;
using (var streamWriter = new StreamWriter(req.GetRequestStream()))
{
streamWriter.Write(xmlSOAPTemplate);
streamWriter.Flush();
streamWriter.Close();
}
#endregion
#region HTTP RESPONSE
string resultValue = string.Empty;
WebResponse resp = req.GetResponse();
strm = resp.GetResponseStream();
StreamReader streamReader = new StreamReader(strm);
string res = streamReader.ReadToEnd();
ExceptionHandler.WriteLog($"{url}:Response:{res}", MethodBase.GetCurrentMethod().Name);
XmlSerializer serializer = new XmlSerializer(typeof(T));
result = (T)serializer.Deserialize(strm);
So, How can we solve this issue?
what is the error you're getting ?
Your code seems to manipulate pure HTTP API, while you should use a library that invoke SOAP over HTTP.
I'm no C# programmer, but I googled the subject and found this example (see step 7) :
https://www.c-sharpcorner.com/UploadFile/88b6e5/how-to-call-web-service-in-android-using-soap/
SOAP can be fairly complex (and especially if you use TIBCO Business Works to produce it with an entreprise project behind), calling it with HTTP API will be complicated.

Integration of Rightmove Real Time Data Feed (RTDF) asp.net

i am integrating rightmove real time data feed (rtdf) in my property site for listing my properties on rightmove website. i am using asp.net web api to post data on rightmove listing.
they have provide me with these SSL Files [.p12,.pem,.jks]. i have imported .p12 certificate in my local machine personal store and sending it in my http request
to rightmove test api link provide by rightmove.
i am getting the following error from server.
The remote server returned an error: 403 forbidden.
i checked my certificate loaded successfully in the request, below is my code
public static string PostData(string data, string url)
{
String result = "";
try
{
byte[] bytebuffer = Encoding.UTF8.GetBytes(data);
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
objRequest.Method = "POST";
objRequest.ContentLength = bytebuffer.Length;
objRequest.ContentType = "application/json";
objRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0";
objRequest.PreAuthenticate = true;
objRequest.Accept = "application/json";
objRequest.ClientCertificates.Add(CertificateHelper.GetRightmoveApiX509Certificate());
using (Stream stream = objRequest.GetRequestStream())
{
stream.Write(bytebuffer, 0, bytebuffer.Length);
stream.Close();
}
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
using (StreamReader streamReader = new StreamReader(objResponse.GetResponseStream()))
{
result = streamReader.ReadToEnd();
// Close and clean up the StreamReader
streamReader.Close();
}
}
catch (Exception e)
{
result = "Exception: " + e.Message;
}
return result;
}
help me to get rid from 403 forbidden error.
Use the following.
I have tested it and it's working fine in my case.
// Grab Certificate
X509Certificate2 cert2 = new X509Certificate2(
AppDomain.CurrentDomain.BaseDirectory + "CertificateName.p12",
CertificatePasswordHere,
X509KeyStorageFlags.MachineKeySet);
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://adfapi.adftest.rightmove.com/v1/property/sendpropertydetails");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
httpWebRequest.ClientCertificates.Clear();
httpWebRequest.ClientCertificates.Add(cert2);
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(data);
streamWriter.Flush();
streamWriter.Close();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}

C# Siteminder Authentication

I am trying to write some code to connect to an HTTPS site that uses Siteminder authentication.
I keep getting a 401. Any ideas?
I have read a few different things on here but none have really seemed all that helpful. I am also using Fiddler/Firefox Tamper to snoop what's going on.
Here is what I've got so far in regards to code:
try
{
Uri uri = new Uri("https://websiteaddresshere");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri) as HttpWebRequest;
request.Accept = "text/html, application/xhtml+xml, */*";
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko";
// request.Connection = "Keep-Alive";
// request.Method = "Get";
// request.Accept = "text";
request.AllowAutoRedirect = true;
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
Cookie emersoncookie = new Cookie("SMCHALLENGE", "YES");
emersoncookie.Domain = "mydomain";
emersoncookie.Path = "/";
// authentication
var cache = new CredentialCache();
cache.Add(uri, "False", new NetworkCredential("myusername", "mypassword"));
request.Credentials = cache;
// response.
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
XmlTextReader reader = new XmlTextReader(stream);
MessageBox.Show(stream.ToString());
}
}
}
catch (WebException exception)
{
string responseText;
using (var reader = new StreamReader(exception.Response.GetResponseStream()))
{
responseText = reader.ReadToEnd();
MessageBox.Show(responseText.ToString());
}
}
After doing some more reading on the MSDN website I decided to go a different route.
I ended up making this a service since it will need to be a service at the end of the day and did the following:
CookieContainer emersoncookie = new CookieContainer();
HttpWebRequest request = (HttpWebRequest)
WebRequest.Create("https://websiteaddress");
request.Credentials = new NetworkCredential("username", "password");
request.CookieContainer = emersoncookie;
request.Method = "GET";
HttpWebResponse response = (HttpWebResponse)
request.GetResponse();
Stream resStream = response.GetResponseStream();
using (Stream output = File.OpenWrite(#"c:\\somefolder\\somefile.someextention"))
using (Stream input = resStream)
{
input.CopyTo(output);
}
To anyone that might be running into Siteminder authentication issues, this piece of code works pretty well.
I couldn't get Jasen's code to work. Maybe your SM setup is different from mine. But with SiteMinder it's generally a two step authentication process. The code block below works for me:
//Make initial request
RestClient client = new RestClient("http://theResourceDomain/myApp");
client.CookieContainer = new CookieContainer();
IRestResponse response = client.Get(new RestRequest("someProduct/orders"));
//Now add credentials.
client.Authenticator = new HttpBasicAuthenticator("username", "password");
//Get resource from the SiteMinder URI which will redirect to the correct API URI upon authentication.
response = client.Get(new RestRequest(response.ResponseUri));
Although this uses RestSharp, it can be easily replicated using HttpClient or even HttpWebRequest.

HttpWebRequest get 404 page only when using POST mode

First of all: I know this has been asked over 100 times, but most of these questions were eigher caused by timeout problems, by incorrect Url or by foregetting to close a stream (and belive me, I tried ALL the samples and none of them worked).
So, now to my question: in my Windows Phone app I'm using the HttpWebRequest to POST some data to a php web service. That service should then save the data in some directories, but to simplify it, at the moment, it only echos "hello".
But when I use the following code, I always get a 404 complete with an apache 404 html document. Therefor I think I can exclude the possibility of a timeout. It seems like the request reaches the server, but for some reason, a 404 is returned. But what really makes me be surprised is, if I use a get request, everything works fine. So here is my code:
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.CreateHttp(server + "getfeaturedpicture.php?randomparameter="+ Environment.TickCount);
webRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0";
webRequest.Method = "POST";
webRequest.ContentType = "text/plain; charset=utf-8";
StreamWriter writer = new StreamWriter(await Task.Factory.FromAsync<Stream>(webRequest.BeginGetRequestStream, webRequest.EndGetRequestStream, null));
writer.Write(Encoding.UTF8.GetBytes("filter=" + Uri.EscapeDataString(filterML)));
writer.Close();
webRequest.BeginGetResponse(new AsyncCallback((res) =>
{
string strg = getResponseString(res);
Stator.mainPage.Dispatcher.BeginInvoke(() => { MessageBox.Show(strg); });
}), webRequest);
Although I don't think this is the reason, here's the source of getResponseString:
public static string getResponseString(IAsyncResult asyncResult)
{
HttpWebRequest webRequest = (HttpWebRequest)asyncResult.AsyncState;
HttpWebResponse webResponse;
try
{
webResponse = (HttpWebResponse)webRequest.EndGetResponse(asyncResult);
}
catch (WebException ex)
{
webResponse = ex.Response as HttpWebResponse;
}
MemoryStream tempStream = new MemoryStream();
webResponse.GetResponseStream().CopyTo(tempStream);
tempStream.Position = 0;
webResponse.Close();
return new StreamReader(tempStream).ReadToEnd();
}
This is tested code work fine in Post method with some body. May this gives you an idea.
public void testSend()
{
try
{
string url = "abc.com";
string str = "test";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
req.ContentType = "text/plain; charset=utf-8";
req.BeginGetRequestStream(SendRequest, req);
}
catch (WebException)
{
}
}
//Get Response and write body
private void SendRequest(IAsyncResult asyncResult)
{
string str = "test";
string Data = "data=" + str;
HttpWebRequest req= (HttpWebRequest)asyncResult.AsyncState;
byte[] postBytes = Encoding.UTF8.GetBytes(Data);
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = postBytes.Length;
Stream requestStream = req.GetRequestStream();
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Close();
request.BeginGetResponse(SendResponse, req);
}
//Get Response string
private void SendResponse(IAsyncResult asyncResult)
{
try
{
MemoryStream ms;
HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult);
HttpWebResponse httpResponse = (HttpWebResponse)response;
string _responestring = string.Empty;
using (Stream data = response.GetResponseStream())
using (var reader = new StreamReader(data))
{
_responestring = reader.ReadToEnd();
}
}
catch (WebException)
{
}
}
I would suggest you to use RestSharp for your POST requests in windows phone. I am making an app for a startup and i faced lots of problems while using a similar code as yours. heres an example of a post request using RestSharp. You see, instead of using 3 functions it can be done in a more concise form. Also the response can be handled efficiently. You can get RestSharp from Nuget.
RestRequest request = new RestRequest("your url", Method.POST);
request.AddParameter("key", value);
RestClient restClient = new RestClient();
restClient.ExecuteAsync(request, (response) =>
{
if (response.StatusCode == HttpStatusCode.OK)
{
StoryBoard2.Begin();
string result = response.Content;
if (result.Equals("success"))
message.Text = "Review submitted successfully!";
else
message.Text = "Review could not be submitted.";
indicator.IsRunning = false;
}
else
{
StoryBoard2.Begin();
message.Text = "Review could not be submitted.";
}
});
It turned out the problem was on the server-side: it tried it on the server of a friend and it worked fine, there. I'll contact the support of the hoster and provide details as soon as I get a response.

Read the HTTP POST request of HttpWebRequest

I need to create Http POST requests and maybe a few GET requests as strings for some tests I am writing. Currently, my tests build them using a StringBuilder and hardcoded POST requests pulled out from fiddler kinda like this:
var builder = new StringBuilder();
builder.Append("POST https://some.web.pg HTTP/1.1\r\n");
builder.Append("Content-Type: application/x-www-form-urlencoded\r\n");
builder.Append("Referer: https://some.referer.com\r\n");
builder.Append("Accept-Language: en-us\r\n");
builder.Append("Accept-Encoding: gzip, deflate\r\n");
builder.Append("User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\n");
builder.Append("Host: login.yahoo.com\r\n");
// ... other header info
builder.Append("\r\n");
builder.Append("post body......\r\n");
var postData = builder.ToString();
This is quickly making my tests messy and would prefer to have a cleaner way to build these POST requests. I've been looking into HttpWebRequest class hoping that maybe it can create these for me. I figured that behind the sences it must have some way to construct this exact request I am trying to creating in some form or another. But alas, the GetRequestStream is a writable only stream.
Is there a way to read the request stream HttpWebRequest will generate (and then change it to a string)? Or even any ideas on how to generate these POST requests would do.
here an msdn sample to make a Get request:
using System;
using System.Net;
using System.IO;
namespace MakeAGETRequest_charp
{
///
/// Summary description for Class1.
///
class Class1
{
static void Main(string[] args)
{
string sURL;
sURL = "http://www.microsoft.com";
WebRequest wrGETURL;
wrGETURL = WebRequest.Create(sURL);
WebProxy myProxy = new WebProxy("myproxy",80);
myProxy.BypassProxyOnLocal = true;
wrGETURL.Proxy = WebProxy.GetDefaultProxy();
Stream objStream;
objStream = wrGETURL.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string sLine = "";
int i = 0;
while (sLine!=null)
{
i++;
sLine = objReader.ReadLine();
if (sLine!=null)
Console.WriteLine("{0}:{1}",i,sLine);
}
Console.ReadLine();
}
}
}
and here an for post request (from HTTP request with post)
HttpWebRequest httpWReq =
(HttpWebRequest)WebRequest.Create("http:\\domain.com\page.asp");
ASCIIEncoding encoding = new ASCIIEncoding();
string postData = "username=user";
postData += "&password=pass";
byte[] data = encoding.GetBytes(postData);
httpWReq.Method = "POST";
httpWReq.ContentType = "application/x-www-form-urlencoded";
httpWReq.ContentLength = data.Length;
using (Stream newStream = httpWReq.GetRequestStream())
{
newStream.Write(data,0,data.Length);
}
I advise you to use mocking because it is a best practice on unit test:
see this answer on stack
Unit testing HTTP requests in c#
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(yoururllink);
var c = HttpContext.Current;
//Set values for the request back
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
byte[] param = Request.BinaryRead(HttpContext.Current.Request.ContentLength);
string strRequest = Encoding.ASCII.GetString(param);
string strResponse_copy = strRequest; //Save a copy of the initial info sent from your url link
strRequest += "&cmd=_notify-validate";
req.ContentLength = strRequest.Length;
//for proxy
//WebProxy proxy = new WebProxy(new Uri("http://url:port#"));
//req.Proxy = proxy;
//Send the request to PayPal and get the response
StreamWriter streamOut = new StreamWriter(req.GetRequestStream(), System.Text.Encoding.ASCII);
streamOut.Write(strRequest);
streamOut.Close();
StreamReader streamIn = new StreamReader(req.GetResponse().GetResponseStream());
string strResponse = streamIn.ReadToEnd();
streamIn.Close();

Categories