Processing SOAP request with USING statement not working? - c#

I'm trying to refactor a console app that uses SOAP to get some API data. I saw that the original code isn't using any USING statements. I thought I would try to refactor the code to do so, however, I get an "Internal Server Error". I've looked this over an few times and I'm not seeing why this wouldn't work. If I switch back to the original code it works as expected.
This is the original code that works:
public static string ProcessSOAPRequest(string xml, string endPoint)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(endPoint);
req.Timeout = 100000000;
req.Method = "POST";
Stream objStream = req.GetRequestStream();
doc.Save(objStream);
objStream.Close();
WebResponse resp = req.GetResponse();
objStream = resp.GetResponseStream();
StreamReader r = new StreamReader(objStream);
string data = r.ReadToEnd();
return data;
}
This is my attempt at refactoring with USING.
public static string ProcessSOAPRequest(string xml, string endPoint)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(endPoint);
request.Timeout = 100000000;
request.Method = "POST";
using (WebResponse response = request.GetResponse())
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
UPDATE: another attempt based on the responses. This time in the second USING statement it says that I can't use stream = response.GetResponseStream(); because "stream" is in a using statement.
var data = string.Empty;
using (Stream stream = request.GetRequestStream())
{
doc.Save(stream);
using (WebResponse response = request.GetResponse())
{
stream = response.GetResponseStream();
using (StreamReader reader = new StreamReader(stream))
{
data = reader.ReadToEnd();
}
}
}
return data;

Answer to the update:
The variable declared in a using statement is treated as readonly. I suggest you to declare a new variable and assign the response to that. Why? - Why is a variable declared in a using statement treated as readonly?
var data = string.Empty;
using (Stream stream = request.GetRequestStream())
{
doc.Save(stream);
using (WebResponse response = request.GetResponse())
{
var responseStream = response.GetResponseStream();
if (responseStream != null)
{
using (StreamReader reader = new StreamReader(responseStream))
{
data = reader.ReadToEnd();
}
}
}
}
return data;
should work.

Related

Cannot send a content-body with this verb-type using HttpWebRequest

I try to GET data using HttpWebRequest.
But this line of code: Stream requestStream = request.GetRequestStream() is giving me this error:
Cannot send a content-body with this verb-type.
How can I fix this?
var data = new
{
COMTAXCODE = "abcd"
};
var httpWebRequest = (HttpWebRequest)WebRequest.Create(endpoint);
httpWebRequest.Method = "GET";
httpWebRequest.Headers[HttpRequestHeader.Authorization] = token;
byte[] byteArray = Encoding.UTF8.GetBytes(JSONHelper.ObjectToJson(data));
httpWebRequest.ContentLength = byteArray.Length;
string res = "";
using (Stream requestBody = httpWebRequest.GetRequestStream())
{
requestBody.Write(byteArray, 0, byteArray.Length);
}
using (HttpWebResponse response = (HttpWebResponse)httpWebRequest.GetResponse())
using (Stream stream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
res = reader.ReadToEnd();
}

How to get an Automation Account Webhook to Return Values in ASP.NET

I'm new to ASP.NET development and the use of webhooks.
I'm using ASP.NET and an Azure Automation Account which has a webhook. I can currently execute the webhook, however I would like to have my code wait until it receives the output of the webhook. How best to do this?
ASP.NET Code:
public ActionResult UpdateAll()
{
(random db calls)
string jsonList = JsonConvert.SerializeObject(userEnvironmentList);
try
{
string uri = "webhook_url";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
string data = jsonList;
request.Method = "POST";
request.ContentType = "text/plain;charset=utf-8";
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
byte[] bytes = encoding.GetBytes(data);
request.ContentLength = bytes.Length;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
request.BeginGetResponse((x) =>
{
using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(x))
{
using (Stream stream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(stream, Encoding.UTF8);
String responseString = reader.ReadToEnd();
}
}
}, null);
}
catch (Exception ex)
{
throw ex;
}
return View();
}
PS in Automation Account:
param
(
[Parameter (Mandatory = $false)]
[object] $WebhookData
)
if ($WebhookData) {
return "Finally this works"
}
Call GetResponse in a synchronized context then.
Change ...
request.BeginGetResponse((x) =>
{
using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(x))
{
using (Stream stream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(stream, Encoding.UTF8);
String responseString = reader.ReadToEnd();
}
}
}, null);
To ...
var response = (HttpWebResponse)webRequest.GetResponse();
using (Stream stream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(stream, Encoding.UTF8);
String responseString = reader.ReadToEnd();
}
note: GetResponse() waits till the underlying web request finishes, then it returns the result. no need to use BeginGetResponse() in your code context.

Convert C# from full framework to core with WebRequest

I’m not overly awesome with my C# but was hoping if someone could help me with my code snippet here.
First one works fine in C# full .net framework, the second one is where I tried to change the first over to dotnet core (standard 1.3), but it just doesn’t work and seems to barf out on “using (Stream stream = response.GetResponseStream())” with “"errorMessage": "The remote server returned an error: (400) Bad Request.", but no idea why.
I assume it has something to do with the *async calls, but really not sure.
Thanks already and help is much appreciated.
public static string AcquireTokenBySpn(string tenantId, string clientId, string clientSecret)
{
var payload = String.Format(SpnPayload, WebUtility.UrlEncode(ArmResource), WebUtility.UrlEncode(clientId),
WebUtility.UrlEncode(clientSecret));
byte[] data = Encoding.ASCII.GetBytes(payload);
var address = String.Format(TokenEndpoint, tenantId);
WebRequest request = WebRequest.Create(address);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
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())
{
if (stream != null)
using (StreamReader sr99 = new StreamReader(stream))
{
responseContent = sr99.ReadToEnd();
}
}
}
JObject jObject = JObject.Parse(responseContent);
return (string)jObject["access_token"];
}
This is the "core snippet".
public static async Task<string> AcquireTokenBySpn(string tenantId, string clientId, string clientSecret, double apiVersion)
{
var payload = String.Format(SpnPayload, WebUtility.UrlEncode(clientId),
WebUtility.UrlEncode(clientSecret));
var data = Encoding.ASCII.GetBytes(payload);
var address = String.Format(TokenEndpoint, tenantId, apiVersion);
WebRequest request = WebRequest.Create(address);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
//request. ContentLength = data.Length;
using (Stream stream = await request.GetRequestStreamAsync())
{
stream.Write(data, 0, data.Length);
}
string responseContent = null;
using (WebResponse response = await request.GetResponseAsync())
{
using (Stream stream = response.GetResponseStream())
{
if (stream != null)
using (StreamReader sr99 = new StreamReader(stream))
{
responseContent = sr99.ReadToEnd();
}
}
}
JObject jObject = JObject.Parse(responseContent);
return (string)jObject["access_token"];
}
}
The error sure is related to to GetResponseAsync(). You need to check what is happening over there.
BTW. it is much better to work with .NETCore 2.0 rather than 1.3 as it has a vere huger library support as it supports .NET Standard 2.0 libraries.

i want to make the following curl call in my C# application

i want to make the following curl call in my C# application: i beginner of code
**this code get json response of cities on facebook contain character 'a' and character 'b' from facebook graph api i tried to make it i have error The request was aborted: The connection was closed unexpectedly **
private JArray Getcities(string token)
{
try
{
string s1 = "access_token="+Server.UrlEncode(token);
string s2 = "&batch=" + Server.UrlEncode(" [ { \"method\": \"get\", \"relative_url\":\"search?type=adgeolocation&location_types=city&region_id=3871&country_code=us&limit=3000&q=a\" }, { \"method\": \"get\", \"relative_url\": \"search?type=adgeolocation&location_types=city&region_id=3871&country_code=us&limit=3000&q=b\" } ]");
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create("https://graph.facebook.com/v2.3/");//make url
httpRequest.Method = "Post";
httpRequest.ContentType = "text/json; charset=utf-8";
byte[] bytedata = Encoding.UTF8.GetBytes(s1 + s2);
httpRequest.ContentLength = bytedata.Length;
Stream requestStream = httpRequest.GetRequestStream();
requestStream.Write(bytedata,0,bytedata.Length);
requestStream.Close();
StreamReader reader;
HttpWebResponse httpWebResponse = (HttpWebResponse) httpRequest.GetResponse()
using (var responsestream = httpWebResponse.GetResponseStream())
{
reader = new StreamReader(responsestream, encoding: Encoding.UTF8);
}
var apiData = reader.ReadToEnd();
Response.Write(apiData);
var data = JArray.Parse(apiData).ToString();
//var s = data["data"].ToString();
var x = JArray.Parse(data);
return x;
}
The problem is with your using statement
using (var responsestream = httpWebResponse.GetResponseStream())
{
reader = new StreamReader(responsestream, encoding: Encoding.UTF8);
}
At the end of the using statement the stream gets disposed so it no longer works when you try read to end. It should work if you re-write like this.
byte[] apiData;
using (var responsestream = httpWebResponse.GetResponseStream())
{
reader = new StreamReader(responsestream, encoding: Encoding.UTF8);
apiData = reader.ReadToEnd();
}
Then the stream is disposed after reading all the data.

Read text from response

HttpWebRequest request = WebRequest.Create("http://google.com") as HttpWebRequest;
request.Accept = "application/xrds+xml";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
WebHeaderCollection header = response.Headers;
Here google returns text. How to read it?
Your "application/xrds+xml" was giving me issues, I was receiving a Content-Length of 0 (no response).
After removing that, you can access the response using response.GetResponseStream().
HttpWebRequest request = WebRequest.Create("http://google.com") as HttpWebRequest;
//request.Accept = "application/xrds+xml";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
WebHeaderCollection header = response.Headers;
var encoding = ASCIIEncoding.ASCII;
using (var reader = new System.IO.StreamReader(response.GetResponseStream(), encoding))
{
string responseText = reader.ReadToEnd();
}
The accepted answer does not correctly dispose the WebResponse or decode the text. Also, there's a new way to do this in .NET 4.5.
To perform an HTTP GET and read the response text, do the following.
.NET 1.1 ‒ 4.0
public static string GetResponseText(string address)
{
var request = (HttpWebRequest)WebRequest.Create(address);
using (var response = (HttpWebResponse)request.GetResponse())
{
var encoding = Encoding.GetEncoding(response.CharacterSet);
using (var responseStream = response.GetResponseStream())
using (var reader = new StreamReader(responseStream, encoding))
return reader.ReadToEnd();
}
}
.NET 4.5
private static readonly HttpClient httpClient = new HttpClient();
public static async Task<string> GetResponseText(string address)
{
return await httpClient.GetStringAsync(address);
}
I've just tried that myself, and it gave me a 200 OK response, but no content - the content length was 0. Are you sure it's giving you content? Anyway, I'll assume that you've really got content.
Getting actual text back relies on knowing the encoding, which can be tricky. It should be in the Content-Type header, but then you've got to parse it etc.
However, if this is actually XML (e.g. from "http://google.com/xrds/xrds.xml"), it's a lot easier. Just load the XML into memory, e.g. via LINQ to XML. For example:
using System;
using System.IO;
using System.Net;
using System.Xml.Linq;
using System.Web;
class Test
{
static void Main()
{
string url = "http://google.com/xrds/xrds.xml";
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
XDocument doc;
using (WebResponse response = request.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
doc = XDocument.Load(stream);
}
}
// Now do whatever you want with doc here
Console.WriteLine(doc);
}
}
If the content is XML, getting the result into an XML object model (whether it's XDocument, XmlDocument or XmlReader) is likely to be more valuable than having the plain text.
This article gives a good overview of using the HttpWebResponse object:How to use HttpWebResponse
Relevant bits below:
HttpWebResponse webresponse;
webresponse = (HttpWebResponse)webrequest.GetResponse();
Encoding enc = System.Text.Encoding.GetEncoding(1252);
StreamReader loResponseStream = new StreamReader(webresponse.GetResponseStream(),enc);
string Response = loResponseStream.ReadToEnd();
loResponseStream.Close();
webresponse.Close();
return Response;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://www.google.com");
request.Method = "GET";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string strResponse = reader.ReadToEnd();
response.GetResponseStream() should be used to return the response stream. And don't forget to close the Stream and Response objects.
If you http request is Post and request.Accept = "application/x-www-form-urlencoded";
then i think you can to get text of respone by code bellow:
var contentEncoding = response.Headers["content-encoding"];
if (contentEncoding != null && contentEncoding.Contains("gzip")) // cause httphandler only request gzip
{
// using gzip stream reader
using (var responseStreamReader = new StreamReader(new GZipStream(response.GetResponseStream(), CompressionMode.Decompress)))
{
strResponse = responseStreamReader.ReadToEnd();
}
}
else
{
// using ordinary stream reader
using (var responseStreamReader = new StreamReader(response.GetResponseStream()))
{
strResponse = responseStreamReader.ReadToEnd();
}
}

Categories