Http request to web service in java - c#

I have the following method in a C# project which builds a web request to consume a web service:
private HttpWebRequest BuildRequest(string fullUri, object param, RequestMethod method, Dictionary<string, string> requestHeaders)
{
HttpWebRequest request = WebRequest.Create(fullUri) as HttpWebRequest;
request.Method = method.ToString().ToUpper();
request.Accept = "application/json";
request.ContentType = "application/json";
foreach (var h in requestHeaders)
{
request.Headers.Add(string.Format("{0}: {1}", h.Key, h.Value));
}
if (method == RequestMethod.Post)
{
JavaScriptSerializer ser = new JavaScriptSerializer();
string postData = ser.Serialize(param);
request.ContentLength = postData.Length;
Stream s = request.GetRequestStream();
StreamWriter sw = new StreamWriter(s);
sw.Write(postData);
sw.Flush();
}
return request;
}
Now I am wanting to do the same thing in Java but cant quite figure out how. So far I have...
private HttpRequestBase BuildRequest(String fullUri, Object param,
RequestMethod method, HashMap<String, String> requestHeaders) {
HttpRequestBase request = null;
if(method == RequestMethod.GET) {
request = new HttpGet(fullUri);
} else if (method == RequestMethod.POST) {
request = new HttpPost(fullUri);
}
request.addHeader(new BasicHeader("Accept", "application/json"));
request.addHeader(new BasicHeader("ContentType", "application/json"));
for(Map.Entry<String, String> header : requestHeaders.entrySet()) {
request.addHeader(new BasicHeader(header.getKey(), header.getValue()));
}
return request;
}
As far as I can tell that looks like it will work but I need to get the request stream like I do in the C# version in order to send an object as json but cant see how to get it. So my question is how to get it from a HttpRequestBase or any other object that I can use to build a HttpRequest in java.
Thanks.
FYI.. RequestMethod is an Enum either GET or POST"
And this is in an android application so I am able to use anything in the android sdk.

Related

Why does request.Headers.Add("Cookie", "...") have no effect? [duplicate]

I am trying to unit test some code, and I need to to replace this:
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create( uri );
httpWebRequest.CookieContainer = new CookieContainer();
with
WebRequest webRequest = WebRequest.Create( uri );
webRequest.CookieContainer = new CookieContainer();
Basically, how do I get cookies into the request without using a HttpWebRequest?
Based on your comments, you might consider writing an extension method:
public static bool TryAddCookie(this WebRequest webRequest, Cookie cookie)
{
HttpWebRequest httpRequest = webRequest as HttpWebRequest;
if (httpRequest == null)
{
return false;
}
if (httpRequest.CookieContainer == null)
{
httpRequest.CookieContainer = new CookieContainer();
}
httpRequest.CookieContainer.Add(cookie);
return true;
}
Then you can have code like:
WebRequest webRequest = WebRequest.Create( uri );
webRequest.TryAddCookie(new Cookie("someName","someValue"));
Try with something like this:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.contoso.com/default.html");
request.CookieContainer = new CookieContainer();
request.CookieContainer.Add(new Cookie("ConstoCookie", "Chocolate Flavour"));
WebRequest is an abstract class that does not have a CookieContainer property. In addition you can't use the Headers collection (not implemented exception) so any attempt like webRequest.Headers.Add("Cookie", "...") will fail.
Sorry, but you have no chance to use cookies with WebRequest.
Stick on HttpWebRequest and add/edit as many cookies you like using its Headers collection!
dlev's answer ended up working, but I had problems implementing the solution ("The parameter '{0}' cannot be an empty string."), so I decided to write the full code in case anybody else has similar problems.
My goal was to get the html as a string, but I needed to add the cookies to the web request. This is the function that downloads the string using the cookies:
public static string DownloadString(string url, Encoding encoding, IDictionary<string, string> cookieNameValues)
{
using (var webClient = new WebClient())
{
var uri = new Uri(url);
var webRequest = WebRequest.Create(uri);
foreach(var nameValue in cookieNameValues)
{
webRequest.TryAddCookie(new Cookie(nameValue.Key, nameValue.Value, "/", uri.Host));
}
var response = webRequest.GetResponse();
var receiveStream = response.GetResponseStream();
var readStream = new StreamReader(receiveStream, encoding);
var htmlCode = readStream.ReadToEnd();
return htmlCode;
}
}
We are using the code from dlev's answer:
public static bool TryAddCookie(this WebRequest webRequest, Cookie cookie)
{
HttpWebRequest httpRequest = webRequest as HttpWebRequest;
if (httpRequest == null)
{
return false;
}
if (httpRequest.CookieContainer == null)
{
httpRequest.CookieContainer = new CookieContainer();
}
httpRequest.CookieContainer.Add(cookie);
return true;
}
This is how you use the full code:
var cookieNameValues = new Dictionary<string, string>();
cookieNameValues.Add("varName", "varValue");
var htmlResult = DownloadString(url, Encoding.UTF8, cookieNameValues);

My request body is encoded in UTF-8 which causes a web service to deny it. What are my options?

I am trying to obtain a token from a Web Service (Salesforce Commerce Cloud) however because my web client is encoding the request in UTF-8, the Content-Length is coming up as 82 characters.. not 79. Because of this, the web service is throwing an error.
I tried changing the header to application/x-www-form-urlencoded; charset=utf-8 however that had no effect.
If I change my WebClient from new StreamWriter(webRequest.GetRequestStream(), Encoding.UTF8)) to new StreamWriter(webRequest.GetRequestStream(), Encoding.ASCII)), the request is successful, however I am reluctant to change that because I have other things using that WebClient and don't yet know how they will handle that change.
Without adding overloads or anything to my WebClient, is there another generally accepted practice for telling the remote web service to encoding of my data that may make it accept it? I'm assuming this largely depends on the implementation of the web service itself.
This is the method I'm using for sending the request:
public HttpResponseData SendRequestWithBody(HttpMethod httpMethod, string url, Dictionary<string, string> headers, string contentType, string body)
{
logger.InfoFormat("Sending {0} request to url={1}", httpMethod.Method, url);
HttpWebRequest webRequest = CreateHttpWebRequest(url, headers);
webRequest.ContentType = contentType;
webRequest.Method = httpMethod.Method;
ServicePointManager.Expect100Continue = true;
if (this.webRequestLogger != null)
{
webRequestLogger.LogRequest(webRequest, webClientRequestLoggerTime, body);
}
using (StreamWriter streamWriter = new StreamWriter(webRequest.GetRequestStream(), Encoding.ASCII))
{
streamWriter.Write(body);
streamWriter.Flush();
}
HttpWebResponse httpWebResponse = (HttpWebResponse)webRequest.GetResponse();
HttpResponseData httpResponseData = CreateHttpResponseData(httpWebResponse);
if (this.webRequestLogger != null)
{
webRequestLogger.LogResponse(httpResponseData, webClientRequestLoggerTime);
}
return httpResponseData;
}
private HttpWebRequest CreateHttpWebRequest(string requestUrl, Dictionary<string, string> headers)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(requestUrl);
webRequest.Timeout = requestTimeoutInSeconds * 1000;
if (headers != null && headers.Count > 0)
{
foreach (KeyValuePair<string, string> header in headers)
{
if (header.Key == HttpHeaderContentTypeName)
webRequest.ContentType = header.Value;
else if (header.Key == HttpHeaderAcceptName)
webRequest.Accept = header.Value;
else
webRequest.Headers.Add(header.Key, header.Value);
}
}
return webRequest;
}

Expecting JSON/XML data in Webapi

when i request one webapi request, i got error like Expecting JSON/XML data
try
{
string oRequest = _xml.UpdateInvereqxml(UserName, Password,OTAhotelid, Invy);
string uri = #"service/update";
System.Net.WebRequest req = System.Net.WebRequest.Create(uri);
req.Method = "POST";
req.ContentType = "text/xml";
System.IO.StreamWriter writer = new System.IO.StreamWriter(req.GetRequestStream());
writer.WriteLine(oRequest);
writer.Close();
System.Net.WebResponse rsp = req.GetResponse();
Stream istrm = rsp.GetResponseStream();
string StreamReader = new StreamReader(istrm).ReadToEnd();
}
I suggest using HttpClient to communicate with ASP.NET Web API. The class provides many functions for working with REST service (example)
public EnumProduct Post(EnumProduct product)
{
HttpResponseMessage reponse = httpClient.PostAsJsonAsync("api/enumproducts/Post", product).Result;
if (reponse.IsSuccessStatusCode)
{
var enumProduct = reponse.Content.ReadAsAsync().Result;
return enumProduct;
}
else
return null;
}

How can I call a SOAP Web Service without Adding Web Reference

I require developing a .NET 4.5 Client for a SOAP based web service. The problem is the company who are developing these SOAP based services do not provide WSDLs. However they do provide the request response schemas (XSD files). Since there are no WSDLs I'm unable to add a web reference and get the client proxy code autogenerated.
Are there any .NET 4.5 libraries out there that I can use to make these SOAP base service calls? It needs to support SOAP 1.1 and SOAP attachements too.
If for some reason you don't want to create the WSDL file, the example below could be used to manually construct a SOAP HTTP request:
var url = Settings.Default.URL; //'Web service URL'
var action = Settings.Default.SOAPAction; //the SOAP method/action name
var soapEnvelopeXml = CreateSoapEnvelope();
var soapRequest = CreateSoapRequest(url, action);
InsertSoapEnvelopeIntoSoapRequest(soapEnvelopeXml, soapRequest);
using (var stringWriter = new StringWriter())
{
using (var xmlWriter = XmlWriter.Create(stringWriter))
{
soapEnvelopeXml.WriteTo(xmlWriter);
xmlWriter.Flush();
}
}
// begin async call to web request.
var asyncResult = soapRequest.BeginGetResponse(null, null);
// suspend this thread until call is complete. You might want to
// do something usefull here like update your UI.
var success = asyncResult.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(5));
if (!success) return null;
// get the response from the completed web request.
using (var webResponse = soapRequest.EndGetResponse(asyncResult))
{
string soapResult;
var responseStream = webResponse.GetResponseStream();
if (responseStream == null)
{
return null;
}
using (var reader = new StreamReader(responseStream))
{
soapResult = reader.ReadToEnd();
}
return soapResult;
}
private static HttpWebRequest CreateSoapRequest(string url, string action)
{
var webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Headers.Add("SOAPAction", action);
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
return webRequest;
}
private static XmlDocument CreateSoapEnvelope()
{
var soapEnvelope = new XmlDocument();
soapEnvelope.LoadXml(Settings.Default.SOAPEnvelope); //the SOAP envelope to send
return soapEnvelope;
}
private static void InsertSoapEnvelopeIntoSoapRequest(XmlDocument soapEnvelopeXml, HttpWebRequest webRequest)
{
using (Stream stream = webRequest.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
}

WebRequest BeginGetRequestStream and BeginGetResponse do not fire their callbacks

I have a PHP web service using JSON that I need to post requests to from a Silverlight application. I had used the HttpWebRequest class before, in a regular C# application and it worked flawlessly. In my Silverlight application, however, the callbacks for the BeginGetRequestStream and BeginGetResponse methods are not getting called.
I tried testing it out in about every way without success. Note that the data I am sending is not long - just a 32 character string most of the time. I checked if the callbacks were getting called at all, and they weren't being called. Here is my code:
public void Request(Command cmd, Dictionary<string, string> data)
{
Dictionary<string, object> fullRequest = new Dictionary<string,object>();
HttpWebRequest request = WebRequest.Create(address) as HttpWebRequest;
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
StringWriter writer = new StringWriter(new StringBuilder());
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(writer, fullRequest);
string query = "query=" + writer.ToString();
request.ContentLength = query.Length;
request.ContentType = "text/json";
_queue.Enqueue(new KeyValuePair<Command, string>(cmd, query));
request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), request);
public void GetRequestStreamCallback(IAsyncResult target)
{
HttpWebRequest request = (HttpWebRequest)target.AsyncState;
Stream postStream = request.EndGetRequestStream(target);
string postData = "";
//not sure why I have to do this. in the Silverlight documentation
//Queue<> is supposed to have the SyncRoot property
//but I get an error if I just try _queue.SyncRoot
lock ((_queue as ICollection).SyncRoot)
{
postData = _queue.Dequeue().Value;
}
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
postStream.Write(byteArray, 0, postData.Length);
postStream.Close();
request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
public void GetResponseCallback(IAsyncResult result)
{
HttpWebRequest request = (HttpWebRequest)result.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
Stream streamResponse = response.GetResponseStream();
StreamReader streamRead = new StreamReader(streamResponse);
string responseString = streamRead.ReadToEnd();
streamResponse.Close();
streamRead.Close();
response.Close();
JsonSerializer serializer = new JsonSerializer();
Dictionary<string, object> responseData = new Dictionary<string, object>();
responseData = (Dictionary<string, object>)serializer.Deserialize(new StringReader(responseString), typeof(Dictionary<string, object>));
if (_data.ContainsKey(responseData["key"] as string))
{
_data[responseData["key"] as string] = responseData;
}
else
{
_data.Add(responseData["key"] as string, responseData);
}
I also tried this:
IAsyncResult resultRequest = request.BeginGetRequestStream(null, null) as IAsyncResult;
Stream postStream = request.EndGetRequestStream(resultRequest );
To get the stream synchronously (yes, bad style, I just wanted to see if it will work). No success .
Thanks in advance.

Categories

Resources