I am trying to consume the .net webservice from cold fusion. Methods having simple types working fine. But i am having problems with one particular method which accepts byte[] array as input.
Below the sample webmethod declaration
[WebMethod]
public AVStatus ScanStream(byte[] fileObject)
{
// code
}
and the cold fusion code consuming this service is
<cffile action="readBinary" file="#FileName#" variable="filedata">
<cfset b64file = #toBase64(filedata)#>
<cfinvoke webservice = "http://xxx/scanservice.asmx?wsdl"
method = "ScanStream"
returnVariable = "result">
<cfinvokeargument name="fileObject" value="#b64file#" />
</cfinvoke>
This always leads to this error Web service operation ScanStream with parameters cannot be found.
can someone help me out this?
It seems that the binary data has been exposed as bas64 string in the coldfusion while byte[] is exposed by the service as an XML array (of bytes).
Change the ScanStream (if you can) to accept a string, if web service is not yours you could convince owners to provide another method which accepts string and uses Convert.FromBase64String to change to byte array.
Webservices are remote, not public. Public allows access by other CF classes and pages. Change public to remote, and you should be able to "see" your webservice.
Related
My boss asked how long it would take to build a client to access a web service that will send and receive some basic data and embedded documents. Just starting playing with it to see what's involved. I have been doing web and desktop development for about 20 years but have literally never touched a web service so with that I'm at the extreme newb level.
So far I used the wsdl to create the ServiceReference1 and I can see the methods in intellisense but I don't have the first clue where to start with calling the methods, passing parameters and consuming the response. I feel stupid because I'm sure it's pretty simple but just flailing at the code and looking for on point examples has gotten me nowhere. Usually I can find something through google in minutes that is exactly on point but not having luck here. Would appreciate a push in the right direction.
So basic questions. Proper way to make the calls. How and where to land the returned data. How to add parameters.
Here is my first attempt. This gets a simple list and has no parameters. The result in fiddler returns data but there is a runtime type mismatch error which I think is caused by some stray characters leading the response which appear to be caused by chucking, what ever that is. The response starts with 1ffs every time then contains the remainder of the xml. Secondarily I need to get the list into a dataset or some other container but I was hoping to just be able to step into the code and see a result
ServiceReference1.FilingInfoClient webservice = new FilingInfoClient();
ServiceReference1.courtListRequest cr = new ServiceReference1.courtListRequest();
ServiceReference1.courtListResponse lr = new ServiceReference1.courtListResponse();
lr = webservice .getCourtList(cr);
This is essentially the same but takes a date param. When I run this fiddler shows the parameter is not being sent. No other errors but I'm sure only because it exploded immediately.
ServiceReference1.FilingInfoClient webservice = new FilingInfoClient();
ServiceReference1.messageListRequest mr = new ServiceReference1.messageListRequest();
ServiceReference1.MessageListResponse mlr = new ServiceReference1.MessageListResponse();
mr.latestMessagePullTimestamp = DateTime.Now.AddDays(-5);
mr.endTimestamp = DateTime.Now;
mlr.latestMessagePullTimestamp = DateTime.Now;
mlr = webservice.getMessageList(mr);
This is the info provided by the web service host
<x:Envelope xmlns:x="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:urn1="urn:green:partner:ws:schema:FilingInfo">
<x:Header/>
<x:Body>
<urn1:getcourtList>
<urn1:courtListRequest/>
</urn1:getcourtList>
</x:Body>
</x:Envelope>
<x:Envelope xmlns:x="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:urn1="urn:green:partner:ws:schema:FilingInfo">
<x:Header/>
<x:Body>
<urn1:getMessageList>
<urn1:messageListRequest>
<urn1:latestMessagePullTimestamp>?</urn1:latestMessagePullTimestamp>
</urn1:messageListRequest>
</urn1:getMessageList>
</x:Body>
</x:Envelope>
we've got request and response pairs for each operation in the webservice. think like request => input, response => output, operation => method.
the webservice is an API. things that consume APIs are clients. the WSDL describes the API's operations and their requests and responses. tools like visual studio know how to read WSDLs and build C# code to perform those (SOAP) operations under-the-hood. this is the client (here FilingInfoClient). visual studio'll also generate classes representing each request and response.
this allows for a familiar programming experience. you call a method, give it some input, and it returns some output.
using (var client = new FilingInfoClient())
{
var request = new courtListRequest
{
//TODO fill in relevant properties
};
var response = client.getCourtList(request);
}
I'm trying to perform some actions on a remote server using the XML-RPC .NET library and C#. I have no prior experience using this protocol but most examples seemed pretty straight forward. But the server I'm trying to communicate with seems to parse commands slightly different than most examples I've seen.
All calls are made using a 'perform_actions' function and it expects a list of action(s) along side with it as parameter. Fortunately there's a pretty decent documentation with some code samples included but these examples are done in Ruby/Perl with which I have no experience. I've tried translating these to C# with which I believe I'm on the right path but I'm consistently getting the error"Server returned a fault exception: [400] Invalid request: expected list of actions."
My current code
[XmlRpcUrl("https://DOMAIN/admin/rpc")]
public interface iFace : IXmlRpcProxy
{
[XmlRpcMethod("perform_actions")]
XmlRpcStruct[] perform_actions(XmlRpcStruct struc);
}
public void GetData()
{
XmlRpcStruct actions = new XmlRpcStruct();
actions.Add("name", "registrations.accounts.list");
iFace proxy = XmlRpcProxyGen.Create<iFace>();
proxy.Credentials = new NetworkCredential("USERNAME", "PASSWORD");
XmlRpcStruct[] response = proxy.perform_actions(actions);
}
And here is a Ruby example from the API documentation which I was trying to replicate which is functional
require 'xmlrpc/client'
url = 'https://user:passwd#qmanage.example.com/admin/rpc'
c = XMLRPC::Client.new_from_uri(url)
# Call the action to list the access groups.
ags = c.call('perform_actions', [{
'name' => 'network.accessgroups.list',
'args' => {}
}])
The server doesn't really seem to recognize the XmlRpcStruct I'm sending as the error seems to complain about not receiving a list of actions. (I receive the same error if I send no parameter). However if I change the XmlRpcStruct to a regular string array it will complain about expecting a struct instead so the data isn't ignored entirely.
Is anyone able to help me in the right direction with my problem or does anyone know why this error is returned?
Finally managed to figure out my dilemma. Seems I had to pass an array of XmlRpcStruct's rather than just singular XmlRpcStruct, the following solved my problem:
XmlRpcStruct[] actions = new XmlRpcStruct[1];
XmlRpcStruct action = new XmlRpcStruct();
action.Add("name", "registrations.accounts.list");
actions[0] = action;
I just passed actions as parameter to the perform_actions function.
I have wsdl. When I tested my wsdl in SoapUI 5 response was ok. I received proper XML data. When I added service reference in C# and run methods which belongs to web services, the methods didn't return a value. I don't know why. I want to ask how can solve this problem. Can I build a xml parser? How can I connect directly with wsdl document and pass parameters and receive response?
Maybe I should change something in visual studio to my method return a value? because now method return only null value.
In Java the webservices works fine, but in C# don't.
using (CCS.CCSClient ccClient = new CCS.CCSClient())
{
CCS.contactCenterCampaignListResponse infoooo = new CCS.contactCenterCampaignListResponse();
string info = ccClient.contactCenterCampaignGet(token, 66).accountId.ToString();
info variable is null
contactCenterCampaignGet() method return null, but when i use this method in Java contactCenterCampaignGet() return 66
Please, help.
from a Wcf data service client (inherited from System.Data.Services.Client.DataServiceContext) I would like to invoke a service operation defined on a Wcf Data Service that returns void
[WebGet]
public void Operation()
{
// logic
}
The only reasonable method I found is the Execute, but how could I use it with a void operation?
Thank you
You can use just plain HttpWebRequest to do this. I think it will need to be POST service operation (as GET would assume some response, but since you declare it as void it would have no response). In which case Execute can't be used anyway (as it always issues a GET request).
Using plain HttpWebRequest just issue a simple POST to the service operation URL and just check the response status code (should be 204 No Content).
Currently WCF Data Services doesn't have native client support for service operations, so you need to write one for yourself.
I have found a workaround for this problem.
This website solved me quite a few problems before, so I thought it would be nice to share back.
The quick answer to your question is:
string empty = context.Execute<string>(new Uri("Operation", UriKind.Relative)).FirstOrDefault();
The "empty" string should be null or empty upon response. It "works around" the HttpWebRequest method mentioned on the post above.
Further more, it is also possible to get primitive types back using this technique.
Lets say I have this Method:
[WebGet]
public bool Authenticate(string Username, string Password)
{...do stuff here...}
When you try the normal execution it fails (Vitek Karas explains it well in his reponse above):
var query = context.CreateQuery<bool>("Authenticate").AddQueryOption("Username", "'itye'").AddQueryOption("Password","'123456'");
DataServiceCollection<bool> list = new DataServiceCollection<bool>();
list.Load(query);
But the following will do the trick:
var query = context.CreateQuery<bool>("Authenticate").AddQueryOption("Username", "'itye'").AddQueryOption("Password","'123456'");
bool authenticated = context.Execute<bool>(new Uri(query.RequestUri.ToString().Replace("Authenticate()", "Authenticate"))).FirstOrDefault();
Please note the Replace("Authenticate()", "Authenticate"), which omits () from the query string (otherwise it will cause error).
Hope it helps.
- Itye
Thanks Itye
I was looking for similar solution. Did using HttpWebRequest way first. But your two lines of code helped me doing the same task. Very Happy. Thanks Once Again..
var query = context.CreateQuery("Authenticate").AddQueryOption("Username", "'itye'").AddQueryOption("Password","'123456'");
bool authenticated = context.Execute(new Uri(query.RequestUri.ToString().Replace("Authenticate()", "Authenticate"))).FirstOrDefault();
I have to call a webservice from withing a C# programm. The webservice has most probably not a standard format. The interface description (wsdl and xsd) are very complicated, and using a proxy generating mechanismus results in hundreds of classes. The generated classes ar of little help since they are very generic, having mostly simple Object types as members.The best option is to build the SOAP message manually. That is also the way the webservice provider suggested to chose: Take the soap/xml messages that has to be sent and build the message according to the template. Now the question is how to build the message most efficiently. Of course hard coding the message string is an option, however I wonder if better options exists. If I have the complete message in a string, how do I best send the messages. Should I use a simple HttpRequest or can I use mechanisms of the wcf stack?
My current approach to build the message looks like this:
string msg = envelopeBegin;
RouteType rootType = new RouteType();
XmlSerializer serializer = new XmlSerializer(typeof(RouteType));
StringWriter stringWriter = new StringWriter();
serializer.Serialize(stringWriter, rootType , customNamespace);
msg += stringWriter.ToString();
msg += envelopeEnd;
// Send the message over the wire
The Soap/xml message I have to generate looks like this
<env:Envelope>xmlns:env=http://schemas.xmlsoap.org/soap/envelope/ xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns0="http://www.skanska.se/oagis/9/ws/faults">
<env:Body>
<ska:ShowSalesOrder xmlns:ska="http://www.skanska.se/oagis/9" systemEnvironmentCode="UTV" versionID="1.0" releaseID="9.0">
<!--plsql=.74s-->
<ApplicationArea xmlns="http://www.openapplications.org/oagis/9">
<!--user_name=SEBA_RAPPE-->
<ska:Sender>
<LogicalID>OEBS_SE</LogicalID>
<ComponentID>SKAIS017I</ComponentID>
<AuthorizationID>SEBA_RAPPE</AuthorizationID>
<ska:ResponsibilityID>XXOM_INTEGRATION_SVT</ska:ResponsibilityID>
</ska:Sender>
<CreationDateTime>2010-02-26T15:03:27+01:00</CreationDateTime>
<BODID>xxxxxxxxxxxxxxxxx</BODID>
</ApplicationArea>
<ska:DataArea>
<Show xmlns="http://www.openapplications.org/oagis/9">
<ResponseCriteria>
<ResponseExpression actionCode="Never" expressionLanguage="xPath">*</ResponseExpression>
</ResponseCriteria>
</Show>
<ska:SalesOrder>
<SalesOrderHeader xmlns="http://www.openapplications.org/oagis/9">
<DocumentID>
<ID>141779</ID>
</DocumentID>
<RequestedShipDateTime>2009-11-04T07:00:54+01:00</RequestedShipDateTime>
</SalesOrderHeader>
</ska:SalesOrder>
</ska:DataArea>
</ska:ShowSalesOrder>
</env:Body>
</env:Envelope>
You can definitely still use the WCF infrastructure without requiring type definitions for all of the various messages. WCF specifically supports this through the Message class. Using it is not all that difficult. Here's some more information about them but the idea is basically you would use XML readers and writers to read and write messages.
Using the Message Class
One way to do it is to create an XML skeleton template containing placeholders for the values. Read the XML and replace the values with those from your object. Post the resulting XML to the web service using HttpWebRequest.
Even that this approach might work I would strongly recommend you creating a WCF proxy class and using this instead even if the web service contains hundreds of methods and objects that are not used. As long as it is a valid WSDL, WCF will handle it. Also if there are any changes to the web service all you have to do is regenerate the proxy. To avoid the ugliness of this web service create your own infrastructure that exposes only the useful methods and classes and hides the real call.