.NET Soap request to Web service - Action not happening - c#

I've searched and found lots on this topic, but I'm just not getting this to work. My request returns the HTML from asmx page that displays the web method (action), but does not perform the action, which basically returns a true/false.
I'm using the same SOAP 1.1 that my method provides. And, when I test the functionality by using the "Invoke" button provided it works just fine. But I really need to call this function behind-the-scenes so I can't use the HTTP Post like this button. Any ideas?
.cs code in App_Code directory of website:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Text;
using System.Web.Caching;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
[WebService(Namespace = "http://www.xxx.org/")]
public class VacationSickPayoutLogger : System.Web.Services.WebService
{
[WebMethod]
public string RunVacationSickPayoutWS()
{
return "True";
}
}
Code from asmx file:
<%# WebService Language="C#" CodeBehind="~/App_Code/VacationSickPayoutLogger.cs" Class="VacationSickPayoutLogger" %>
Code to call web method:
protected void Page_Load(object sender, EventArgs e)
{
string soap =
#"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
<soap:Body>
<RunVacationSickPayoutWS xmlns=""http://www.xxx.org/"" />
</soap:Body>
</soap:Envelope>";
var _url = "http://localhost/HR/VacationSickPayoutLogger.asmx";
var _action = "\"http://www.xxx.org/RunVacationSickPayoutWS\"";
System.Xml.XmlDocument soapEnvelopeXml = CreateSoapEnvelope(soap);
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();
}
Response.Write(soapResult);
}
}
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 System.Xml.XmlDocument CreateSoapEnvelope(string soap)
{
System.Xml.XmlDocument soapEnvelop = new System.Xml.XmlDocument();
soapEnvelop.LoadXml(soap);
return soapEnvelop;
}
private static void InsertSoapEnvelopeIntoWebRequest(System.Xml.XmlDocument soapEnvelopeXml, HttpWebRequest webRequest)
{
using (Stream stream = webRequest.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
}

Related

C# Login to a non-interactive website and pass XML via URL

Okay, so here is what I have and I am probably doing this completely wrong, but I need some more direction than what I am finding online.
I am trying to pass a URL containing login information and then pass another url in the same connection containing my XML. That's all, and I can't seem to get this to work. Please help!!
Here's my code.
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Xml;
using System.Net;
using System.IO;
using System.Configuration;
using System.Data.SqlClient;
using System.Data.Sql;
using System.Data;
using System.ComponentModel;
using System.Collections.Specialized;
namespace DataIntegration.DataSender
{
class RaveDataSender
{
static void Main(string[] args)
{
System.Uri myUri = new System.Uri(#"https://api.myloginpage.com/edc_studyservices.jsp?action=importfile&filecontents=<?xml version='1.0'?><dataprocessitems><item>someitem</item></dataprocessitems>&filename=1.xml");
System.Uri loginUri = new System.Uri(#"https://api.myloginpage.com/login.jsp?studyid=something&action=login&login=myLoginName&password=myPassword");
byte[] mybytes = Encoding.ASCII.GetBytes("https://api.myloginpage.com/edc_studyservices.jsp?action=importfile&filecontents=<?xml version='1.0'?><dataprocessitems><item>someitem</item></dataprocessitems>&filename=1.xml");
byte[] loginbytes = Encoding.ASCII.GetBytes(#"https://api.myloginpage.com/login.jsp?studyid=something&action=login&login=myLoginName&password=myPassword");
CookieAwareWebClient client = new CookieAwareWebClient();
client.UploadDataAsync(loginUri, loginbytes);
client.UploadDataAsync(myUri, mybytes);
client.Dispose();
}
public class CookieAwareWebClient : WebClient
{
private CookieContainer cookie = new CookieContainer();
protected override WebRequest GetWebRequest(Uri address)
{
WebRequest request = base.GetWebRequest(address);
if (request is HttpWebRequest)
{
(request as HttpWebRequest).CookieContainer = cookie;
}
return request;
}
}
}
}
EDIT this is what I ended up doing.
using (var client = new CookieAwareWebClient())
{
byte[] authresp = client.UploadData(loginUri, loginbytes);
byte[] dataRespose = client.UploadData(xmlUri, reqbytes);
string authResult = System.Text.Encoding.UTF8.GetString(authresp);
string result = System.Text.Encoding.UTF8.GetString(dataRespose);
client.Dispose();
}
I think the problem might be that you dispose the object while the asynchronous methods still running.

c# sending data to php url

okay so I have a c# console source code I have created but it does not work how I want it to.
I need to post data to a URL the same as if I was going to input it an a browser.
url with data = localhost/test.php?DGURL=DGURL&DGUSER=DGUSER&DGPASS=DGPASS
Here is my c# script that does not do it the way I want to I want it to post the data as if I had typed it like above.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using System.Net;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string URL = "http://localhost/test.php";
WebClient webClient = new WebClient();
NameValueCollection formData = new NameValueCollection();
formData["DGURL"] = "DGURL";
formData["DGUSER"] = "DGUSER";
formData["DGPASS"] = "DGPASS";
byte[] responseBytes = webClient.UploadValues(URL, "POST", formData);
string responsefromserver = Encoding.UTF8.GetString(responseBytes);
Console.WriteLine(responsefromserver);
webClient.Dispose();
}
}
}
I have also triead another method in c# this does now work either
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using System.Net;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string URI = "http://localhost/test.php";
string myParameters = "DGURL=value1&DGUSER=value2&DGPASS=value3";
using (WebClient wc = new WebClient())
{
wc.Headers[HttpRequestHeader.ContentType] = "text/html";
string HtmlResult = wc.UploadString(URI, myParameters);
System.Threading.Thread.Sleep(500000000);
}
}
}
}
I have been trying to figure a way to do this in my c# console for days now
Since what you seem to want is a GET-request with querystrings and not a POST you should do it like this instead.
static void Main(string[] args)
{
var dgurl = "DGURL", user="DGUSER", pass="DGPASS";
var url = string.Format("http://localhost/test.php?DGURL={0}&DGUSER={1}&DGPASS=DGPASS", dgurl, user, pass);
using(var webClient = new WebClient())
{
var response = webClient.DownloadString(url);
Console.WriteLine(response);
}
}
I also wrapped your WebClient in a using-statement so you don't have to worry about disposing it yourself even if it would throw an exception when downloading the string.
Another thing to think about is that you might want to url-encode the parameters in the querystring using WebUtility.UrlEncode to be sure that it doesn't contain invalid chars.
How to post data to a URL using WebClient in C#: https://stackoverflow.com/a/5401597/2832321
Also note that your parameters will not appear in the URL if you post them. See: https://stackoverflow.com/a/3477374/2832321

Sending SOAP message with C# Help Needed

I would like to send a SOAP Message to a Web Service and read the response. My code is as follows: I will appreciate your help.
I hope my question is not repeated, I have looked around for a solution however I have not been successful.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Services;
using System.Xml;
using System.Net;
using System.IO;
namespace TolunaPush
{
public partial class _Default : System.Web.UI.Page
{
private string sourceID = "50001255";
private string email = "adsvine#gmail.com";
private string firstName = "Muz";
private string lastName = "Khan";
private string countryID = "2000077";
private string countryLanguage = "2000240";
private string postalCode = "N19 3NU";
private string dob = "1977-03-08";
private string gender = "2000247";
protected void Page_Load(object sender, EventArgs e)
{
sendSoapMessage();
}
protected void sendSoapMessage()
{
XmlDocument doc = new XmlDocument();
doc.InnerXml = #"<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
<soap:Body>
<SubmitPanelist xmlns=""http://www.greenfield.com/RegistrationGateway/Messages"">
<Registration xmlns=""http://www.greenfield.com/RegistrationGateway/Types"">
<Source>
<SourceID>" + sourceID + #"</SourceID>
</Source>
<Email>" + email + #"</Email>
<FirstName>" + firstName + #"</FirstName>
<LastName>" + lastName + #"</LastName>
<CountryUK>
<CountryID>" + countryID + #"</CountryID>
<Language>" + countryLanguage + #"</Language>
<Address>
<Postalcode>" + postalCode + #"</Postalcode>
</Address>
</CountryUK>
<DOB>" + dob + #"</DOB>
<Gender>" + gender + #"</Gender>
</Registration>
</SubmitPanelist>
</soap:Body>
</soap:Envelope>";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://coreg.surveycenter.com/RegistrationGateway/PanelistService.asmx");
//if (proxy != null) req.Proxy = new WebProxy(proxy, true);
// req.Headers.Add("GetClientInfo", "http://tempuri.org/GetClientInfo");
req.ContentType = "text/xml;charset=\"utf-8\"";
req.Accept = "text/xml";
req.Method = "POST";
Stream stm = req.GetRequestStream();
doc.Save(stm);
stm.Close();
WebResponse resp = req.GetResponse();
stm = resp.GetResponseStream();
StreamReader r = new StreamReader(stm);
Response.Write(r.ReadToEnd());
//Response.Write(stm.ToString());
//Response.Write(r.ToString());
Response.End();
}
}
}
Update
As suggested by Darin. I did as instructed however the following line of code
using (var client = new RegistrationBindingsClient("RegistrationBindings"))
gives the error
The type or namespace name 'RegistrationBindingsClient' could not be found (are you missing a using directive or an assembly reference?)
Any help will be greatly appreciated
The web service you are trying to consume offers a WSDL at the following address. So simply right click on the References in the solution explorer and use the Add Service Reference dialog in Visual Studio and point to the WSDL and it will generate strongly typed classes for you to easily consume the service, just like this:
protected void sendSoapMessage()
{
using (var client = new RegistrationBindingsClient("RegistrationBindings"))
{
var registration = new RegistrationType();
registration.Source = new SourceType();
registration.Source.SourceID = "50001255";
registration.Email = "adsvine#gmail.com";
registration.FirstName = "Muz";
registration.LastName = "Khan";
var countryUK = new CountryTypeUK();
countryUK.CountryID = 2000077;
countryUK.Language = 2000240;
countryUK.Address = new AddressTypeUK();
countryUK.Address.Postalcode = "N19 3NU";
registration.Item = countryUK;
registration.DOB = new DateTime(1977, 3, 8);
registration.Gender = 2000247;
client.SubmitPanelist(registration);
}
}
See how easy it is. You should not worry about any SOAP and XML plumbing.
And if you are interested in the actual underlying SOAP envelope that is being sent on the wire using this request:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SubmitPanelist xmlns="http://www.greenfield.com/RegistrationGateway/Messages">
<Registration xmlns="http://www.greenfield.com/RegistrationGateway/Types">
<Source>
<SourceID>50001255</SourceID>
</Source>
<Email>adsvine#gmail.com</Email>
<FirstName>Muz</FirstName>
<LastName>Khan</LastName>
<CountryUK>
<CountryID>2000077</CountryID>
<Language>2000240</Language>
<Income>0</Income>
<Education>0</Education>
<Address>
<Postalcode>N19 3NU</Postalcode>
</Address>
</CountryUK>
<DOB>1977-03-08</DOB>
<Gender>2000247</Gender>
</Registration>
</SubmitPanelist>
</s:Body>
</s:Envelope>
Is there any error message or did you use an HTTP monitor?
Some maybe useful Links:
XmlDocument Save Method
How to: Send Data Using the WebRequest Class
Similar Question in stackoverflow maybe helpful
You can access the service in 2 methods:
By adding a web reference of the service. In visual studio you can right click on your project and select the option Add Web reference and then paste the URL of the service.
Generate client proxy from the wsdl using wsdl tool from Visual studio command prompt.The command would be as follows:
c:>wsdl "http://coreg.surveycenter.com/RegistrationGateway/PanelistService.asmx?wsdl
It would generate a .cs file and an output.config. Include the .cs file in your project and you can directly use it to access the service. Make sure that the config file entries are added to your projects config.
If you want to use HttpWebRequest then find the code below :
string soap =
#"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
xmlns:xsd=""http://www.w3.org/2001/XMLSchema""
xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
<soap:Body>
<Register xmlns=""http://tempuri.org/"">
<id>123</id>
<data1>string</data1>
</Register>
</soap:Body>
</soap:Envelope>";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://localhost/WebServices/CustomerWebService.asmx");
req.Headers.Add("SOAPAction", "\"http://tempuri.org/Register\"");
req.ContentType = "text/xml;charset=\"utf-8\"";
req.Accept = "text/xml";
req.Method = "POST";
using (Stream stm = req.GetRequestStream())
{
using (StreamWriter stmw = new StreamWriter(stm))
{
stmw.Write(soap);
}
}
WebResponse response = req.GetResponse();
Stream responseStream = response.GetResponseStream();
// TODO: Do whatever you need with the response
My Service looks like :
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class CustomerWebService : System.Web.Services.WebService
{
[WebMethod]
public string Register(long id, string data1)
{
return "ID.CUSTOMER";
}
}
Here's a general purpose class you can use to achieve what you need.
IMPORTANT DISCLAIMER: You should only use this when you want (or need) to manually issue a SOAP-based web service: in most common scenarios you should definitely use the Web Service WSDL together with the Add Service Reference Visual Studio feature, which is the proper way to do that.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Xml;
namespace Ryadel.Web.SOAP
{
/// <summary>
/// Helper class to send custom SOAP requests.
/// </summary>
public static class SOAPHelper
{
/// <summary>
/// Sends a custom sync SOAP request to given URL and receive a request
/// </summary>
/// <param name="url">The WebService endpoint URL</param>
/// <param name="action">The WebService action name</param>
/// <param name="parameters">A dictionary containing the parameters in a key-value fashion</param>
/// <param name="soapAction">The SOAPAction value, as specified in the Web Service's WSDL (or NULL to use the url parameter)</param>
/// <param name="useSOAP12">Set this to TRUE to use the SOAP v1.2 protocol, FALSE to use the SOAP v1.1 (default)</param>
/// <returns>A string containing the raw Web Service response</returns>
public static string SendSOAPRequest(string url, string action, Dictionary<string, string> parameters, string soapAction = null, bool useSOAP12 = false)
{
// Create the SOAP envelope
XmlDocument soapEnvelopeXml = new XmlDocument();
var xmlStr = (useSOAP12)
? #"<?xml version=""1.0"" encoding=""utf-8""?>
<soap12:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
xmlns:xsd=""http://www.w3.org/2001/XMLSchema""
xmlns:soap12=""http://www.w3.org/2003/05/soap-envelope"">
<soap12:Body>
<{0} xmlns=""{1}"">{2}</{0}>
</soap12:Body>
</soap12:Envelope>"
: #"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/""
xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
<soap:Body>
<{0} xmlns=""{1}"">{2}</{0}>
</soap:Body>
</soap:Envelope>";
string parms = string.Join(string.Empty, parameters.Select(kv => String.Format("<{0}>{1}</{0}>", kv.Key, kv.Value)).ToArray());
var s = String.Format(xmlStr, action, new Uri(url).GetLeftPart(UriPartial.Authority) + "/", parms);
soapEnvelopeXml.LoadXml(s);
// Create the web request
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Headers.Add("SOAPAction", soapAction ?? url);
webRequest.ContentType = (useSOAP12) ? "application/soap+xml;charset=\"utf-8\"" : "text/xml;charset=\"utf-8\"";
webRequest.Accept = (useSOAP12) ? "application/soap+xml" : "text/xml";
webRequest.Method = "POST";
// Insert SOAP envelope
using (Stream stream = webRequest.GetRequestStream())
{
soapEnvelopeXml.Save(stream);
}
// Send request and retrieve result
string result;
using (WebResponse response = webRequest.GetResponse())
{
using (StreamReader rd = new StreamReader(response.GetResponseStream()))
{
result = rd.ReadToEnd();
}
}
return result;
}
}
}
For additional info & details regarding this class you can also read this post on my blog.

C# WebClient OpenRead url

So I have this program that fetches a page using a short link (I used Google url shortener).
To build my example I used code from Using WebClient in C# is there a way to get the URL of a site after being redirected?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MyWebClient client = new MyWebClient();
client.OpenRead("http://tinyurl.com/345yj7x");
Uri uri = client.ResponseUri;
Console.WriteLine(uri.AbsoluteUri);
Console.Read();
}
}
class MyWebClient : WebClient
{
Uri _responseUri;
public Uri ResponseUri
{
get { return _responseUri; }
}
protected override WebResponse GetWebResponse(WebRequest request)
{
WebResponse response = base.GetWebResponse(request);
_responseUri = response.ResponseUri;
return response;
}
}
}
I do not understant a thing: when I do client.OpenRead("http://tinyurl.com/345yj7x"); this downloads the page that the url points to? If this method downloads the page, I need something to get me only the url, so if there's a method to get only some headers, or only the url, please let me know.
You can get the headers only using a HEAD request, like this:
var request = WebRequest.Create(sourceUri);
request.Method = "HEAD";
var response = request.GetResponse();
if (response != null) {
// You can now use response.Headers to get header info
}
Create a HttpWebRequest with the AllowAutoRedirect property set to false, then look at the Location header on the response.
var request = (HttpWebRequest) WebRequest.Create("http://tinyurl.com/345yj7x");
request.AllowAutoRedirect = false;
var response = request.GetResponse();
var location = response.Headers[HttpResponseHeader.Location];

Problem Executing Async Web Request

Can anyone tell me what I've done wrong with this simple code?
When I run it it hangs on
using (Stream postStream = request.EndGetRequestStream(asynchronousResult))
If I comment out the requestState.Wait.WaitOne(); line the code executes correctly but obviously doesn't wait for the response. I'm guessing the the call to EndGetRequestStream is somehow returning me to the context of the main thread?? I'm pretty sure my code is essentially the same as the sample though (MSDN Documentation)
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;
using System.Text;
namespace SBRemoteClient
{
public class JSONClient
{
public string ExecuteJSONQuery(string url, string query)
{
System.Uri uri = new Uri(url);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.Method = "POST";
request.Accept = "application/json";
byte[] requestBytes = Encoding.UTF8.GetBytes(query);
RequestState requestState = new RequestState(request, requestBytes);
IAsyncResult resultRequest = request.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), requestState);
requestState.Wait.WaitOne();
IAsyncResult resultResponse = (IAsyncResult)request.BeginGetResponse(new AsyncCallback(GetResponseStreamCallback), requestState);
requestState.Wait.WaitOne();
return requestState.Response;
}
private static void GetRequestStreamCallback(IAsyncResult asynchronousResult)
{
try
{
RequestState requestState = (RequestState)asynchronousResult.AsyncState;
HttpWebRequest request = requestState.Request;
using (Stream postStream = request.EndGetRequestStream(asynchronousResult))
{
postStream.Write(requestState.RequestBytes, 0, requestState.RequestBytes.Length);
}
requestState.Wait.Set();
}
catch (Exception e) {
Console.Out.WriteLine(e);
}
}
private static void GetResponseStreamCallback(IAsyncResult asynchronousResult)
{
RequestState requestState = (RequestState)asynchronousResult.AsyncState;
HttpWebRequest request = requestState.Request;
using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult))
{
using (Stream responseStream = response.GetResponseStream())
{
using (StreamReader streamRead = new StreamReader(responseStream))
{
requestState.Response = streamRead.ReadToEnd();
requestState.Wait.Set();
}
}
}
}
}
}
couple of things:
I don't think you can re-use the same request object. i.e. you can call BeginGetRequestStream once per instance of HttpWebRequest.
if you want to perform two requests (calls to the server) you need two instances of HttpWebRequest one per request.
if you want synchronous behavior you have two options: Use the GetRespose method
or use begin/end in a synchronous way. to do so you don't need to pass a callback to the BeginGetRequestStream method (you can pass a null instead).
take the returned value from BeginGetRequestStream (IAsyncResult) and pass it to the EndGetRequestStream method:
AsyncResult resultRequest = request.BeginGetRequestStream(null, null);
Stream postStream = request.EndGetRequestStream(asynchronousResult)
EndGetRequestStream will block until the request is completed (this is bad if you are doing it from the UI, but it will still work).

Categories

Resources