Help with ASP.NET HttpWebRequest - c#

I began to learn ASP.NET and C#, to get more familiar with techniques I want to make plugin for open source BugTracker.Net application. Where I am stacked is that for adding new issue application need to get HttpWebRequest on insert_bug.aspx
I did make basic thing working on code like this:
string Url = "http://localhost:8090/insert_bug.aspx";
string post_data =
"&username=admin"
+ "&password=admin"
+ "&short_desc=Description"
+ "&comment=Comment"
+ "&projectid=1"
byte[] bytes = Encoding.UTF8.GetBytes(post_data);
HttpWebResponse res = null;
try
{
HttpWebRequest req = (HttpWebRequest) System.Net.WebRequest.Create(Url);
req.Credentials = CredentialCache.DefaultCredentials;
req.PreAuthenticate =
req.Method = "POST";
req.ContentType= "application/x-www-form-urlencoded";
req.ContentLength=bytes.Length;
Stream request_stream = req.GetRequestStream();
request_stream.Write(bytes,0,bytes.Length);
request_stream.Close();
res = (HttpWebResponse) req.GetResponse();
}
catch (Exception e)
{
Console.WriteLine("HttpWebRequest error url=" + Url);
Console.WriteLine(e);
}
I want to insert also CATEGORY into my issues and reading code on insert_bug.aspx i fund part for defining category for opening issue
if (Request["$CATEGORY$"] != null && Request["$CATEGORY$"] != "") { categoryid = Convert.ToInt32(Request["$CATEGORY$"]); }
Question:
What and How I can add "$CATEGORY$" to my request so the issues I added have defined category.

If I understand your question correctly, if you want to add a category, you need to look up the category ID and add it as a variable in your POST data. For example, if the category you want has its ID=1 ("bug" in BugTracker.NET), then you'd use this:
string post_data =
"&username=admin"
+ "&password=admin"
+ "&short_desc=Description"
+ "&comment=Comment"
+ "&projectid=1"
+ "&$CATEGORY$=1";
BTW, in simple HTTP client scenarios like this one you're better off using the WebClient class. You can accomplish the same thing in many fewer lines of code.

Related

Always Getting an HTML in Response from RTC

It seems like the RTC server doesn't like my url request. I can essentially add whatever I want after the "host" part of the url and get the same result. So I'm guessing something about what I've got is wrong. Following the answer from my previous post, I'm pretty sure I have the right url from the "services" file in the <oslc_cm:simpleQuery><dc:title>Change request queries</dc:title> tag. So I'm not sure if there's something else it doesn't like? It no longer fails authentication and I'm now using form-based rather than basic, so I don't think it's authentication-related. It just seems to ignore anything and everything but still knows my credentials aren't wrong. Any ideas?
Update: I've also tried swapping all the colons with %3A as the Jazz documentation didn't seem particularly consistent in their examples if that was necessary or not. Same results though.
string host = "https://my.host.com:9443/ccm/";
string item = host + "oslc/contexts/_MySp3ci4lK3Y/workitems?" +
"oslc.where=dcterms:identifier=%222494443%22&" +
"oslc.properties=dcterms:title,dcterms:identifier&" +
"oslc.prefix=dcterms=%3Chttp://purl.org/dc/terms/%3E";
Debug.Log("Request");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(item);
request.Accept = "application/json";
request.Headers.Add("OSLC-Core-Version", "2.0");
WebResponse response = request.GetResponse();
string AuthHeader = response.Headers["X-com-ibm-team-repository-web-auth-msg"];
//check if authentication has failed
if ((AuthHeader != null) && AuthHeader.Equals("authrequired"))
{
Debug.Log("Authentication Required");
HttpWebRequest _formPost = (HttpWebRequest)WebRequest.Create(host + "authenticated/j_security_check"); // Same response without the "authenticated/j_security_check"
_formPost.Method = "POST";
_formPost.Timeout = 30000;
_formPost.Headers.Add("OSLC-Core-Version", "2.0");
_formPost.CookieContainer = request.CookieContainer;
_formPost.Accept = "text/xml";
_formPost.ContentType = "application/x-www-form-urlencoded";
Byte[] _outBuffer = Encoding.UTF8.GetBytes(credentials); //store in byte buffer
_formPost.ContentLength = _outBuffer.Length;
Stream _str = _formPost.GetRequestStream();
_str.Write(_outBuffer, 0, _outBuffer.Length); //update form
_str.Close();
//FormBasedAuth Step2:submit the login form and get the response from the server
HttpWebResponse _formResponse = (HttpWebResponse)_formPost.GetResponse();
string _rtcAuthHeader = _formResponse.Headers["X-com-ibm-team-repository-web-auth-msg"];
//check if authentication has failed
if ((_rtcAuthHeader != null) && _rtcAuthHeader.Equals("authfailed"))
{
Debug.Log("Authentication Failed");
return;
}
else
{
//login successful
// *** Still says AuthRequired here for some reason ***
Debug.Log("Auth Header = " + _rtcAuthHeader);
_formResponse.GetResponseStream().Flush();
_formResponse.Close();
//FormBasedAuth Step3: Resend the request for the protected resource.
response = (HttpWebResponse)request.GetResponse();
}
}
else if (AuthHeader == null)
{
Debug.Log("AuthHeader Null");
}
else
{
Debug.Log("AuthHeader = " + AuthHeader);
}
Debug.Log("Response Stream");
Stream responseStream = response.GetResponseStream();
byte[] buffer = new byte[BufferSize];
int read;
while ((read = responseStream.Read(buffer, 0, buffer.Length)) > 0)
{
// Prints out an HTML Doc rather than a JSON string.
Debug.Log(Encoding.UTF8.GetString(buffer));
}
This is what I've come to understand.
The comment "// * Still says AuthRequired here for some reason *" is telling of the fact that authorization is indeed not occurring. The header value for "X-com-ibm-team-repository-web-auth-msg" will indeed be null when it is officially no longer required.
It is failing because:
The _formPost itself needs basic authentication to post the form values
The CookieContainer is null. Creating a new CookieContainer allows for the authentication to proceed.
The "authenticated/j_security_check" is not correct. It should simply be "j_security_check".
When requesting the data a second time after authenticating, a new request must be created and using the CookieContainer from the original.

WCF HTTP GET api

In my .NET project, I have to use HTTP GET request to get weather info for my city from API. Because of my JavaScript background I thought "OK, so all I need is something like app.get(url, body)", so I started with something like this:
using (var client = new WebClient())
{
var responseString = client.DownloadString("http://www.webservicex.net/globalweather.asmx/GetWeather?CityName=" + city + "&CountryName=" + country);
string xmlString = DecodeXml(responseString);
return xmlString;
}
Unfortunately for me it turned out, that I have to use WCF to get the data. I searched the web for some tutorials, but I couldn't find anything with getting the data from outer sources, just creating own API.
I'm not a native speaker, so maybe I'm just out of words to look for the solution, but it would be awesome if you could give me some advice.
Assuming you are using Visual Studio. Add Service Reference, and then type "http://www.webservicex.net/globalweather.asmx" into the address and hit Go. It'll auto-generate the end point for you to use.
Then the code is something like:
ServiceReference1.GlobalWeatherSoapClient client = new ServiceReference1.GlobalWeatherSoapClient("GlobalWeatherSoap");
string cities = client.GetCitiesByCountry("Hong Kong");
If you want to just use HTTP GET, you can do something like this:
var city = "Dublin";
var country = "Ireland";
WebRequest request = WebRequest.Create(
"http://www.webservicex.net/globalweather.asmx/GetWeather?CityName=" +
city +
"&CountryName=" + country);
request.Credentials = CredentialCache.DefaultCredentials;
WebResponse response = request.GetResponse();
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
Console.WriteLine(responseFromServer);
reader.Close();
response.Close();
Console.ReadLine();
Please note, I have not HTML decoded the response here, you can simply use HttpUtility.HtmlDecode for that.
Also, you will need to include the following using statements:
using System.IO;
using System.Net;

How to print all results of a JSON API call

I'm making a web-app that needs data through an API. I am trying to re-purpose some of the developer's example code of a different function than the original code was written for. Here's the important part:
WebRequest request = WebRequest.Create(urlPrefix + "getthingjson/" + Key);
WebResponse response = request.GetResponse();
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
reader.Close();
response.Close();
// Parse returned JSON into data
//
using (var web = new WebClient())
{
web.Encoding = System.Text.Encoding.UTF8;
var jsonString = responseFromServer;
var jss = new JavaScriptSerializer();
var ThingsList = jss.Deserialize<List<Things>>(jsonString);
string ThingsListStr = "";
foreach (Things x in ThingsList)
ThingsListStr = ThingsListStr + ", " + x.Name;
MessageBox.Show(ThingsListStr);
}
I know that I need to change 'Name' in order to get a different piece of info on the 'Things' call. The thing is, I need to call results on a different function, instead of 'Things' say 'Details'. I don't know what to look for in place of 'Name' since when I search that it returns nothing. How could I just deserialize all of what JSON returns? Sorry if my terminology was off or I made a simple mistake, I'm new to JSON and C#. Thanks!
To get Details instead of Name property you should:
Check if you receive this data in json.
Adjust your c# class with Details property if it doesn't exist. (Go to Things class and add new Details property)
Change
ThingsListStr = ThingsListStr + ", " + x.Name;
to
ThingsListStr = ThingsListStr + ", " + x.Details;

Send object through HttpWebRequest (REST Service)

I have a REST Service that accepts a id in the URL for PUT requests. So far the PUT request looks like this:
string url = "http://localhost:3596/WidgetManager.svc/Widgets/" + TextBox3.Text;
WebRequest req = WebRequest.Create(url);
req.Method = "PUT";
using (HttpWebResponse resp = req.GetResponse() as HttpWebResponse)
{
StreamReader reader = new StreamReader(resp.GetResponseStream());
Label4.Text = reader.ReadToEnd();
}
But I also need to send a Widget object in my request.
Widget w = new Widget();
w.Name = "worked!!!";
w.CogCount = 1000;
w.SprocketSize = 2000;
I saw a lot of examples on how to send strings. But what about objects like this?
You could serialise it using XML or JSON.
If it is such a small object, you could write your own small method like
.toJSON() {
return '{"Name":"' + this.name + '", "CogCount":' + this.CogCount + ', "SprocketSize":' + this.SprocketSize + '}';
}
//Output: '{"Name":"worked!!!", "CogCount":1000, "SprocketSize":2000}'
On the other hand: C# provides powerful (XML) serialisation tools!
This here: http://www.codeproject.com/Articles/1789/Object-Serialization-using-C is only one of many examples.
But if you use PHP or similar, JSON might even be more interesting.

Why does sending post data with WebRequest take so long?

I am currently creating a C# application to tie into a php / MySQL online system. The application needs to send post data to scripts and get the response.
When I send the following data
username=test&password=test
I get the following responses...
Starting request at 22/04/2010 12:15:42
Finished creating request : took 00:00:00.0570057
Transmitting data at 22/04/2010 12:15:42
Transmitted the data : took 00:00:06.9316931 <<--
Getting the response at 22/04/2010 12:15:49
Getting response 00:00:00.0360036
Finished response 00:00:00.0360036
Entire call took 00:00:07.0247024
As you can see it is taking 6 seconds to actually send the data to the script, I have done further testing bye sending data from telnet and by sending post data from a local file to the url and they dont even take a second so this is not a problem with the hosted script on the site.
Why is it taking 6 seconds to transmit the data when it is two simple strings?
I use a custom class to send the data
class httppostdata
{
WebRequest request;
WebResponse response;
public string senddata(string url, string postdata)
{
var start = DateTime.Now;
Console.WriteLine("Starting request at " + start.ToString());
// create the request to the url passed in the paramaters
request = (WebRequest)WebRequest.Create(url);
// set the method to post
request.Method = "POST";
// set the content type and the content length
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postdata.Length;
// convert the post data into a byte array
byte[] byteData = Encoding.UTF8.GetBytes(postdata);
var end1 = DateTime.Now;
Console.WriteLine("Finished creating request : took " + (end1 - start));
var start2 = DateTime.Now;
Console.WriteLine("Transmitting data at " + start2.ToString());
// get the request stream and write the data to it
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteData, 0, byteData.Length);
dataStream.Close();
var end2 = DateTime.Now;
Console.WriteLine("Transmitted the data : took " + (end2 - start2));
// get the response
var start3 = DateTime.Now;
Console.WriteLine("Getting the response at " + start3.ToString());
response = request.GetResponse();
//Console.WriteLine(((WebResponse)response).StatusDescription);
dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
var end3 = DateTime.Now;
Console.WriteLine("Getting response " + (end3 - start3));
// read the response
string serverresponse = reader.ReadToEnd();
var end3a = DateTime.Now;
Console.WriteLine("Finished response " + (end3a - start3));
Console.WriteLine("Entire call took " + (end3a - start));
//Console.WriteLine(serverresponse);
reader.Close();
dataStream.Close();
response.Close();
return serverresponse;
}
}
And to call it I use
private void btnLogin_Click(object sender, EventArgs e)
{
// string postdata;
if (txtUsername.Text.Length < 3 || txtPassword.Text.Length < 3)
{
MessageBox.Show("Missing your username or password.");
}
else
{
string postdata = "username=" + txtUsername.Text +
"&password=" + txtPassword.Text;
httppostdata myPost = new httppostdata();
string response = myPost.senddata("http://www.domainname.com/scriptname.php", postdata);
MessageBox.Show(response);
}
}
Make sure you explicitly set the proxy property of the WebRequest to null or it will try to autodetect the proxy settings which can take some time.
Chances are that because, in your test, you only call this once, the delay you see is the C# code being JIT compiled.
A better test would be to call this twice, and discard the timings from the first time and see if they are better.
An even better test would be to discard the first set of timings, and then run this many times and take an average, although for a very loose "indicative" view, this is probably not necessary.
As an aside, for this sort of timing, you are better off using the System.Diagnostics.Stopwatch class over System.DateTime.
[EDIT]
Also, noting Mant101's suggestion about proxies, if the setting no proxy fails to resolve things, you may wish to set up Fiddler and set your request to use Fiddler as its proxy. This would allow you to intercept the actual http calls so you can get a better breakdown of the http call timings themselves from outside the framework.

Categories

Resources