I am currently writing a C# web service which has several methods, one of which has to receive HTTP POST requests. The first thing i have done is alter the web.config file in the web service project as below.
<webServices>
<protocols>
<add name="HttpSoap"/>
<add name="HttpPost"/>
<add name="HttpPostLocalhost"/>
<add name="Documentation"/>
</protocols>
</webServices>
I can run the web service locally and when i click on the method in the browser, i can see it handles HTTP POST requests and accepts args=string, as my signature of the web method accepts one string parameter named args. I am then testing this via a test ASP.NET app using the code below to fire the HTTP POST request.
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(ConfigurationManager.AppSettings["PaymentHubURL"].ToString());
request.KeepAlive = false;
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
StringBuilder sb = new StringBuilder();
sb.Append("message_type=");
sb.Append(HttpUtility.UrlEncode("Txn_Response"));
byte[] bytes = UTF8Encoding.UTF8.GetBytes(sb.ToString());
request.ContentLength = bytes.Length;
using (Stream postStream = request.GetRequestStream())
{
postStream.Write(bytes, 0, bytes.Length);
}
string test;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
StreamReader reader = new StreamReader(response.GetResponseStream());
test = reader.ReadToEnd();
}
But when i run this i get "The remote server returned an error: (500) Internal Server Error". If i remove the parameter, by removing the stringbuilder and byte code, as well as having no parameter in the web service, it works. So it is obviously a problem with the parameters. I actually want to send more data, and was using a string[] parameter in the web service, but this also failed.
Can anyone help??
I would suggest that you reconsider your approach. Microsoft has written pretty awesome libraries for consuming web services, but there are two ways to do it - "add web reference" and "add service reference".
In your case, it seems you have an "asmx web service" so I would recommend that you add a "web reference" to you project in visual studio. This is assuming you are using visual studio.
After you add this web reference, you can create your client by "new"-ing it. You can the execute any web method on this client. This is the easiest way to consume web services. You do not have to deal with any http complications.
Hope this helps.
I can guess you are building the HttpPost request wrongly.
Try to use the code showed at the link below to create your request:
http://msdn.microsoft.com/en-us/library/debx8sh9.aspx
Or probabily the response doesn't contain unicode char value
try to copy and paste this code to get the response
System.Text.Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
StreamReader objSR;
webResponse = (HttpWebResponse)response.GetResponse();
StreamReader reader = webResponse.GetResponseStream();
objSR = new StreamReader(objStream, encode, true);
sResponse = objSR.ReadToEnd();
Related
I am trying to patch a .net web application that after years of working started failing to get UPS shipping quotes, which is impacting web business dramatically. After much trial and error, I found the following code that works just fine in a console application:
static string FindUPSPlease()
{
string post_data = "<xml data string>";
string uri = "https://onlinetools.ups.com/ups.app/xml/Rate";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version10;
byte[] postBytes = Encoding.ASCII.GetBytes(post_data);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postBytes.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Close();
// get response and send to console
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Console.WriteLine(new StreamReader(response.GetResponseStream()).ReadToEnd());
Console.WriteLine(response.StatusCode);
return "done";
}
This runs in Visual Studio just fine and gets a nice little response from UPS that the XML is, of course, malformed.
But, if I paste this function into the web application without changing a single character, an exception is thrown on request.GetRequestStream():
Authentication failed because the remote party has closed the transport stream.
I tried it in a couple of different place in the application with the same result.
What is there about the web application environment that would affect the request?
It turns out to be a TLS issue. I guess the console app uses a higher protocol by default than the web application, although none was specified. So, all you have to do is add the following line(s) of code sometime prior to making the request:
using System.Net;
...
System.Net.ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
That was all it took, though I spent an enormous amount of getting there.
Here is the response from UPS on the issue:
Effective January 18, 2018, UPS will only accept TLS 1.1 and TLS 1.2 security protocols... 100% of requests from customers who are on TLS 1.0 while using production URLS (onlinetools.ups.com/tool name) will be rejected.
Anyway, hope this helps someone.
Jim
Can you try setting the Credentials to your request object like following.
request.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
Try setting the default credentials or check if there is any proxy server set and pass it like in the example below.
The example is given for WebClient.
I was having problem with setting Default Credential, as proxy was enabled on the server. So i passed the proxy URL and port with credentials which can access it.
using (System.Net.WebClient web = new System.Net.WebClient())
{
//IWebProxy defaultWebProxy = WebRequest.DefaultWebProxy;
//defaultWebProxy.Credentials = CredentialCache.DefaultCredentials;
//web.Proxy = defaultWebProxy;
var proxyURI = new Uri(string.Format("{0}:{1}", proxyURL, proxyPort));
//Set credentials
System.Net.ICredentials credentials = new System.Net.NetworkCredential(proxyUserId, proxyPassword);
//Set proxy
web.Proxy = new System.Net.WebProxy(proxyURI, true, null, credentials);
web.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
var result = web.UploadString(URL, "");
return result;
}
This is not a subject I am strong in so I apologize ahead of time if I say something ridiculous.
I have developed an HTTP service using Mule. I have it functioning perfectly when I connect directly to the service and send data using a test harness I wrote in C#.
As the final part of my testing, I need to send it to an HTTPS URL that is supposed to "decrypt" the message and forward it to my service. When I send a message to the HTTPS URL, it gets forwarded to my service but the message contents appear empty and therefore does not get processed. I understand that I may have to add some "encryption" to my Test Harness but I have been researching how to do this all day and nothing I have found is answering my question.
Here is an example of the code I am using for the simple HTTP request:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(ConfigurationManager.AppSettings["HttpDestination"].ToString());
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = data.Length;
using (Stream strm = req.GetRequestStream())
{
strm.Write(data, 0, data.Length);
}
HttpWebResponse response = (HttpWebResponse)req.GetResponse();
What do I need to change here to make this work?
Here is the solution that I discovered here. I needed to add the following line:
req.ProtocolVersion = System.Net.HttpVersion.Version10;
Without this, a timeout was occurring when getting the request stream and the content was never being sent, only the headers.
So this is my situation. I have to consume a third party web service (not wcf) from another WCF service that will serve as an intermediary between the first service and my web app. The problem is almost every example I have seen on doing this requieres you to Add Web/Service Reference to the app in order to generate the proxy, but I can't add the reference, it returns an error, possibly due to some authentication required.
This service can be consumed only by either GET or POST. I was successful in consuming the service by both GET and POST from an ajax call with jquery in a web page, but I don't know how to consume the service from inside a wcf service in c#.
An example GET request from the service is:
http://webservice.server.com/services/myservice?user=[username]&password=[password]&value1=[somevalue]&value2=[anothervalue]
The response is an xml with the status code of the operation and a status message, which I then proceed to save to a database.
How might I go about doing this?
Thank you for any help...
SOLUTION
Thanks to Sean for pointing me in the right direction. How I did it:
Reference article: How to use HttpWebRequest to send POST request to another web server
ASCIIEncoding encoding = new ASCIIEncoding();
string postData = "username=" + username;
postData += ("&password=" + password);
postData += ("&value1=" + val1);
postData += ("&value2=" + val2);
byte[] data = encoding.GetBytes(postData);
// Prepare POST web request...
HttpWebRequest myRequest =
(HttpWebRequest)WebRequest.Create(new Uri("http://webservice.server.com/services/myservice"));
myRequest.Method = "POST";
myRequest.ContentType = "application/x-www-form-urlencoded";
myRequest.ContentLength = data.Length;
Stream newStream = myRequest.GetRequestStream();
// Send the data.
newStream.Write(data, 0, data.Length);
newStream.Close();
// Get response
using (HttpWebResponse response = myRequest.GetResponse() as HttpWebResponse)
{
// Get the response stream
StreamReader reader = new StreamReader(response.GetResponseStream());
// Read the whole contents and return as a string
result = reader.ReadToEnd();
}
XDocument doc = XDocument.Parse(result);
// Read XML
Please if you have any comments on my solution, objections or improvements, all comments are welcomed.
I think you'd want to take a look at the HttpRequest class:
http://msdn.microsoft.com/en-us/library/system.web.httprequest.aspx
If you can't add the web service reference (I would investigate further why you can't do this first) I am afraid you'll have to do this manually issuing an HTTP Request manually using the WebClient class WebClient or the HttpReqest class as Sean suggests
Do I need to just slap some random garbage data in a WebRequest object to get by the HTTP status code 411 restriction on IIS?
I have an HttpPost action method in an MVC 3 app that consumes a POST request with all the relevant information passed in the querystring (no body needed).
[HttpPost] public ActionResult SignUp(string email) { ... }
It worked great from Visual Studio's built in web host, Cassini. Unfortunately, once the MVC code was live on IIS [7.5 on 2008 R2], the server is pitching back an HTTP error code when I hit it from my outside C# form app.
The remote server returned an error:
(411) Length Required.
Here is the calling code:
WebRequest request = WebRequest.Create("http://somewhere.com/signup/?email=a#b.com");
request.Method = "POST";
using (WebResponse response = request.GetResponse())
using (Stream responseStream = response.GetResponseStream())
using (StreamReader responseReader = new StreamReader(responseStream)) {
// Do something with responseReader.ReadToEnd();
}
Turns out you can get this to go through by simply slapping an empty content length on the request before you send it.
WebRequest request = WebRequest.Create("http://somewhere.com/signup/?email=a#b.com");
request.Method = "POST";
request.ContentLength = 0;
Not sure how explicitly giving an empty length vs. implying one makes a difference, but IIS was happy after I did. There are probably other ways around this, but this seems simple enough.
I believe you are required to set a Content-Length header anytime you post a request to a web server:
http://msdn.microsoft.com/en-us/library/system.web.httprequest.contentlength.aspx
You could try a GET request to test it.
I'm attempting to use Fogbugz's BugzScout in order to automatically submit unhanded application exceptions to my Fogbugz on demand Account. I've written up a wrapper class for it and everything appears to be just groovy - on my box. Testing the same code in the production environment, behind a Proxy that requires authentication, I have had nothing but issues.
I went to work modifying the BugzScout code in order to get it to authenticate with the Proxy, and after trying many different methods suggested via a Google search, found one that works! But now I'm getting an "Connection actively refused" error from Fogbugz itself, and I don't know what to do.
Here is the code where the BugzScout connects via a .net WebClient to submit a new case, with my modifications to deal with our Proxy. What am I doing that would cause Fogbugz to refuse my request? I've removed all non web-client related code from the procedure for ease of reading.
public string Submit(){
WebClient client = new WebClient();
WebProxy proxy = new WebProxy();
proxy.UseDefaultCredentials = true;
client.Proxy = proxy;
Byte[] response = client.DownloadData(fogBugzUrl);
string responseText = System.Text.Encoding.UTF8.GetString(response);
return (responseText == "") ? this.defaultMsg : responseText;
}
The url is correct and the case is filled in properly- this has been verified.
EDIT: Additional info.
Using Fogbugz on Demand.
Using FogBugz.net code in it's entirety, with only these additions
WebProxy proxy = new WebProxy();
proxy.UseDefaultCredentials = true;
client.Proxy = proxy;
Error occurs when attempting to connect to both https://oursite.fogbugz.com/scoutsubmit.asp and http://oursite.fogbugz.com//scoutsubmit.asp (except one says port 443, and the other port 80, obviously)
I don't know anything about web authentication so I can't tell you what kind I'm using- if you tell me where to look I'd be happy to answer that for you.
Got the fix from Fogbugz- this is the appropriate network code to get though the proxy authentication and not mis-authenticate with Bugzscout.
WebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultNetworkCredentials;
WebRequest request = WebRequest.Create(fogBugzUrl);
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
request.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials;
Stream requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
Is your fogbugzUrl using HTTP Basic Authentication? Is it SSL (hosted on On Demand?)
The connection actively refused message would be coming from the web server itself, not really FogBugz.
Can you post the HTTP Status Code?
One thing to note if you are using FogBugz On Demand is you HAVE to use the https:// url (not the http url).