How do I access an ASMX web service using a WebClient? - asp.net

I am trying to create a method in a class that accesses a WebMethod on a Web Service using WebClient, and am running into problems. Using VS2010 on Windows.
First of all, yes I know I could create a Web Reference to the web service in the class library, of course this is design time binding. However, I need to be able to get to the web service using information only available at run time. There's a business reason for this that I won't go into here, just go with it, please.
This appears to be possible using the WebClient class from the System.Net namespace. And in fact I am able to get to the service in question, but the data I am sending to it doesn't appear to be in a correct format, although for all I can tell it is a properly formatted SOAP message.
The WebException contains the following message: "The remote server returned an error: (415) Unsupported Media Type."
Here's the code:
public string DoingBusiness()
{
WebClient client = new WebClient();
string destUri = "http://localhost/Service/Service.asmx?op=CommunicationsCheck";
StreamReader reader = new StreamReader(#"CommCheck.xml");
string data = String.Format(reader.ReadToEnd(), "The End is Near!");
reader.Close();
string response = client.UploadString(destUri, data);
return response;
}
Leaving off the actual xmlns, which is sensitive, the data read by the StreamReader above looks like:
<?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>
<CommunicationsCheck xmlns="http://.../">
<communication>{0}</communication>
</CommunicationsCheck>
</soap:Body>
</soap:Envelope>
This looks like a perfectly fine SOAP message. Of course the "{0}" gets filled in with the payload string. If the WebMethod "CommunicationsCheck(string communication) ran successfully it would return:
<?xml version="1.0" encoding="utf-8" ?>
<string xmlns="http://[service url]/">You sent 'The End is Near!'</string>
Which it does if I access the service through a browser, or through a design-time web reference.
So, the question is, what am I doing wrong here that I get the "(415) Unsupported Media Type"
Are there properties on the WebClient that need to be set? Do I perhaps need to provide a Header containing a UserAgent? Or something else?

Darn. I guess I should let someone else answer the question, but answering one's own question is acceptable, if one finds it oneself.
Anyway, some further research on the problem seemed to suggest that one surmise on my part, namely that there might be some Header property I needed to set, was a possible solution. And the research suggested that the property would be "content-type" needed to be set as "text/xml". So I added this line:
client.Headers.Add("content-type", "text/xml");
just before the UploadString method call.
BINGO!
The expected response occurred.
Has anyone ever noticed that answers to perplexing questions sometimes become self-evident once the question is posed, but not before? Interesting phenomenon.

Related

How do I completely control ASP.NET WCF return output?

I have an ASP.NET WCF .svc interface which is accepting a POSTed form. I cannot control the POSTing client at all (which happens to be the IBM Lotus Forms Viewer application), but its behavior is that it POSTs itself to a URL of my choosing and the response is popped up in Internet Explorer as a locally served temporary file with an extension controlled by the mime-type.
I am new to WCF REST services, but I am having a hard time controlling the response, which keeps getting wrapped in XML tags. Is there a way to turn off all output wrapping and control exactly what is returned from the WCF operation?
I can point the form to something other than a WCF service (like an .aspx file), but I thought it would be useful at least to learn how the formatting is controlled before I made that decision.
[EDIT] For clarification, my current service interface prototype looks like this:
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/AF1067/SubmitForm",
BodyStyle = WebMessageBodyStyle.Bare)]
public string AF1067_SubmitForm(System.IO.Stream fileContents) { ... }
[EDIT] User #Kon found this link which had the answer -- if I return a System.IO.Stream, the response will stop being wrapped.
Continuing from our comments, I still think this may have something to do with the requestor's settings. Perhaps the bare POST which doesn't specify a content type setting defaults to the wrong one? Try to explicitly set it to "application/json" or "application/json; charset=utf-8" Just throwing ideas out there.
The other thing to make sure of is that your service method's ResponseFormat is set to JSON as well.
Btw, nice method name. ;)

Possible SOAP version mismatch

I have a problem with web service connection. It says,
Possible SOAP version mismatch:
Envelope namespace
http://schemas.xmlsoap.org/wsdl/ was
unexpected. Expecting
http://schemas.xmlsoap.org/soap/envelope/.
when i call webservice's method. Do you have any idea about my problem?
It looks like you're providing the wrong namespace when creating the SOAP envelope - it should look similar to this:
<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/">
It's the third one that is probably wrong in your case.
I ran into the same issue dealing with a legacy web service hosted on a mainframe(obviously not .net). The url for the service was specified in the config of the client, but the wsdl file had not been included in the deployment. I suspect that on the initial call, the .Net client attempted to retrieve a fresh wsdl. The service wasn't expecting that and we received the "Possible SOAP version mismatch" error.
We encountered this error, because we set the c#-WebServiceProxy-URL to a wrong value.
we did
WebService ws = new WebService();
ws.Url = "http://URL_TO_WEBSERVICE?WSDL";
var response = ws.CallFunction()
Here the ?WSDL at the end of the URL caused the error.

receive xml file as a parameter to a .net web service

My company is currently looking into bringing a new piece of third party software in for online ordering. The software does not handle pricing so they are requesting the pricing information from a web service. Their software is passing an XML file as a parameter, and expecting an XML file as a response. I would think that returning an XML file would be pretty straight forward, but I cannot think of a way to receive an XML file as a parameter. Has anyone done this, or am I missing something really obvious?
Possibly obvious - an XML "file" can be represented by a String.
Edit to Answer Comment
The string is the XML file, so all you need to do is deserialize it into the classes created from the XSD:
Dim xmlString As String = GetStringFromVendor()
Dim xmlClass As New CoolXMLClass
Dim serializer As New Xml.Serialization.XmlSerializer(GetType(CoolXMLClass))
xmlClass = serializer.Deserialize(New StringReader(xmlString))

Problems with an ASMX Web Method that uses File I/O

Right now I am working on a stub of a project. In the course of the project I need to be able to from a web front end set a message on a server to and then from an iPhone Query the Server to read the message.
While all the individual peices are working and my request is going through fine I am having trouble using this webmethod
[WebMethod()]
public void setMessage(string message)
{
FileStream file = new FileStream("mymessage.txt", FileMode.OpenOrCreate, FileAccess.Write);
StreamWriter sw = new StreamWriter(file);
sw.Write(message);
sw.Close();
file.Close();
}
When I invoke this via HTTP Post using SOAP from an iPhone app.
I get the following xml in my console when I make the request.
<?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>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>Server was unable to process request. ---> Access to the path 'c:\windows\system32\inetsrv\myMessage.txt' is denied.</faultstring>
<detail />
</soap:Fault>
</soap:Body>
</soap:Envelope>
The Server is one configured by my boss, that is currently being used in other capacities as an in house test server for several different projects.
The server is an IIS server I do not know what version, with ASP.NET configured and installed.
The script is located in a different place than the program is trying to write. I assume that the script is being run from that directory and that is why it is trying to write there. Is that the case or am I missing something fundamental?
If there are any alternative suggestions as to how I could go about this I would love to hear them as well, as I am working of a pretty small knowledge base.
Thanks!
Change "filename.txt" to
Server.MapPath("filename.txt")
or specify the full physical path of the file and grant NTFS permissions to the ASP.NET user to be able to access the folder.
Server.MapPath converts virtual paths (e.g. ~/helloworld.aspx) to physical paths (e.g. D:\WebSite\helloworld.aspx).
In addition to storing the file in a folder you have access to (were you unable to read the message?), you need to properly implement "using" blocks:
using (FileStream file = new FileStream("mymessage.txt",
FileMode.OpenOrCreate, FileAccess.Write)) {
using (StreamWriter sw = new StreamWriter(file)) {
sw.Write(message);
}
}
The reason it's writing to c:\windows\system32\inetsrv\ is that this is its default directory. If you want to write to a different directory, then you have tp specify it. Server.MapPath will do that, as has already been pointed out to you.

Soap Post Failure

So, I'm trying to use soap to communicate with a webservice and getting errors. What is frustrating about this particular issue is that it works perfectly fine with my local copy of the webservice (yes, I tried turning off my firewall) and used to work fine with a previous version of the webservice and client. I suspect I could (though I'll have to look up how to do this) add an action parameter to what the client is sending. However, I am very curious why it was able to work previously without one.
Edit Clarification: I think the relevant code was the same between when it stopped working and when it worked (since I checked against an old version of the program and had the same problems and the relevant code was the same...unless I missed something subtle). I know the actual server program is the same on both the local copy and the remote copy, even though it only works locally. I thus suspect there is some sort of weird configuration setting I can change to make it work.
Error message: "soap:ClientUnable to handle request without a valid action parameter. Please supply a valid soap action."
VB Client Code
'WEB_SERVICE_URL_CONST = http://site.com/foo.asmx
'domDoc.xml = <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><TestConnection xmlns="http://site.com"/></soap:Body></soap:Envelope>
Dim oXml As New XMLHTTPRequest
oXml.Open "POST", WEB_SERVICE_URL_CONST, False, "\"
oXml.setRequestHeader "Content-Type", "text/xml"
oXml.send domDoc.xml
C# Server Code
[WebMethod]
public int TestConnection()
{
return 1;
}
Are you sure the first two lines are not commented-out in the real version? The sample code seems to have no value for WEB_SERVICE_URL_CONST and domDoc.xml, and an empty Soap request would indeed not specify any action?
EDIT: I find the "used to work fine with a previous version of the webservice and client" a bit confusing. If you actually changed both the client and the server, then what part did not change?
The problem was with the xmlns="http://site.com" code. When I tested locally, I was using xmlns="http://localhost" by mistake. In fact, this should not be changed on the client or the server (in the server, this would be WebService(Namespace =...)), regardless of where I am testing...but if it does change, the client and server need to match.

Resources