Send object through HttpWebRequest (REST Service) - c#

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.

Related

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;

Deserialize JSON data with C#

I am a new user in C# and I'm haveing some problems with my code.
I cant deserialize JSON data and I cant understand why:
webRequest = (HttpWebRequest)WebRequest.Create("http://" + Ip.ToString() + ":" + Port.ToString() + "........"); // Create a request to get server info
webRequest.Method = "GET";
webRequest.KeepAlive = true;
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.CookieContainer = cookieJar; //set container for HttpWebRequest
webResponse = (HttpWebResponse)webRequest.GetResponse(); // Get the response.
reader = new StreamReader(webResponse.GetResponseStream());
ServerInfo outObject = JsonConvert.DeserializeObject<ServerInfo>(reader.ToString());
my_label_ServerInfo.Text = outObject.message;
the server info class:
public class ServerInfo
{
public string message { get; set; }
public string message_timestamp { get; set; }
}
In C#,
reader.ToString()
will by default return the name of the class. In this case, "System.IO.StreamReader"
What you want is
reader.ReadToEnd()
which will return the entire contents of the stream as a string.
That should cause it to work, but be aware that it's not best practice. A few areas for consideration as you learn more about C#:
As Aron mentioned, you should wrap all your streams and readers in "using" statement to take advantage of the Dispose pattern which will let the runtime know it can release resources right away rather than waiting for the finalizer
As Fred demonstrated in his code, you can avoid converting the stream to a string and just let the Json.Net library do that.
To ensure that you properly escape and format the request URL, you could use the UriBuilder class: new UriBuilder("http", ip, port, path).Uri)
You could use the newer and async friendly HttpClient class to download the data.
Although Jeff is correct in WHY it doesn't work correctly. His answer still isn't the correct way to "fix" your code. Strings are very inefficient in C# (like almost EVERY programming language, and we avoid them as much as possible).
So you should be doing this instead.
//STOP USING member fields (when possible),
//you encourage threading problems with member fields.
var webRequest = (HttpWebRequest)WebRequest.Create("http://" + Ip.ToString() + ":" + Port.ToString() + "........"); // Create a request to get server info
webRequest.Method = "GET";
webRequest.KeepAlive = true;
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.CookieContainer = cookieJar; //set container for HttpWebRequest
var webResponse = (HttpWebResponse)webRequest.GetResponse();
//ALWAYS dispose your disposable correctly
//Not disposing HttpStreams will cause you to leak TCP/IP
//ports.
using(var stream = webResponse.GetResponseStream())
using(var reader = new StreamReader(stream))
{
JsonSerializer serializer = new JsonSerializer();
ServerInfo outObject = (ServerInfo)serializer.Deserialize(reader, typeof(ServerInfo));
my_label_ServerInfo.Text = outObject.message;
}
What is the json that comes in your response body?
You might want to start off with a little test to make sure that the response body can correctly deserialize into your ServerInfo class. This is a matter of personal preference, but I like to do things a bit more explicitly as it helps to minimize unexpected behavior down the road.
For example, you could decorate your ServerInfo class like this:
// I chose MemberSerialization.OptIn so that all members need to be
// included explicitly, rather than implicitly (which is the default)
[JsonObject(MemberSerialization.OptIn)]
public class ServerInfo
{
[JsonProperty]
public string message { get; set; }
[JsonProperty]
public string message_timestamp { get; set; }
}
Then, you read the full HttpWebResponse body into a string like this:
reader = new StreamReader(webResponse.GetResponseStream());
string responseBody = reader.ReadToEnd();
reader.Close();
And lastly, you deserialize the response body into your ServerInfo class like this:
ServerInfo serverInfo = JsonConvert.DeserializeObject<ServerInfo>(responseBody);
This is assuming your json will come in the following format (or of a similar structure):
{
"message": "Test Message",
"message_timestamp": "2015-04-04T20:00:00"
}
Of course you should first check if your actual input deserializes correctly. I tried the format above in a unit test with this simple snippet:
var sb = new StringBuilder();
sb.Append("{");
sb.AppendLine();
sb.AppendFormat("\"{0}\": \"{1}\"", "message", "Test Message");
sb.Append(",");
sb.AppendLine();
sb.AppendFormat("\"{0}\": \"{1}\"", "message_timestamp", "2015-04-04T20:00:00");
sb.AppendLine();
sb.Append("}");
string json = sb.ToString();
ServerInfo serverInfo = JsonConvert.DeserializeObject<ServerInfo>(json);
EDIT: I completely agree with Aron in that you shouldn't unnecessarily use member fields and always make sure to dispose streams properly.
Improving my original answer with his suggestions, the following code I suggested earlier:
webRequest = (HttpWebRequest)WebRequest.Create("http://" + Ip.ToString() + ":" + Port.ToString() + "........");
webRequest.Method = "GET";
webRequest.KeepAlive = true;
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.CookieContainer = cookieJar;
webResponse = (HttpWebResponse)webRequest.GetResponse();
reader = new StreamReader(webResponse.GetResponseStream());
string responseBody = reader.ReadToEnd();
reader.Close();
ServerInfo serverInfo = JsonConvert.DeserializeObject<ServerInfo>
my_label_ServerInfo.Text = serverInfo.message;
Would change into this, which will perform better and is less prone to errors (I removed the comments for brevity, see Aron's answer for the explanations):
var webRequest = (HttpWebRequest)WebRequest.Create("http://" + Ip.ToString() + ":" + Port.ToString() + "........");
webRequest.Method = "GET";
webRequest.KeepAlive = true;
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.CookieContainer = cookieJar;
var webResponse = (HttpWebResponse)webRequest.GetResponse();
using (var stream = webResponse.GetResponseStream())
using (var reader = new StreamReader(stream))
{
JsonSerializer serializer = new JsonSerializer();
ServerInfo serverInfo = (ServerInfo)serializer.Deserialize(reader, typeof(ServerInfo));
my_label_ServerInfo.Text = serverInfo.message;
}
This will still work with the explicit JSON serialization attributes I added to your ServerInfo class. Note that they are not strictly necessary if the property names match up. I do this mainly just to show you how to gain more control over the serialization behavior without the need to implement a custom JsonSerializer.
I'd suggest the approach of accessing JSON values with structured JSON types (object and array), without having to predefine types (such as the ServerInfo type) to deserialize into.
JsonObject serverinfo = (JsonObject)JsonObject.Load(responseStream);

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;

Convert JSON curl to C#

I have the following curl code:
curl 'localhost:8983/solr/sessions/update?commit=true' -H 'Content-type:application/json' -d '[{"Session_SessionId":"da7007e9-fe7a-4bdf-b9e4-1a55034cf08f","Session_HasComments":{"set":true}}]'
I am trying to convert to C#, but I am getting an error every time so unsure if my code is correct...
Here's what I have so far:
string path = "http://localhost:8983/solr/sessions/update?commit=true";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(path);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "{\"Session_SessionId\":\"" + sessionId + "\"," +
"\"" + fieldName + "\":{\"set\":\"" + fieldValue + "\"}}";
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
}
It always seems to error () on this line:
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
The error i get is:
The remote server returned an error: (400) Bad Request.","StackTrace":" at System.Net.HttpWebRequest.GetResponse()
Any ideas? Thanks in advance!
Dave
Maybe it's that you have removed square brackets in your JSON content that you are streaming into request? Try adding the [ ] back to the start/end of data. Although the "BadRequest" is usually quite strict error that tells you that your HTTP request is malformed, your server may actually return that code also for other cases - like missing session id - which probably occurred here.
note the diff:
-d '[{"Session_SessionId":"da70.....
^ bracket
and
string json = "{\"Session_SessionId\":\"" + sessionId + "\"," + ....
^ no bracket
and the same at the end of data.
But, of course, that's just a guess. :)
Your request cannot be understood by the server. Did you check the output of json variable. I believe the JSON string is not generating properly.
Why don't you use JavaScriptSerializer.Serialize to create JSON string.
Your use the Update Handler with a JSON object will need to follow the JSON format outlined in Update JSON - Update Commands
As another user has suggested your JSON output does not match the CURL. Try the following rather than typing the text.
var data = new[]
{
new
{
Session_SessionId = "da7007e9-fe7a-4bdf-b9e4-1a55034cf08f",
Session_HasComments = new {set = true}
}
};
var json = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(data);
Also, you are using the using keyword to write the data through, and attempt to handle response while inside the block - it probably does make a difference but it might be worth moving this outside this block.
Lastly, you may need to encode the data as a byte array.
Here is the code implementing the above suggestions.
string path = "http://localhost:8983/solr/sessions/update?commit=true";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(path);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
var data = new[]
{
new
{
Session_SessionId = "da7007e9-fe7a-4bdf-b9e4-1a55034cf08f",
Session_HasComments = new {set = true}
}
};
string json = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(data);
byte[] byteData = new System.Text.ASCIIEncoding().GetBytes(json);
httpWebRequest.ContentLength = byteData.Length;
using (Stream stream = httpWebRequest.GetRequestStream())
{
stream.Write(byteData,0,byteData.Length);
}
HttpWebResponse resp = (HttpWebResponse)httpWebRequest.GetResponse();
string respStr = new StreamReader(resp.GetResponseStream()).ReadToEnd();
Console.WriteLine("Response : " + respStr);
Just use SolrNet. If you are doing this with Solr 4+, you need to download latest code and built it yourself, but that's very easy.
Dave, it worked for me.
You were missing square brackets. Just replace respective line with below:
string json = "[{\"Session_SessionId\":\"" + sessionId + "\"," +
"\"" + fieldName + "\":{\"set\":\"" + fieldValue + "\"}}]";

Help with ASP.NET HttpWebRequest

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.

Categories

Resources