I instantiate the HttpWebRequest object:
HttpWebRequest httpWebRequest =
WebRequest.Create("http://game.stop.com/webservice/services/gameup")
as HttpWebRequest;
When I "post" the data to this service, how does the service know which web method to submit the data to?
I do not have the code to this web service, all I know is that it was written in Java.
This gets a bit complicated but it's perfectly doable.
You have to know the SOAPAction you want to take. If you don't you can't make the request. If you don't want to set this up manually you can add a service reference to Visual Studio but you will need to know the services endpoint.
The code below is for a manual SOAP request.
// load that XML that you want to post
// it doesn't have to load from an XML doc, this is just
// how we do it
XmlDocument doc = new XmlDocument();
doc.Load( Server.MapPath( "some_file.xml" ) );
// create the request to your URL
HttpWebRequest request = (HttpWebRequest)WebRequest.Create( Your URL );
// add the headers
// the SOAPACtion determines what action the web service should use
// YOU MUST KNOW THIS and SET IT HERE
request.Headers.Add( "SOAPAction", YOUR SOAP ACTION );
// set the request type
// we user utf-8 but set the content type here
request.ContentType = "text/xml;charset=\"utf-8\"";
request.Accept = "text/xml";
request.Method = "POST";
// add our body to the request
Stream stream = request.GetRequestStream();
doc.Save( stream );
stream.Close();
// get the response back
using( HttpWebResponse response = (HttpWebResponse)request.GetResponse() )
{
// do something with the response here
}//end using
Different web services engines route incoming requests to particular web services implementations differently.
You said "web services", but didn't specify the use of SOAP. I'm going to assume SOAP.
The SOAP 1.1 specification says ...
The SOAPAction HTTP request header field can be used to indicate the intent of the SOAP HTTP request. The value is a URI identifying the intent. SOAP places no restrictions on the format or specificity of the URI or that it is resolvable. An HTTP client MUST use this header field when issuing a SOAP HTTP Request.
Most web service engines comply with the spec, and therefore use the SOAPAction: header. This obviously works only with SOAP-over-HTTP transmissions.
When HTTP is not used (say, TCP, or some other), the web services engine needs to fall back on something. Many use the message payload, specifically the name of the top-level element in the XML fragment within the soap:envelope. For example, the engine might look at this incoming message:
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<soap:Body>
<m:GetAccountStatus xmlns:m="Some-URI">
<acctnum>178263</acctnum>
</m:GetAccountStatus>
</soap:Body>
</soap:Envelope>
...find the GetAccountStatus element, and then route the request based on that.
If you're trying to talk to a Java web service, then you should not use HttpWebRequest. You should use "Add Service Reference" and point it to the Java service.
Related
I can obtain the details of my http request including headers via Fiddler, however I'd like to display the value of my http request and response as part of my MVC web service to ensure the request is valid.
I want to return all of the details of the request as a string so I can return the result to the View for this specific controller.
I am using C# to create the request:
var _httpClientManager = new HttpClientManager(_httpClientPool, _Identity, _errorLogger);
_httpClientManager.HttpRequestHeaders = new Dictionary<string, string>();
_httpClientManager.HttpRequestHeaders.Add("Accept", "application/json");
... extra headers omitted.....
... url and request JSON is omitted
var response = await _httpClientManager.PostAsJsonAsync<IdentityVerificationRequest>(url, request, null);
return View(response);
Basically I'd like to obtain what I am about to Post to the server and include that in the View response.
Its probably a bit of a naïve question, I am quite new working with this.
Is it possible?
Thankyou.
How can I call HTTP GET using JSON parameters in content body?
I tried this:
HttpWebRequest.WebRequest.Create(_uri);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "GET";
httpWebRequest.Headers.Add("X-AUTH-TOKEN", _apiKey);
using(var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream())) {
string _json = "\"{\"filter\": {\"relation\": \"equals\", \"attribute\": \"state\", \"value\": \"CA\" }, \"insights\": {\"field\": \"family.behaviors\", \"calculations\": [\"fill_count\"]}}";
streamWriter.Write(_json);
streamWriter.Flush();
streamWriter.Close();
}
var httpResponse = (HttpWebResponse) httpWebRequest.GetResponse();
using(var streamReader = new StreamReader(httpResponse.GetResponseStream())) {
var result = streamReader.ReadToEnd();
}
but it throws an exception:
"Cannot send a content-body with this verb-type."
If you use .NET core, the new HttpClient can handle this. Otherwise you can use System.Net.Http.WinHttpHandler package, but it has a ton of dependencies. See answer
https://stackoverflow.com/a/47902348/1030010
for how to use these two.
I can't use .NET core and I don't want to install System.Net.Http.WinHttpHandler.
I solved it by using reflection, to trick WebRequest that it is legal to send body with a GET request (which is according to latest RFC). What I do is to set ContentBodyNotAllowed to false for HTTP verb "GET".
var request = WebRequest.Create(requestUri);
request.ContentType = "application/json";
request.Method = "GET";
var type = request.GetType();
var currentMethod = type.GetProperty("CurrentMethod", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(request);
var methodType = currentMethod.GetType();
methodType.GetField("ContentBodyNotAllowed", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(currentMethod, false);
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write("<Json string here>");
}
var response = (HttpWebResponse)request.GetResponse();
Note, however, that the attribute ContentBodyNotAllowed belongs to a static field, so when its value changes, it remains in effect for the rest of the program. That's not a problem for my purposes.
It is entirely possible, but you have to use the newer HttpClient class: https://stackoverflow.com/a/47902348/70345
Even tho it is technically allowed to send a body with Get requests, Microsoft has decided for you that you cannot do that.
This can be seen in HttpWebRequest source code:
if (onRequestStream) {
// prevent someone from getting a request stream, if the protocol verb/method doesn't support it
throw new ProtocolViolationException(SR.GetString(SR.net_nouploadonget));
}
So you need to change your verb to Put or Post or have some other workaround.
GET will only receive it.
If you need to specify parameters, please include it in url.
Or you can send JSON BODY if POST or PUT.
HTTP request methods
HTTP defines a set of request methods to indicate the desired action to be performed for a given resource. Although they can also be nouns, these request methods are sometimes referred as HTTP verbs. Each of them implements a different semantic, but some common features are shared by a group of them: e.g. a request method can be safe, idempotent, or cacheable.
GET
The GET method requests a representation of the specified resource. Requests using GET should only retrieve data.
HEAD
The HEAD method asks for a response identical to that of a GET request, but without the response body.
POST
The POST method is used to submit an entity to the specified resource, often causing a change in state or side effects on the server.
PUT
The PUT method replaces all current representations of the target resource with the request payload.
In Addition:
I found this. Long discussion has been held.
HTTP GET with request body
What this means is that it is possible to send BODY with GET, but sending a payload body on a GET request might cause some existing implementations to reject the request (such as Proxy in the middle of the route).
Please be sure to read this article carefully as there are many other points to pay attention to.
By the way, it seems that you can send GET with body using the -i option of cURL command.
Curl GET request with json parameter
I am getting this error. When i call the c# WebService using HttpWebRequest.
System.Web.Services.Protocols.SoapException: Unable to handle request without a valid action parameter. Please supply a valid soap action.
from wsdl i found the soap action and i added in the request, still it is showing the error
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:33333/AccountService.asmx");
request.Method = "POST";
request.ContentType = "text/xml";
request.Accept = "text/xml";
request.Headers.Add("SOAPAction", "https://ttt/test.aspx"
Thanks
The action is specified by the url you post the soap envelope to. Chances are the url either has a typo or you are trying to execute an action that the SOAP service doesn't understand. Check the WSDL for the service and make sure you are calling the proper action.
request.Headers.Add("SOAPAction", "https://ttt/test.aspx/methodname")
Method name should be specified after 'test.aspx/' in above URL.
I'm having problems with sending POST request in C# and it seems I misunderstood some HTTP basics. So basically I'm implementing RESTfull service client, which work as follows:
Make POST request with username/password and get token
Use this token in header (Authorization:TOKEN) while making other GET/POST/PUT requests
I use WebRequest to make GET requests (with Authorization header) and it's working. But when I use following code to make PUT requests, service is giving "Authentication failed - not logged in" message back:
String url = String.Format("{0}/{1}", AN_SERVER, app);
WebRequest theRequest = WebRequest.Create(url);
theRequest.Method = "POST";
theRequest.ContentType = "text/x-json";
theRequest.ContentLength = json.Length;
Stream requestStream = theRequest.GetRequestStream();
requestStream.Write(Encoding.ASCII.GetBytes(json), 0, json.Length);
requestStream.Close();
theRequest.Headers.Add("Authorization", authToken);
HttpWebResponse response = (HttpWebResponse)theRequest.GetResponse();
I must be making minor mistake (at least I hope so) while sending POST request. So what am I doing wrong?
Thanks.
Moving Headers before the request steam works (as per AI W's comment), because the request stream is adding the body.
The way webrequest is implemented internally, you need to finish the header before writing body, and once its in stream format, its ready to send.
If you look at the implementation of webrequest in reflector or some such decompiling tool, you'll be able to see the logic.
Hope this helps
i need to visit a secure web service,
every request in the header need to carry a token.
i know the endpoint to the web service,
i also know how to create the token.
but i cannot see the WSDL for the webservice.
is there a way in C#, to create a soap client, without the WSDL file.
I have verified that this code, which uses the HttpWebRequest class, works:
// Takes an input of the SOAP service URL (url) and the XML to be sent to the
// service (xml).
public void PostXml(string url, string xml)
{
byte[] bytes = Encoding.UTF8.GetBytes(xml);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentLength = bytes.Length;
request.ContentType = "text/xml";
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
if (response.StatusCode != HttpStatusCode.OK)
{
string message = String.Format("POST failed with HTTP {0}",
response.StatusCode);
throw new ApplicationException(message);
}
}
}
You will need to create the proper SOAP envelope and pass that in as the "xml" variable. It takes some reading. I found this SOAP Tutorial to be helpful.
A SOAP client is simply an HTTP client with more stuff in it. See the HttpWebRequest class. You'll then have to create your own SOAP message, perhaps using XML Serialization.
You could create your own service, expose it to have a WSDL and then generate the client from that... kind of the long way.
Can you ask the developers of the web service to send you the WSDL and XSD file(s) by email? If so, you can dump the files in a folder and then add a Service Reference using the WSDL on your hard disk.