Easiest way to read the response from WebResponse - c#

private void RespCallback(IAsyncResult asynchronousResult)
{
try
{
WebRequest myWebRequest1 = (WebRequest)asynchronousResult.AsyncState;
// End the Asynchronous response.
WebResponse webResponse = myWebRequest1.EndGetResponse(asynchronousResult);
}
catch (Exception)
{
// TODO:Log the error
}
}
Now having the webResponse object, what is the easiest way to read its contents?

I would simply use the async methods on WebClient - much easier to work with:
WebClient client = new WebClient();
client.DownloadStringCompleted += (sender,args) => {
if(!args.Cancelled && args.Error == null) {
string result = args.Result; // do something fun...
}
};
client.DownloadStringAsync(new Uri("http://foo.com/bar"));
But to answer the question; assuming it is text, something like (noting you may need to specify the encoding):
using (var reader = new StreamReader(response.GetResponseStream()))
{
string result = reader.ReadToEnd(); // do something fun...
}

Here is one way to do it if the response is coming in from XML.
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create("https://www.yoururl.com");
WebResponse response = myReq.GetResponse();
Stream responseStream = response.GetResponseStream();
XmlTextReader reader = new XmlTextReader(responseStream);
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Text)
{
Console.WriteLine("{0}", reader.Value.Trim());
}
Console.ReadLine();
}

internal string Get(string uri)
{
using (WebResponse wr = WebRequest.Create(uri).GetResponse())
{
using (StreamReader sr = new StreamReader(wr.GetResponseStream()))
{
return sr.ReadToEnd();
}
}
}

Related

How to Request Specific Object From JSON URL with C# WebClient

Following code returns entire JSON objects but I need to Filter to some specific Object, for example I need to get only the "layers" or tiltle can you please let me know how to do this is C#?
Do I have to create an HttpWebRequestobject for this? if so where should I pass the requested data?
using (WebClient wc = new WebClient())
{
var json = wc.DownloadString("https://sampleserver6.arcgisonline.com/arcgis/rest/services/Water_Network/FeatureServer?f=pjson");
Console.WriteLine(json);
}
I already tried this but it is also returning everything
class Program
{
private const string URL = "https://sampleserver6.arcgisonline.com/arcgis/rest/services/Water_Network/FeatureServer?f=pjson";
private const string DATA = #"{{""layers"":""Layers""}}";
static void Main(string[] args)
{
CreateObject();
}
private static void CreateObject()
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
request.Method = "POST";
request.ContentType = "application/json";
request.ContentLength = DATA.Length;
using (Stream webStream = request.GetRequestStream())
using (StreamWriter requestWriter = new StreamWriter(webStream, System.Text.Encoding.ASCII))
{
requestWriter.Write(DATA);
}
try
{
WebResponse webResponse = request.GetResponse();
using (Stream webStream = webResponse.GetResponseStream())
{
if (webStream != null)
{
using (StreamReader responseReader = new StreamReader(webStream))
{
string response = responseReader.ReadToEnd();
Console.WriteLine(response);
Console.ReadLine();
}
}
}
}
catch (Exception e)
{
Console.WriteLine("-----------------");
Console.WriteLine(e.Message);
Console.ReadLine();
}
}
}
If you need the info related to the layers array object then you can use following code
using (var wc = new WebClient())
{
string json = wc.DownloadString("https://sampleserver6.arcgisonline.com/arcgis/rest/services/Water_Network/FeatureServer?f=pjson");
dynamic data = Json.Decode(json);
Console.WriteLine(data.layers[0].id);
Console.WriteLine(data.layers[0].name);
Console.WriteLine(data.documentInfo.Title);
}

Properly handle WebRequests

I have a dynamic page with a .JSON file, and I'm using my C# program to access it every x number of seconds, to determine if something has been changed or not. Everything works flawlessly as long as I have Internet connection, if for whatever reason I lose it, then my program crashes as the ex.Response is a null. I was wondering if there's a better way of handling the following code:
void Function(){
while(true){
jList = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<jsonList>(GET(jsonUrl));
//SOME THINGS I DO with the data above here
Thread.Sleep(5000);
}}
string GET(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
try
{
WebResponse response = request.GetResponse();
using (Stream responseStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
return reader.ReadToEnd();
}
}
catch (WebException ex)
{
WebResponse errorResponse = ex.Response;
if (ex.Response != null) {
using (Stream responseStream = errorResponse.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
String errorText = reader.ReadToEnd();
// log errorText
}
}
throw;
}
}
Perhaps I should ping it first, and see if I get a reply, and only then Perform the WebRequest function?
EDIT:
After adding this
public bool getResponse(string URL)
{
try
{
WebClient wc = new WebClient();
string HTMLSource = wc.DownloadString(URL);
return true;
}
catch (Exception)
{
return false;
}
}
And use it as
void Function(){
while(true){
if (!getResponse(jsonUrl))
{
return;
}
jList = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<jsonList>(GET(jsonUrl));
//SOME THINGS I DO with the data above here
Thread.Sleep(5000);
}}
My C# application waits a bit, and then exits normally. Why?
The program '[10476] Kiosk2.vshost.exe' has exited with code 0 (0x0).
Alright, well this seems to work fine for me.
public void Update() //CALLED IT void FUNCTION earlier
{
while (true)
{
while (getResponse(jsonUrl))
{
jList = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<jsonList>(GET(jsonUrl));
//I DO SOME STUFF HERE
//INTERESTING STUFF
Thread.Sleep(5000);
}
}
}
And seconds function:
public bool getResponse(string URL)
{
try
{
WebClient wc = new WebClient();
string HTMLSource = wc.DownloadString(URL);
return true;
}
catch (Exception)
{
return false;
}
}

c# catch empty Json / 404 error

I have the following code for accessing a Api which returns a Json value. Now it's possible that i try to access the api but nothing is being returned, aka the given ID its trying to search doesnt exist. This ofcourse returns a 404 but i do not know how to handle this error so the code continious on going, now it breaks the program and crashes.
public RootObject GetApi(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
try{
WebResponse response = request.GetResponse();
using (Stream responseStream = response.GetResponseStream()){
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
var jsonReader = new JsonTextReader(reader);
var serializer = new JsonSerializer();
return serializer.Deserialize<RootObject>(jsonReader);
}
}
catch (WebException ex){
WebResponse errorResponse = ex.Response;
using (Stream responseStream = errorResponse.GetResponseStream()){
StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
String errorText = reader.ReadToEnd();
// log errorText
}
throw;
}
}
This is the button click event where the Url of the api is given.
private void button1_Click(object sender, EventArgs e)
{
result_rTBox.Text = "";
api_Handler api_Handler = new api_Handler();
string spidyApi_itemSearch = "http://www.gw2spidy.com/api/v0.9/json/item-search/";
string Gw2Api_allListings = "https://api.guildwars2.com/v2/commerce/listings/";
string userInput_itemName = userSearchInput_tBox.Text;
string spidyApi_searchIdByName = spidyApi_itemSearch + userInput_itemName;
if (!string.IsNullOrWhiteSpace(userSearchInput_tBox.Text)){
var spidyApi_searchIdByName_result = api_Handler.GetApi(spidyApi_searchIdByName);
var Gw2Api_isItemIdinListing_result = api_Handler.GetApi(Gw2Api_allListings + spidyApi_searchIdByName_result.results[0].data_id);
//result_rTBox.Text = Gw2Api_isItemIdinListing_result.results[0].data_id.ToString();
}
}
First i access the api with string "spidApi_itemSearch" and after that I have and ID that i need to check if exists in the api Gw2Api_allListings. If it doesnt exist, which will happen quite often, it returns nothing with a 404 error. How do i get around of making the code continue even if it returns nothing?
EDIT: code that i have now, still crashes on the break.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
try
{
var requesting = WebRequest.Create(url);
using (var response = request.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
var jsonReader = new JsonTextReader(reader);
var serializer = new JsonSerializer();
return serializer.Deserialize<RootObject>(jsonReader);
}
}
}
catch (WebException ex)
{
if (ex.Status == WebExceptionStatus.ProtocolError &&
ex.Response != null)
{
var resp = (HttpWebResponse)ex.Response;
if (resp.StatusCode == HttpStatusCode.NotFound){
}
}
throw;
}
}
Use the HttpStatusCode Enumeration, specifically HttpStatusCode.NotFound
Instead of WebResponse, try using HttpWebResponse
HttpWebResponse errorResponse = we.Response as HttpWebResponse;
if (errorResponse.StatusCode == HttpStatusCode.NotFound) {
// handle the error here
}
Where we is a WebException

Returning Stream from WebRequest

I'm having an issue when i return a Stream from a WebRequest, it says that the stream was closed, when i have everything in the same method then it works here is the code example:
public static Stream MethodOne()
{
Uri uri = new Uri(url, true);
WebRequest request = WebRequest.Create(uri);
request.Method = "GET";
Stream responseStream = null;
using (WebResponse webResponse = request.GetResponse())
{
responseStream = webResponse.GetResponseStream();
}
}
The other method is:
public static XDocument MethodTwo()
{
Stream stream = MethodOne();
if (stream == null)
{
return null;
}
XmlReader xmlReader = XmlReader.Create(stream);
return XDocument.Load(xmlReader);
}
The error that i get is where i try to create an xmlReader from the stream with the following message: The request was aborted: The connection was closed unexpectedly.
Any idea how to resolve it?
your using statement calls Dispose on the Response before you read the stream.
I would return the WebResponse from Method one.
public static XDocument MethodTwo()
{
WebResponse response = MethodOne();
if (response == null)
{
response null;
}
try
{
var stream = response.GetResponseStream();
XmlReader xmlReader = XmlReader.Create(stream);
return XDocument.Load(xmlReader);
}
finally
{
response.Dispose();
}
}
Update: Better solution
public static XDocument MethodTwo()
{
using (var response = MethodOne())
using (var stream = response.GetResponseStream())
{
var stream = response.GetResponseStream();
XmlReader xmlReader = XmlReader.Create(stream);
return XDocument.Load(xmlReader);
}
}
public static Stream MethodOne()
{
Uri uri = new Uri(url, true);
WebRequest request = WebRequest.Create(uri);
request.Method = "GET";
return request;
}
This will ensure that your resources are disposed (even if an exception occures).
As SchlaWiener pointed out, the problem you're facing is that the using statement calls Dispose() on the stream before you can read the stream. You should refactor your code as follows:
public static Stream GetResponseStream()
{
var uri = new Uri(url, true);
WebRequest request = WebRequest.Create(uri);
request.Method = WebRequestMethods.Http.Get;
WebResponse response = request.GetResponse();
return response.GetResponseStream();
}
public static XDocument GetXDocument()
{
using(Stream stream = GetResponseStream())
{
XmlReader xmlReader = XmlReader.Create(stream);
return XDocument.Load(xmlReader);
}
}
This way, you'll make sure the stream is closed only after the read.

.NET Threading - HttpWebRequest BeginGetResponse + AutoResetEvent

I would like to know which approach among the two is a better implementation ?
I need to create a web request which can range between 200ms to 5 seconds. I need the html response to proceed - so need to block on the main thread.
First Approach
string GetResponse()
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
IAsyncResult result = request.BeginGetResponse(null, null);
using (HttpWebResponse httpResponse = (HttpWebResponse)request.EndGetResponse(result))
{
using (Stream dataStream = httpResponse.GetResponseStream())
{
StreamReader reader = new StreamReader(dataStream);
response = reader.ReadToEnd();
}
}
Second Approach
string response = string.Empty;
AutoResetEvent waitHandle = null;
void GetResponse(string url)
{
waitHandle = new AutoResetEvent(false);
try
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
IAsyncResult asyncResult = request.BeginGetResponse(Callback, request);
waitHandle.WaitOne();
}
catch { }
finally
{
waitHandle.Close();
}
}
void Callback(IAsyncResult asyncResult)
{
HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;
try
{
using (HttpWebResponse httpResponse = (HttpWebResponse)request.EndGetResponse(asyncResult))
{
if (httpResponse.StatusCode == HttpStatusCode.OK)
{
using (Stream dataStream = httpResponse.GetResponseStream())
{
StreamReader reader = new StreamReader(dataStream);
response = reader.ReadToEnd();
}
}
}
}
catch { }
finally
{
waitHandle.Set();
}
}
Why not execute the web request on the main thread? If you want the main thread to block, this is by far the easiest way to accomplish this.

Categories

Resources