Calling methods from .ashx handler from aspx.cs page - c#

I'm having a bit of trouble calling a method from a generic handler we have. I've tried using two separate techniques to call a simple 'HelloWorld()' method but I get two different errors:
The first technique is as follows:
WebClient wc = new WebClient();
NameValueCollection formData = new NameValueCollection();
formData["method"] = "HelloWorld";
byte[] data;
try
{
data = wc.UploadValues(_domain, formData);
}
catch (WebException ex)
{
Label1.Text = ex.Message;
return;
}
string response = Encoding.UTF8.GetString(data);
Label1.Text = response;
wc.Dispose();
and I get the following error:
{"id":null,"error":{"name":"Found String where Object was expected."}}
and the second technique I've tried is:
var httpWebRequest = (HttpWebRequest)WebRequest.Create(_domain);
httpWebRequest.ContentType = "text/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "{\"method\":\"helloWorld\"}"; //," +
//"\"password\":\"bla\"}";
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
try
{
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
}
catch (WebException wex)
{
Label2.Text = wex.Message;
}
catch (Exception ex)
{
Label2.Text = ex.Message;
}
}
and with this, I get the following error:
The remote server returned an error: (500) Internal Server Error.
When I test the call from the ".ashx?test" page the method runs and the details at the bottom of the screen are:
Pragma: no-cache
Date: Tue, 23 Jul 2013 13:46:19 GMT
Server: ASP.NET Development Server/11.0.0.0
X-AspNet-Version: 2.0.50727
Content-Type: application/json; charset=utf-8
Cache-Control: no-cache
Connection: Close
Content-Length: 32
Expires: -1
Any ideas as to why this wouldn't be working?
Thanks!

An ASHX handler is not a web service. You don't call methods within the ASXH handler. You just call the handler, and it delivers data directly, be it a text or binary data - that's up to you.

Related

HttpWebRequest get unauthorized exception

Trying to call a remote server using the following code I get always the unauthorized exception from the server:
HttpWebRequest webRequest;
var myURI = "https://myURI";
webRequest = (HttpWebRequest)WebRequest.Create(myURI);
webRequest.Method = "GET";
string myCredentials = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes("myUsername" + ":" + "myPassword"));
webRequest.Headers.Add("Authorization", "Basic " + myCredentials);
HttpWebResponse webResponse;
webResponse = (HttpWebResponse)webRequest.GetResponse();
string response = string.Empty;
using (StreamReader sr = new StreamReader(webResponse.GetResponseStream()))
{
response = sr.ReadToEnd();
sr.Close();
}
System.Net.WebException: 'The remote server returned an error: (401) Unauthorized.'
WWW-Authenticate: Basic realm="geoserver"
Cache-Control: proxy-revalidate
Connection: Keep-Alive
Set-Cookie: BCSI-CS-**********=1; Path=/
Proxy-Support: Session-based-authentication
Content-Type: text/plain; charset=UTF-8
Content-Length: 23
It is a litte bit weird because, if I try (almost) the same thing via postman, it works and i get the correct response from the remote server (without 401).
I've also tried other ways like the follwing code, but nothing helps:
CredentialCache cc = new CredentialCache();
cc.Add(
new Uri("https://mywebserver/webpage"),
"Basic", //also tried NTLM
new NetworkCredential("user", "password"));
webRequest.Credentials = cc;
If I try to call an other server with the same code it works.
As you can see in the Exception, has a Session-based-authentication. The problem is: There is no documentation for the reverse proxy and I cannot find an endpoint in order to get a clean cookie. As workaround i've tried the fllowing code and it works now.
It's maybe not the best way to set the Cookie as HttpHeader.
static void Main(string[] args)
{
HttpWebRequest webRequest = CreateWebRequest();
string cookie = null;
HttpWebResponse webResponse;
try
{
webResponse = (HttpWebResponse) webRequest.GetResponse();
}
catch (WebException ex)
{
var headers = (WebHeaderCollection)ex.Response.GetType().GetProperty("Headers").GetValue(ex.Response, null);
cookie = headers.Get("Set-Cookie");
webRequest = CreateWebRequest();
webRequest.Headers.Add("Cookie", cookie);
webResponse = (HttpWebResponse) webRequest.GetResponse();
}
string response = string.Empty;
using (StreamReader sr = new StreamReader(webResponse.GetResponseStream()))
{
response = sr.ReadToEnd();
sr.Close();
}
}
private static HttpWebRequest CreateWebRequest()
{
HttpWebRequest webRequest;
var myURI = "https://myURI";
webRequest = (HttpWebRequest)WebRequest.Create(myURI);
webRequest.Method = "GET";
string myCredentials = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes("myUsername" + ":" + "myPassword"));
webRequest.Headers.Add("Authorization", "Basic " + myCredentials);
return webRequest;
}

Downloading data with broken header

I just got the following problem:
I need to download data which is behind a login page. When I however make my get request, the server is providing bad data - the content is there, but no content length in header set, its an empty field. I looked it up with Fiddler, and its the same when I try to download the file with browser, but browser completes the download ok, while C# drops with exception when getting the response object from my request.
The header looks like this :
HTTP/1.1 200 OK
Date: Sat, 06 Dec 2014 11:55:06 GMT
Server: Apache
Content-Disposition: attachment; filename=;
Pragma: no-cache
Expires: 0
Content-Length:
X-Powered-By: PleskLin
Connection: close
Content-Type: application/octet-stream
Hersteller;"Hersteller Art-Nr";"Lieferant Art-Nr";Ma�stab;Bezeichnung;EAN;"EK (netto)";UVP;USt;Verkaufseinheit;Hinweis;"Letzte Pro...
My code looks like this
public string ReadPage(string path, string method = "GET"){
var result = "";
var request = (HttpWebRequest)WebRequest.Create(path);
request.Method = method;
request.Host = "somehost.de";
request.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore);
request.Referer = #"http://somehost.de/login.php?redir=list.php%3Ftype%3Dmm";
request.AllowAutoRedirect = true;
request.Headers.Add("Cookie", LoginCookie);
try
{
var response = request.GetResponse();
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
result = sr.ReadToEnd();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
//throw;
}
return result;
}
The exception appears in the var response = request.GetResponse(); line. Any idea how to fix this problem? I just want it to carry on and let me read out the data.
Forgot the exception - its a WebException with a message
The server committed a protocol violation. Section=ResponseHeader Detail='Content-Length' header value is invalid
I'm really loving the answer of Matthew: .Net HttpWebRequest.GetResponse() raises exception when http status code 400 (bad request) is returned
litte bit changed
public static class WebRequestExtensions
{
public static WebResponse GetWEResponse(this WebRequest request)
{
if (request == null)
{
throw new ArgumentNullException("request");
}
try
{
return request.GetResponse();
}
catch (WebException e)
{
return e.Response;
}
}
}
You can use this now by using request.GetWEResponse
public string ReadPage(string path, string method = "GET") {
var result = "";
var request = (HttpWebRequest)WebRequest.Create(path);
request.Method = method;
request.Host = "somehost.de";
request.CachePolicy = new System.Net.Cache.RequestCachePolicy(System.Net.Cache.RequestCacheLevel.NoCacheNoStore);
request.Referer = #"http://somehost.de/login.php?redir=list.php%3Ftype%3Dmm";
request.AllowAutoRedirect = true;
request.Headers.Add("Cookie", LoginCookie);
try
{
var response = request.GetWEResponse();
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
result = sr.ReadToEnd();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
//throw;
}
return result;
}
or better
public string ReadPage(string path, string method = "GET")
{
var request = (HttpWebRequest)WebRequest.Create(path);
request.Method = method;
request.Host = "somehost.de";
request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
request.Referer = #"http://somehost.de/login.php?redir=list.php%3Ftype%3Dmm";
request.AllowAutoRedirect = true;
request.Headers.Add("Cookie", LoginCookie);
using (var response = (HttpWebResponse)request.GetWEResponse())
using (var reader = new StreamReader(response.GetResponseStream()))
{
return reader.ReadToEnd();
}
}

Passing querystring parameters in OpenPaths.cc api call with OAuth not working

I am trying to call the OpenPaths.cc rest service API which requires 2-legged OAuth. For this I use the DevDefined.OAuth library (I tried the nuget package and the latest from github). It works when I don't pass parameters in the querystring but returns 400 NOT AUTHORIZED when I do pass parameters.
Working sample with no parameters:
public class OpenPathsRequest
{
private const string accessKey = "your personal access key";
private const string secretKey = "your personal secret";
private const string url = "https://openpaths.cc/api/1";
private OAuthSession session;
public OpenPathsRequest()
{
var consumerContext = new OAuthConsumerContext
{
ConsumerKey = accessKey,
ConsumerSecret = secretKey,
SignatureMethod = SignatureMethod.HmacSha1,
UseHeaderForOAuthParameters = true
};
session = new OAuthSession(consumerContext, url, url, url);
}
private string GetWebResponseAsString(HttpWebResponse response)
{
Encoding enc = System.Text.Encoding.GetEncoding(1252);
StreamReader loResponseStream = new StreamReader(response.GetResponseStream(), enc);
return loResponseStream.ReadToEnd();
}
public string GetResponse()
{
HttpWebResponse response = session.Request().Get().ForUrl(url).ToWebResponse();
var result = GetWebResponseAsString(response);
return result;
}
}
class Program
{
static void Main(string[] args)
{
// create new OpenPathsRequest and get result
var request = new OpenPathsRequest();
var response = request.GetResponse();
Console.WriteLine(response);
Console.WriteLine("Press any key...");
Console.ReadKey();
}
}
But when I change the GetResponse method and pass in 2 parameters (start_time and end_time) like so:
public string GetResponse()
{
HttpWebResponse response = session.Request().Get().ForUrl(url).WithQueryParameters(
new { start_time = 1364962612, end_time = 1364991412 }).ToWebResponse();
var result = GetWebResponseAsString(response);
return result;
}
Which results in the following HTTP request (consumer key omitted):
GET https://openpaths.cc/api/1?start_time=1364962612&end_time=1364991412 HTTP/1.1
Authorization: OAuth oauth_nonce="7b5da37a-6227-4ded-ae8b-a695e789ef90",oauth_consumer_key="**********",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1365058952",oauth_version="1.0",oauth_signature="tAk4KMj%2FsiG6BTLSmvDNKXbBpNs%3D"
Host: openpaths.cc
Connection: Keep-Alive
I get the an error response:
HTTP/1.1 400 Bad Request
Date: Thu, 04 Apr 2013 07:03:26 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Content-Length: 19
Server: TornadoServer/2.0
Set-Cookie: _xsrf=bf20487382b64eeb8646d31b0770db85; Path=/
Set-Cookie: session_id=ZTk2Mjk1MzIzNWNiMmRjMTY1ZmY5Y2ExNWUwMGY5ZTAxZmY1NGIyODljZGJiNzRlMmIyMWI4NTA3YzUwYWJlYg==|1365059006|7459a7ff95039279e9686ceb76b58918fd9f3e48; expires=Thu, 04 Apr 2013 07:18:26 GMT; Path=/
400: NOT AUTHORIZED
All help would be appreciated very much. Thanks in advance.
Harmen
Solved! Apparently OpenPaths.cc api requires signing WITHOUT the additional query parameters in the signature base string. I believe this is not according to OAuth specs, is it? Anyway, with DevDefined.OAuth i can easily solve this by calling SignWithoutToken before calling WithQueryParameters like so:
public string GetResponse()
{
HttpWebResponse response = session.Request().Get().ForUrl(url).
SignWithoutToken().
WithQueryParameters(new { start_time = 1364962612, end_time = 1364991412 }).
ToWebResponse();
var result = GetWebResponseAsString(response);
return result;
}

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;
}

Downloading a file, and I get Content-Length header is Invalid

I'm downloading a file, from a webserver, using the code below, and am recieving this error:
The Error:
Error saving file from URL:The server committed a protocol violation.
Section=ResponseHeader Detail='Content-Length' header value is invalid
From running Fiddler while this is running, it says:
Content-Length response header is not a valid unsigned integer
Content-Length: 13312583
The Code:
public static bool SaveFileFromURL(string url, string destinationFileName, int timeoutInSeconds)
{
//SetAllowUnsafeHeaderParsing20();
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
SettingsSection section = (SettingsSection)config.GetSection("system.net/settings");
section.HttpWebRequest.UseUnsafeHeaderParsing = false;
config.Save();
// Create a web request to the URL
HttpWebRequest MyRequest = (HttpWebRequest)WebRequest.Create(url);
MyRequest.UseDefaultCredentials = true;
MyRequest.ContentLength = 0;
MyRequest.Timeout = timeoutInSeconds * 1000;
try
{
// Get the web response
HttpWebResponse MyResponse = (HttpWebResponse)MyRequest.GetResponse();
// Make sure the response is valid
if (HttpStatusCode.OK == MyResponse.StatusCode)
{
// Open the response stream
using (Stream MyResponseStream = MyResponse.GetResponseStream())
{
// Open the destination file
using (FileStream MyFileStream = new FileStream(destinationFileName, FileMode.OpenOrCreate, FileAccess.Write))
{
// Create a 4K buffer to chunk the file
byte[] MyBuffer = new byte[4096];
int BytesRead;
// Read the chunk of the web response into the buffer
while (0 < (BytesRead = MyResponseStream.Read(MyBuffer, 0, MyBuffer.Length)))
{
// Write the chunk from the buffer to the file
MyFileStream.Write(MyBuffer, 0, BytesRead);
}
}
}
}
}
catch (Exception err)
{
throw new Exception("Error saving file from URL:" + err.Message, err);
}
return true;
}
Update: If I pass the URL straight into a browser, the file is downloaded successfully, and the error is thrown on the GetResponse line.
Update 2: I get the same error with WebClient.Downloadfile:
public static bool DL_Webclient(string url, string destinationFileName)
{
WebClient myWebClient = new WebClient();
myWebClient.UseDefaultCredentials = true;
myWebClient.DownloadFile(url, destinationFileName);
return true;
}
Update 3: Having retrieved the other headers in the message (using Fiddler), they are:
HTTP/1.1 200 OK
Connection: close
Date: Wed, 03 Mar 2010 08:43:06 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Content-Length: 13314320
Content-Type: application/x-evsaveset
Set-Cookie: ASPSESSIONIDQQCQSCRC=CFHHJHADOIBCFAFOHFJCDNEG; path=/
Cache-control: private
Are there other HTTP headers present?
It might have to do with the 'Transfer-Encoding' header or similar rules. For more specific information about these headers and their effect on the Content-Length header can be found at the W3C website and More W3C website
Hope this helps,
Could you not use WebClient.DownloadFile instead?

Categories