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);
}
}
Related
I have service client application written in C# where I create a service request as a soap XML as following:
var _url = "http://localhost:8082/tartsend";
var _action = "http://rep.oio.no/getTest";
StartSend startSend = new tartSend();
Envelope soapEnvelopeXml = StartSend.StartSendMethod();
HttpWebRequest webRequest = CreateWebRequest(_url, _action);
InsertSoapEnvelopeIntoWebRequest(soapEnvelopeXml, webRequest);
IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);
asyncResult.AsyncWaitHandle.WaitOne();
string soapResult;
using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult))
{
using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
{
soapResult = rd.ReadToEnd();
}
Console.Write(soapResult);
}
}
private static XmlDocument CreateSoapEnvelope()
{
XmlDocument soapEnvelopeDocument = new XmlDocument();
return soapEnvelopeDocument;
}
private static HttpWebRequest CreateWebRequest(string url, string action)
{
HttpWebRequest 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 void InsertSoapEnvelopeIntoWebRequest(Envelope soapEnvelopeXml,
HttpWebRequest webRequest)
{
var xmlString = string.Empty;
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Envelope));
var path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) +
"//Sendservice.xml";
System.IO.FileStream file = System.IO.File.Create(path);
using (StringWriter textWriter = new StringWriter())
{
xmlSerializer.Serialize(file, soapEnvelopeXml);
xmlString = textWriter.ToString();
}
Console.WriteLine(xmlString);
}
Envelop is the class object that contains the Body, Header, and the other objects/ attributes. I serialize it in "InsertSoapEnvelopeIntoWebRequest" method and send it to the service side.
the server side is a simple method that suppose to send OK as response and nothing else. The server side service code is in jave spring boot as following:-
#SpringBootApplication
#EnableWebMvc
#RestController
public class TestController {
#RequestMapping(value = "/getslutsend", method=RequestMethod.GET,
consumes={MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE,
MediaType.APPLICATION_JSON_VALUE, MediaType.TEXT_PLAIN_VALUE})
public ResponseEntity<?> readFromtest(#RequestBody String test) {
return new ResponseEntity<String>(HttpStatus.OK);
}
public static void main(String[] args) {
SpringApplication.run(TestController.class, args);
}
}
I'm not sure what I'm doing wrong to get the above errors mentioned in the title of this post. I get " (405) Method Not Allowed" and Request method not supported.
You have the RequestMethod.GET in your request mapping and the #RequestBody in parameter annotation.
Normally, you should avoid this combination, please use either RequestMethod.POST with #RequestBody, or RequestMethod.GET without the #RequestBody.
I am unable to hit a SOAP 1.2 web service with C# code. I followed the code in this example, Web Service SOAP Call
It does not work for me. My web service URL works in SOAPUI but I can't get a response in my C# code. I get a "500 Internal error." The status reads "ProtocolError."
I am running this from my Visual Studio 2017 editor.
using System;
using System.IO;
using System.Net;
using System.Xml;
namespace testBillMatrixConsole
{
class Program
{
static void Main(string[] args)
{
string _url = #"https://service1.com/MSAPaymentService/MSAPaymentService.asmx";
var _action = #"http://schemas.service1.com/v20060103/msapaymentservice/AuthorizePayment";
try
{
XmlDocument soapEnvelopeXml = CreateSoapEnvelope();
HttpWebRequest webRequest = CreateWebRequest(_url, _action);
InsertSoapEnvelopeIntoWebRequest(soapEnvelopeXml, webRequest);
// begin async call to web request.
IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);
// suspend this thread until call is complete. You might want to
// do something usefull here like update your UI.
asyncResult.AsyncWaitHandle.WaitOne();
// get the response from the completed web request.
string soapResult;
using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult))
{
using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
{
soapResult = rd.ReadToEnd();
}
Console.Write(soapResult);
}
}
catch (WebException ex)
{
throw;//ex.Message.ToString();
}
}
private static XmlDocument CreateSoapEnvelope()
{
XmlDocument soapEnvelopeDocument = new XmlDocument();
soapEnvelopeDocument.LoadXml(#"<soap:Envelope xmlns:soap=""http://www.w3.org/2003/05/soap-envelope"" xmlns:msap=""http://schemas.service1.com/v20060103/msapaymentservice""><soap:Body><msap:AuthorizePayment><!--Optional:--><msap:clientPaymentId>?</msap:clientPaymentId><msap:amount>?</msap:amount><msap:method>?</msap:method><!--Optional:--><msap:parameters><!--Zero or more repetitions:--><msap:PaymentParameter><!--Optional:--><msap:Name>?</msap:Name><!--Optional:--><msap:Value>?</msap:Value></msap:PaymentParameter></msap:parameters></msap:AuthorizePayment></soap:Body></soap:Envelope>");
return soapEnvelopeDocument;
}
private static HttpWebRequest CreateWebRequest(string url, string action)
{
HttpWebRequest 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 void InsertSoapEnvelopeIntoWebRequest(XmlDocument soapEnvelopeXml, HttpWebRequest webRequest)
{
using (Stream stream = webRequest.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
}
}
}
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;
}
I am using the following code to get the json result from the service. It works fine for get methods. But when the method type is POST the request address changes to the previous address.
ie;
on the first call to this method the request.address=XXXXX.com:1234/xxx/oldv1.json (method type is get)
and it returns a json string from which I extract another address:XXXXX.com:1234/xxx/newv1.json
and now I call the makerequest method with this endpoint and method type POST, contenttype="application/x-www-form-urlencoded".
When I put breakpint at using (var response = (HttpWebResponse)request.GetResponse()) and checked the request.address value, it was XXXXX.com:1234/xxx/newv1.json
But after that line is executed, the address changes to XXXXX.com:1234/xxx/oldv1.json and the function returns the same response I got with the first Endpoint(XXXXX.com:1234/xxx/oldv1.json).
Can anybody tell what I am doing wrong here?
Is there any better method to consume the service with POST method?
public string MakeRequest(string EndPoint,string Method, string contentType)
{
var request = (HttpWebRequest)WebRequest.Create(EndPoint);
request.Method = Method;
request.ContentLength = 0;
request.ContentType =contentType;
if ( Method == HttpVerb.POST)
{
var encoding = new UTF8Encoding();
var bytes = Encoding.GetEncoding("iso-8859-1").GetBytes("username=123&password=123");
request.ContentLength = bytes.Length;
using (var writeStream = request.GetRequestStream())
{
writeStream.Write(bytes, 0, bytes.Length);
}
}
using (var response = (HttpWebResponse)request.GetResponse())// request.address changes at this line on "POST" method types
{
var responseValue = string.Empty;
if (response.StatusCode != HttpStatusCode.OK)
{
var message = String.Format("Request failed. Received HTTP {0}", response.StatusCode);
throw new ApplicationException(message);
}
// grab the response
using (var responseStream = response.GetResponseStream())
{
if (responseStream != null)
using (var reader = new StreamReader(responseStream))
{
responseValue = reader.ReadToEnd();
}
}
return responseValue;
}
EDIT: Yesterday I asked THIS Question about consuming the service at client side and many suggested it needs to be done at server side as the other domain might not allow accessing the json result at client side.
The issue was about cookies. As I forgot to set the cookies, the request was getting redirected. I had to set cookie container by using
request.CookieContainer = new CookieContainer();
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.