C# - Sending and receiving HTTP Requests to REST service - c#

So I'm writing the client side user authentication code for my Web API ReST service.
This is how the request and response should look like and I've written this code to register a user and it works fine.
Http Request:
POST https://localhost:44305/api/Account/Register HTTP/1.1
Host: localhost:44305
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0
Accept: */*
Content-Type: application/json; charset=utf-8
X-Requested-With: XMLHttpRequest
Referer: https://localhost:44305/
Content-Length: 84
{"Email":"alice#example.com","Password":"Password1!","ConfirmPassword":"Password1!"}
Http Response:
HTTP/1.1 200 OK
Server: Microsoft-IIS/8.0
Date: Wed, 01 Oct 2014 00:57:58 GMT
Content-Length: 0
Code to accomplish this:
byte[] data = Encoding.UTF8.GetBytes("{\"Email\":\"alssice#example.com\"," + "\"Password\":\"Password1!\"," + "\"ConfirmPassword\":\"Password1!\"}");
WebRequest request = WebRequest.Create("http://localhost:8091/api/Account/Register");
request.Method = "POST";
request.ContentType = "application/json; charset=utf-8";
request.ContentLength = data.Length;
using (Stream stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
string responseContent = null;
using (WebResponse response = request.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
using (StreamReader sr99 = new StreamReader(stream))
{
responseContent = sr99.ReadToEnd();
}
}
}
Console.WriteLine(responseContent);
This works fine and the user account is created in the database but I don't get the response.
The next problem is sending sending the login details to get a bearer token? How can I do this?
This is what the request and response should look like
HTTP REQUEST FOR AUTHENTICATION:
POST https://localhost:44305/Token HTTP/1.1
Host: localhost:44305
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0
Accept: */*
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: https://localhost:44305/
Content-Length: 68
grant_type=password&username=alice%40example.com&password=Password1!
HTTP RESPONSE FOR AUTHENTICATION:
HTTP/1.1 200 OK
Content-Length: 669
Content-Type: application/json;charset=UTF-8
Server: Microsoft-IIS/8.0
Date: Wed, 01 Oct 2014 01:22:36 GMT
{
"access_token":"imSXTs2OqSrGWzsFQhIXziFCO3rF...",
"token_type":"bearer",
"expires_in":1209599,
"userName":"alice#example.com",
".issued":"Wed, 01 Oct 2014 01:22:33 GMT",
".expires":"Wed, 15 Oct 2014 01:22:33 GMT"
}
SO how can I send a request for a token?

I'd kindly like to suggest you using HttpClient if you're going for your own http rest client in your app.
Solution using HttpClient and Json.net:
public class TokenResponse
{
public string access_token { get; set; }
public string token_type { get; set; }
public int expires_in { get; set; }
public string userName { get; set; }
public string issued { get; set; }
public string expires { get; set; }
}
private async Task Login()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://localhost:44305");
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("username", "alice#example.com"),
new KeyValuePair<string, string>("password", "password1")
});
var result = await client.PostAsync("/token", content);
string resultContent = await result.Content.ReadAsStringAsync();
var tokenResponse = JsonConvert.DeserializeObject<TokenResponse>(resultContent);
}
}
And if you need to use HttpWebRequest:
If this is the case, your solution might look something like the following.
private void Login()
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("https://localhost:44305/Token");
request.Method = "POST";
request.AllowAutoRedirect = false;
request.Accept = "*/*";
request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
StringBuilder postData = new StringBuilder();
postData.Append("grant_type=" + HttpUtility.UrlEncode("password") + "&");
postData.Append("username=" + HttpUtility.UrlEncode("alice#example.com") + "&");
postData.Append("password=" + HttpUtility.UrlEncode("password"));
using (StreamWriter stOut = new StreamWriter(request.GetRequestStream(), Encoding.UTF8))
{
stOut.Write(postData);
stOut.Close();
}
}
Update
Now Im not sure where and how you are trying this. If you're invoking this from a console application main method, make sure the following so you don't have to come back to the same asynchronous context and this should always be invoked from an async method itself:
var result = await client.PostAsync("https://localhost:44305/token", content).ConfigureAwait(false);
I updated my solution in a github gist. It's working for me as it's trying to post the request right away.

Related

Restful call returns Bad Request. Success in RestSharp. Failed with HttpClient/HttpWebRequest

Alright! So I have this Restful call that i am trying to make to a Polycom device.
To sort of isolate within this code I used RestSharp and it works fine. Also removing the credentials object or altering it makes it kick back an unauthorized so i believe authorization is fine. I think its the body/parameters that are incorrect.
//THIS SECTION WORKS
//RestRequest restRequest = new RestRequest();
//restRequest.AddJsonBody(body);
//RestClient restClient = new RestClient(targetUrl);
//restClient.RemoteCertificateValidationCallback = (sPoint, cert, wRequest, certProb) => true;
//restClient.Authenticator = new HttpBasicAuthenticator(username, deskPhone.MACPassword);
//IRestResponse restsharpResponse = await restClient.ExecutePostAsync(restRequest).ConfigureAwait(false);
//END SECTION
What my issue is.. I have no idea why I am getting an error 400 Bad Request. When I look at what I have in the call it all seems to align correctly. The Auth token is the same as RestSharp and the body is the same object.
I really am at a loss for what i can do and unfortunately I cant use restsharp i need to use what is available in Net Core.
I have a few different implementations in the code as you can see below. I attempted with HttpClient and I attempted with HttpWebRequest.
My question is... What likely bug do i have that is preventing this from being a proper request.
This link here is to API documentation which I also seem to be aligning with correctly.
https://support.polycom.com/content/dam/polycom-support/products/voice/polycom-uc/other-documents/en/2018/ucsoftware-restapi.pdf
[HttpPost]
[Route("[action]")]
public async Task PhoneNumberStuff(long userId)
{
DeskPhone deskPhone = DbContext.DeskPhones
.Include(x=>x.DeskPhoneUser)
.FirstOrDefault(x => x.DeskPhoneUserId == 11546);
string targetUrl = $"https://{deskPhone.IPv4Address}/api/v1/callctrl/dial";
string certLcation = #"C:\Users\AlexRoundy\Desktop\Polycom.cer";
string username = "Polycom";
SecureString password = new NetworkCredential("", deskPhone.MACPassword).SecurePassword;
String encoded = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + deskPhone.MACPassword));
//$cred = New - Object System.Management.Automation.PSCredential($username,$password)
NetworkCredential credential = new NetworkCredential(username, password);
string body = #"{""data"":{""Dest"": ""7168675309"", ""Line"": ""1"",""Type"": ""TEL"" } }";
//THIS SECTION WORKS
//RestRequest restRequest = new RestRequest();
//restRequest.AddJsonBody(body);
//RestClient restClient = new RestClient(targetUrl);
//restClient.RemoteCertificateValidationCallback = (sPoint, cert, wRequest, certProb) => true;
//restClient.Authenticator = new HttpBasicAuthenticator(username, deskPhone.MACPassword);
//IRestResponse restsharpResponse = await restClient.ExecutePostAsync(restRequest).ConfigureAwait(false);
//END SECTION
HttpClientHandler handler = new HttpClientHandler();
//handler.SslProtocols = System.Security.Authentication.SslProtocols.Tls11;
handler.ServerCertificateCustomValidationCallback = (sPoint, cert, wRequest, certProb) => true;
//handler.CheckCertificateRevocationList = false;
handler.Credentials = credential;
//handler.ClientCertificateOptions = ClientCertificateOption.Manual;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(targetUrl);
request.ServerCertificateValidationCallback = (sPoint, cert, wRequest, certProb) => true;
request.ContentType = "application/json; charset=utf-8";
request.Method = "POST";
request.Headers.Add("Authorization", "Basic " + encoded);
request.AuthenticationLevel = System.Net.Security.AuthenticationLevel.None;
request.Accept = "application/json";
using (StreamWriter streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(body);
streamWriter.Flush();
}
HttpWebResponse httpResponse = (HttpWebResponse)request.GetResponse();
string responseText;
using (StreamReader streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
responseText = streamReader.ReadToEnd();
}
HttpClient httpClient = new HttpClient(handler);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
StringContent temp = new StringContent(body, Encoding.UTF8, "application/json");
HttpRequestMessage httpMessage = new HttpRequestMessage(HttpMethod.Post, targetUrl);
httpMessage.Content = temp;
HttpResponseMessage testA = await httpClient.SendAsync(httpMessage).ConfigureAwait(false);
HttpResponseMessage stuff = await httpClient.PostAsync(targetUrl, temp).ConfigureAwait(false);
handler.Dispose();
httpMessage.Dispose();
httpClient.Dispose();
}
So below are the two comparisons from fiddler.
The problem child is this line here.
request.ContentType = "application/json; charset=utf-8";
The fix??
request.ContentType = "application/json";
The following below is the fiddler results that led to the discovery.
POST https://192.168.50.76/api/v1/callctrl/dial HTTP/1.1
Authorization: Basic UG9seWNvbTp3TUh0bDNKdA==
Accept: application/json, text/json, text/x-json, text/javascript, application/xml, text/xml
User-Agent: RestSharp/106.11.4.0
Connection: Keep-Alive
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 60
Host: 192.168.50.76
{"data":{"Dest": "7164171568", "Line": "1","Type": "TEL" } }
POST https://192.168.50.76/api/v1/callctrl/dial HTTP/1.1
Authorization: Basic UG9seWNvbTp3TUh0bDNKdA==
Accept: application/json, text/json, text/x-json, text/javascript, application/xml, text/xml
User-Agent: FauxPaux
Connection: Keep-Alive
Accept-Encoding: deflate
Content-Type: application/json;
Content-Length: 60
Host: 192.168.50.76
{"data":{"Dest": "7164171568", "Line": "1","Type": "TEL" } }

Emulating a web page form POST submission through C#

I'm trying to write a C# script that in effect does the same thing as when I submit a form through the UI of a certain webpage. This is on a public page of a site that doesn't use cookies. I looked in Chrome at the Network tab for what happens in the request/response when I submit a comment
and I'm trying to emulate that in C# land:
CommentFormData data = CommentFormData.GenerateRandom();
string json = new JavaScriptSerializer().Serialize(data);
StringContent content = new StringContent(json, Encoding.UTF8);
content.Headers.TryAddWithoutValidation("Accept", "text/javascript, text/html, application/xml, text/xml, */*");
content.Headers.TryAddWithoutValidation("Accept-Encoding", "gzip, deflate, br");
content.Headers.TryAddWithoutValidation("Accept-Language", "en-US,en;q=0.8");
content.Headers.TryAddWithoutValidation("Connection", ";eep-alive");
content.Headers.TryAddWithoutValidation("Content-Length", json.Length.ToString());
content.Headers.TryAddWithoutValidation("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
content.Headers.TryAddWithoutValidation("Host", "...");
content.Headers.TryAddWithoutValidation("Origin", "...");
content.Headers.TryAddWithoutValidation("Referer", "...);
content.Headers.TryAddWithoutValidation("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
content.Headers.TryAddWithoutValidation("X-Prototype-Version", "1.6.1");
content.Headers.TryAddWithoutValidation("X-Requested-With", "XMLHttpRequest");
HttpResponseMessage response = await client.PostAsync("...", content);
.....
internal class CommentFormData
{
public string pageID { get; } = "...";
public string comment { get; set; }
public string author { get; set; }
public string email { get; set; }
public int timezone { get; } = -7;
public static CommentFormData GenerateRandom()
{
return new CommentFormData()
{
comment = GenerateRandomString(),
author = GenerateRandomString(),
email = $"{GenerateRandomString()}#gmail.com"
};
}
private static string GenerateRandomString(int length = 100)
{
Random random = new Random();
return new string(Enumerable.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", length)
.Select(s => s[random.Next(s.Length)]).ToArray());
}
}
I am getting back status code 200, but it's not working the same. The response I'm getting is
StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Transfer-Encoding: chunked
Connection: keep-alive
Keep-Alive: timeout=20
Vary: Accept-Encoding
Date: Sat, 10 Jun 2017 20:44:36 GMT
Server: nginx
Content-Type: text/xml; charset=utf-8
}
so why isn't this working? Any ideas?
I think you should look at the System.Net.Http.HttpsClient class: https://msdn.microsoft.com/en-us/library/system.net.http.httpclient(v=vs.118).aspx
Use this calss to construct and execute requests asynchronously, and read the contents of their responses.

Access website with C# POST

I am trying to access the data on a website using some C# code. From a browser, a user would go to http://www.hkexnews.hk/sdw/search/search_sdw.asp, put in a date (17 May 2016) and a stock code ("00001") and be taken to a table with the relevant data.
I have used a Firefox add-on (LiveHTTPHeaders) to see that this process produces the following POST request:
http://www.hkexnews.hk/sdw/search/search_sdw.asp
POST /sdw/search/search_sdw.asp HTTP/1.1
Host: www.hkexnews.hk
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://www.hkexnews.hk/sdw/search/search_sdw.asp
Cookie: ASPSESSIONIDCASQQTQQ=FOLELNMCLAOEPAAEMIICCPAN; TS0161f2e5=017038eb4956ab204b9c8ba8c23ae9307c7879ba5fccd4664528a1407b7fab58353e89b27052a3d4d4df3b4b47034b5a31085f2c11
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 341
txt_today_d=20&txt_today_m=5&txt_today_y=2016&current_page=1&stock_market=HKEX&IsExist_Slt_Stock_Id=False&IsExist_Slt_Part_Id=False&rdo_SelectSortBy=Shareholding&sessionToken=1458.568&sel_ShareholdingDate_d=17&sel_ShareholdingDate_m=05&sel_ShareholdingDate_y=2016&txt_stock_code=00001&txt_stock_name=&txt_ParticipantID=&txt_Participant_name=
HTTP/1.1 200 OK
Cache-Control: private
Pragma: No-Cache
Content-Length: 300802
Content-Type: text/html
Expires: 0
X-Powered-By: ASP.NET
Date: Fri, 20 May 2016 04:58:57 GMT
My code:
string PostData = "txt_today_d=20&txt_today_m=5&txt_today_y=2016&current_page=1&stock_market=HKEX&IsExist_Slt_Stock_Id=False&IsExist_Slt_Part_Id=False&rdo_SelectSortBy=Shareholding&sessionToken=1458.568&sel_ShareholdingDate_d=17&sel_ShareholdingDate_m=05&sel_ShareholdingDate_y=2016&txt_stock_code=00001&txt_stock_name=&txt_ParticipantID=&txt_Participant_name=";
byte[] ByteArray = Encoding.UTF8.GetBytes(PostData);
HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("http://www.hkexnews.hk/sdw/search/search_sdw.asp");
Uri Target = new Uri("http://www.hkexnews.hk/sdw/search/search_sdw.asp");
Request.Method = "POST";
Request.Host = "www.hkexnews.hk";
Request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0";
Request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
WebHeaderCollection Headers = Request.Headers;
Headers.Add("Accept-Language", "en-US,en;q=0.5");
Headers.Add("Accept-Encoding", "gzip, deflate");
Request.Referer = "http://www.hkexnews.hk/sdw/search/search_sdw.asp";
Request.CookieContainer = new CookieContainer();
Request.CookieContainer.Add(new Cookie("ASPSESSIONIDCASQQTQQ", "FOLELNMCLAOEPAAEMIICCPAN") { Domain = Target.Host });
Request.CookieContainer.Add(new Cookie("TS0161f2e5", "017038eb49a575136721aebc3f3ef14ec9c810d2e25d5e909be6fe49639ec38eec624237bf9759851675d091f3a4ed0ebc3d8bb3d2") { Domain = Target.Host });
Request.KeepAlive = true;
Request.ContentType = "Content-Type: application/x-www-form-urlencoded";
Request.ContentLength = ByteArray.Length;
Stream dataStream = Request.GetRequestStream();
// Write the data to the request stream.
dataStream.Write(ByteArray, 0, ByteArray.Length);
// Close the Stream object.
dataStream.Close();
// Get the response.
WebResponse response = Request.GetResponse();
// Display the status.
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
// Get the stream containing content returned by the server.
dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
Console.WriteLine(responseFromServer);
// Clean up the streams.
reader.Close();
dataStream.Close();
response.Close();
What this code appears to do is simply spit out the Html of the original search screen instead of taking me to the results.
Edit: I also tried doing the same with the HttpClient class, as below:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://www.hkexnews.hk/sdw/search/search_sdw.asp");
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("txt_today_d", "20"),
new KeyValuePair<string, string>("txt_today_m", "5"),
new KeyValuePair<string, string>("txt_today_y", "2016"),
new KeyValuePair<string, string>("current_page", "1"),
new KeyValuePair<string, string>("stock_market", "HKEX"),
new KeyValuePair<string, string>("IsExist_Slt_Stock_Id", "False"),
new KeyValuePair<string, string>("IsExist_Slt_Part_Id", "False"),
new KeyValuePair<string, string>("rdo_SelectSortBy", "Shareholding"),
new KeyValuePair<string, string>("sessionToken", "1458.568"),
new KeyValuePair<string, string>("sel_ShareholdingDate_d", "17"),
new KeyValuePair<string, string>("sel_ShareholdingDate_m", "05"),
new KeyValuePair<string, string>("sel_ShareholdingDate_y", "2016"),
new KeyValuePair<string, string>("txt_stock_code", "00001"),
new KeyValuePair<string, string>("txt_stock_name", ""),
new KeyValuePair<string, string>("txt_ParticipantID", ""),
new KeyValuePair<string, string>("txt_Participant_name", "")
});
var result = client.PostAsync("/sdw/search/search_sdw.asp", content).Result;
string resultContent = result.Content.ReadAsStringAsync().Result;
Console.WriteLine(resultContent);
This produces the same result (Html of original form)
Because something wrong in your request(maybe cookie is not correct) and your request was redirected to original website.
HTTP/1.1 302 Object moved
Cache-Control: private
Pragma: No-Cache
Content-Length: 135
Content-Type: text/html
Expires: 0
Location: search_sdw.asp
X-Powered-By: ASP.NET
Date: Fri, 20 May 2016 07:58:52 GMT
<head><title>Object moved</title></head>
<body><h1>Object Moved</h1>This object may be found here.</body>

Logging into a website automatically in Visual C#? (No WebBrowser)

I am trying to log in to a website using Visual C# but I am not sure where to start. Eventually, I want to download a PDF File from the website but I must login to the website as it is password-restricted. The url is below:
https://sso.greatclips.com/authentication/login/login.aspx?ud=1&ApplicationCode=1&ReturnURL=https%3A%2F%2Fwww.salondata.com%2Fv2%2Fwa%2FloginPostBack
I am not sure if it is working. What are my options, and is the code even doing anything?
Here is my code so far. (Note: I do not want to browse the web in the Visual C# App, I want it done in the background)
public static Setup setup = new Setup();
private CookieContainer _jar = new CookieContainer();
public static string password = setup.Password;
public static string username = setup.UserName;
private string _url = "https://sso.greatclips.com/authentication/login/login.aspx";
private string _userAgent;
public Salons()
{
InitializeComponent();
}
private void Salons_Load_1(object sender, EventArgs e)
{
string responseData;
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(_url);
webRequest.CookieContainer = _jar;
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.UserAgent = _userAgent;
string requestBody = String.Format(
"client_id={0}&password={1}", username, password);
using (StreamWriter requestWriter = new StreamWriter(webRequest.GetRequestStream()))
{
requestWriter.Write(requestBody);
lblStatus.Text = "Writing request ...";
requestWriter.Close();
using (HttpWebResponse res = (HttpWebResponse)webRequest.GetResponse())
{
using (StreamReader responseReader = new StreamReader(res.GetResponseStream()))
{
responseData = responseReader.ReadToEnd();
responseReader.Close();
lblStatus.Text = "Closing request ...";
if (res.StatusCode != HttpStatusCode.OK)
throw new WebException("Logon failed", null, WebExceptionStatus.Success, res);
else
lblStatus.Text = "Successfully logged in!";
}
}
}
}
EDIT:
Request when I click on Sign In Button:
POST http://sso.greatclips.com/authentication/login/login.aspx?ud=1&ApplicationCode=1&ReturnURL=https%3a%2f%2fwww.salondata.com%2fv2%2fwa%2floginPostBack HTTP/1.1
Host: sso.greatclips.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:14.0) Gecko/20100101 Firefox/14.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
X-MicrosoftAjax: Delta=true
Cache-Control: no-cache, no-cache
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Referer: http://sso.greatclips.com/authentication/login/login.aspx?ud=1&ApplicationCode=1&ReturnURL=https%3A%2F%2Fwww.salondata.com%2Fv2%2Fwa%2FloginPostBack
Content-Length: 1331
Cookie: stayloggedin=399238; ASP.NET_SessionId=g3tf01mqzgcdbhyoagfz1s55; .ADAuthCookie=2496474AAA6C67DC05253300439E06151F94E728769EA71FBFDB0CD832E772DBA6F5B5220EF7A5C7E79ED7B445EB7DF6C39B9A1E276277BDD3DC9DF2756294157D57C1B926F919F3A87BDE0CDBA8F43E0C8989357A24372DEA39B973A53F89F0EDEE1E2D3B391A785B1AB19FB704B420BD95A5C3505765D51FA865565686F3CF0F74AFD2C2E76146AB14F46BC2E4B21189B721C32DF3A6466631D0326ABB0D95087FF9E2
Pragma: no-cache
ctl00%24ScriptManager1=ctl00%24UpdatePanel1%7Cctl00%24cphMain%24loginMain%24LoginButton&_EVENTTARGET=&_EVENTARGUMENT=&_VIEWSTATE=%2FwEPDwUKMjA3MDY5NDk2Ng9kFgJmD2QWBAIBD2QWBGYPZBYCZg9kFgICAQ8WAh4EVGV4dAUQUmVwb3J0aW5nIENlbnRlcmQCAg9kFgICAQ9kFgICAQ8WAh8ABRpzVGl0bGVCYWNrZ3JvdW5kPScjNUU3MUI2J2QCAw9kFgYCAw8PFgYeCEltYWdlVXJsBRppbWFnZXMvc3BlY3RydW1fYmFubmVyLmpwZx4NQWx0ZXJuYXRlVGV4dAUQUmVwb3J0aW5nIENlbnRlch4HVmlzaWJsZWdkZAIFD2QWAmYPZBYCAgEPDxYEHglCYWNrQ29sb3IJ%2FPz8%2Fx4EXyFTQgIIZBYCAgEPZBYCAgMPZBYCAgEPPCsACgEADxYCHghVc2VyTmFtZQUbc3VkZXNoLnNhcHJhQGdyZWF0Y2xpcHMubmV0ZBYCZg9kFgYCAQ8PFgIfAAUQUmVwb3J0aW5nIENlbnRlcmRkAgUPDxYCHwAFG3N1ZGVzaC5zYXByYUBncmVhdGNsaXBzLm5ldGRkAhkPDxYCHwAFGHdlYm1hc3RlckBncmVhdGNsaXBzLmNvbWRkAgkPDxYCHwAFEUNvcHlyaWdodCDCqSAyMDEyZGQYAQUeX19Db250cm9sc1JlcXVpcmVQb3N0QmFja0tleV9fFgEFJ2N0bDAwJGNwaE1haW4kbG9naW5NYWluJGNoa1N0YXlMb2dnZWRJbufuwcvYeS4gDjHhavP572TVdscK&_EVENTVALIDATION=%2FwEWCQL%2B5bxcAr2ailYCkqyM%2BQ0CtvDI7gECpJCinAICzoverwUCjqr%2B%2FAoCocjV5gcCybrK0QNROj0%2BEho3liuMeskLfe3LtC8Zog%3D%3D&ctl00%24cphMain%24loginMain%24UserName=*&ctl00%24cphMain%24loginMain%24UserName_TextBoxWatermarkExtender_ClientState=&ctl00%24cphMain%24loginMain%24Password=*&ctl00%24cphMain%24loginMain%24chkStayLoggedIn=on&__ASYNCPOST=true&ctl00%24cphMain%24loginMain%24LoginButton=Sign%20In
Couple things which can help you
(a) this url also works without SSL (so you will not have a deal with check the right certificate, etc), and for now you can just try to do this work with url http://sso.greatclips.com/authentication/login/login.aspx?ud=1&ApplicationCode=1&ReturnURL=https%3A%2F%2Fwww.salondata.com%2Fv2%2Fwa%2FloginPostBack (http instead of https)
(b) use fiddler tool which allows you to logs the traffic between browser and web server. Just take a look on request which browser sends to server when you click on Sign In button and try to implement the same request in C# code.

Truncated response received using HttpWebRequest

I'm using the following code to make HttpWebRequests to a web site:
public static HttpWebResponse SendGETRequest(string url, string agent, CookieContainer cookieContainer)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.UserAgent = agent;
request.Method = "GET";
request.ContentType = "text/html";
request.CookieContainer = cookieContainer;
return (HttpWebResponse)request.GetResponse();
}
Everything worked fine with several web pages until I tried with a new one and only received the last part of the page. This is the received response:
<tr>
<td colspan="2" height="5"><spacer type="block" width="100%" height="5"></td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
The header is correct and says that only the received data is sent. The following are the headers of the request and response:
Request:
GET /Broker/Ops/FichaContratoJS.asp?nc=815044&IP=5&YY=2012&M=6&St=0&CC=FESX201206 HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.168 Safari/535.19
Content-Type: text/html
Host: www.xxxx.com
Cookie: ASPSESSIONIDACBDCDBT=MGDNMNABOANDMILHBNCIDFCH;Autenticacion=Sid=230fae3d%2De0e2%2D4df1%2D8aa8%2D000fb352eaef&IdUsuarioWeb=xxxx; ASPSESSIONIDACBCCDAT=AFDJMNABAFJDDHABLOLAINDK; ASPSESSIONIDCADCBCAT=CEBJGNABLCALPJLDJFPBMLDE
Response:
HTTP/1.1 200 OK
Date: Wed, 09 May 2012 07:25:03 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Pragma: no-cache
**Content-Length: 155**
Content-Type: text/html
Expires: Wed, 09 May 2012 07:24:02 GMT
Set-Cookie: Autenticacion=Sid=230fae3d%2De0e2%2D4df1%2D8aa8%2D000fb352eaef&IdUsuarioWeb=xxxx; path=/
Cache-control: no-cache
Doing the same with a web browser works fine and returns a content length of about 4000 bytes.
Any ideas?
PD: Just in case it matters I'm doing several calls to the SendGETRequest from different threads to the same site but as there are no shared variables I think it shouldn't make a difference.
EDIT: This is the extension I use to extract the text from the Stream:
public static string ReadTextResponse(this Stream stream)
{
int count;
Encoding enconding = System.Text.Encoding.GetEncoding(1252);
System.Text.StringBuilder stringBuilder = new StringBuilder();
byte[] buffer = new byte[1023];
do
{
count = stream.Read(buffer, 0, buffer.Length);
if (count != 0)
{
string tempString = enconding.GetString(buffer, 0, count);
stringBuilder.Append(tempString);
}
}
while (count > 0);
return stringBuilder.ToString();
}
As far as I know it's correct. Also, note that the response header from the server contains the length of the truncated data
I think that you are not using right the HttpWebResponse object.
Maybe you are not closing the request or reading all the response strem.
http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.getresponse.aspx
Your method should be:
public static string SendGETRequest(string url, string agent, CookieContainer cookieContainer)
{
var request = (HttpWebRequest)WebRequest.Create(url);
request.UserAgent = agent;
request.Method = "GET";
request.ContentType = "text/html";
request.CookieContainer = cookieContainer;
string result;
using (var myResponse = (HttpWebResponse) request.GetResponse())
{
using (var stream = myResponse.GetResponseStream())
{
result = null;
if (stream != null)
{
using (var sr = new StreamReader(stream, System.Text.Encoding.UTF8))
{
result = sr.ReadToEnd();
sr.Close();
}
stream.Close();
}
}
myResponse.Close();
}
return result;
}
Incredible ... I was sending the URL /Broker/Ops/FichaContratoJS.asp?nc=815044&IP=5&YY=2012&M=6 and the browser was sending /Broker/Ops/FichaContratoJS.asp?nc=815044&IP=5&YY=2012&M=06& (note the extra 0 on the M parameter (it's a month). Putting there that 0 returned the full page. Sounds like a defect to me
I have run into a similar situation and found that copying the response stream into a MemoryStream seemed to fix my problems.
public static string SendGETRequest(string url, string agent, CookieContainer cookieContainer)
{
var request = (HttpWebRequest)WebRequest.Create(url);
request.UserAgent = agent;
request.Method = "GET";
request.ContentType = "text/html";
request.CookieContainer = cookieContainer;
string result;
using (var myResponse = (HttpWebResponse) request.GetResponse())
{
using (var stream = myResponse.GetResponseStream())
{
result = null;
if (stream != null)
{
MemoryStream memStream = new MemoryStream();
stream.CopyTo(memStream);
memStream.Flush();
stream.Close();
using (var sr = new StreamReader(memStream, System.Text.Encoding.UTF8))
{
result = sr.ReadToEnd();
sr.Close();
}
memStream.Close();
}
}
myResponse.Close();
}
return result;
}

Categories