I need to invoke action on a web service, but i have no idea what the request envelope will look like (the services are attached at runtime by users).
Generally I'd like to generate soap envelope programmatically based on wsdl link. With given link get list of operation and such result for specific one:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:webservice.contentinn.com">
<soapenv:Header>
<urn:AuthHeaderElement>
<token></company>
</urn:AuthHeaderElement>
</soapenv:Header>
<soapenv:Body>
<urn:TestMethod>
<id></id>
</urn:TestMethod>
</soapenv:Body>
</soapenv:Envelope>
Anyone have idea how to do that?
Answers to this question suggests a couple of approaches:
SoapUI: This is not really a programmatic approach.
Castle Dynamic Proxy: This is closer to what you sound like you need, but still not quite there.
The example here is probably what you're after:
The DynamicProxy allows you to create the dynamic WCF client at runtime by specifying the WSDL URI of the service. The DynamicProxy does not depend on the precompiled proxy or configuration. The DynamicProxy uses the MetadataResolver to download the metadata from the service and WsdlImporter to create the contract and binding at runtime. The compiled dynamic proxy can be used to invoke the operations on the service using reflection.
The example shows how you can the dynamic proxy to invoke operations that use simple types and complex types. The flow of usage is as following.
Create the ProxyFactory specifying the WSDL URI of the service.
DynamicProxyFactory factory = new DynamicProxyFactory("http://localhost:8080/WcfSamples/DynamicProxy?wsdl");
Browse the endpoints, metadata, contracts etc.
factory.Endpoints factory.Metadata factory.Contracts factory.Bindings
Create DynamicProxy to an endpoint by specifying either the endpoint or contract name.
DynamicProxy proxy = factory.CreateProxy("ISimpleCalculator");
OR
DynamicProxy proxy = factory.CreateProxy(endpoint);
Invoke operations on the DynamicProxy
double result = (dobule)proxy.CallMethod("Add", 1d ,2d);
Close the DynamicProxy
proxy.Close();
To run the example: Compile the solution, run the CalculatorService.exe and then run the CalculatorDynamicClient.exe
There is a Java example here, too.
You'll need to generate a proxy class; that'll generate everything needed for invoking the service's actions.
There are several ways to generate the proxy class
You could add a Service Reference to your project
Run SVCUTIL: svcutil http://someurl?wsdl
Once the proxy class is generated, it'll expose the service's actions as methods. Just invoke the desired method and the SOAP envelope will be generated for you.
Related
I have several SOAP web services that have the same interface but have different URLs' and namespaces'.
URL 1 http://badservice.com/one has a namespace "one-ns"
URL 2 http://badservice.com/two has a namespace "two-ns"
When I generate a web service client via svcutil from http://badservice.com/one?wsdl, I can only use it for http://badservice.com/one. Once I try to send a request to http://badservice.com/two SOAP service says
namespace mismatch require http://nanopetdbs.driver.maestro.ibtech.com found http://ozkaraslanpetroldbs.driver.maestro.ibtech.com
I can generate clients for each web service URLs at the worst scenario.
I need an idea to prevent code duplication in this case. I have tried altering namespace while sending requests, could not make it.
I need to change the highlighted place of the envelope at the runtime.
No, we can’t specify these values at the runtime. During SOAP communication, this field will be used for addressing the method to be called.
Here is a communication telegram captured by Fiddle.
The SOAPAction field will specify the method to be called.
If these values can be changed at the runtime, the addressing method becomes confusing. This is the meaning of a service contract with its namespace and name properties.
[ServiceContract(Namespace ="http://mycommany.com")]
public interface IService
{
[OperationContract(Name ="Mymethod")]
Int32 Add(Int32 Num1, Int32 Num2);
}
Besides the BasicHttpbinding, some other bindings, such as wshttpbinding using ws-addressing. They use these properties(namespace, name) in Action SOAP header to specify the addressing method.
In summary, It is these attributes that determine the addressing mode at the runtime, so we cannot modify these attributes(namespace, name) at the runtime.
Feel free to let me know if there is anything I can help with.
I am in the process of creating a Send Port in Biztalk, that uses the Wcf-Custom adapter for sending SOAP requests.
So far I have been testing the SOAP requests in Visual Studio, using C# code from the System-ServiceModel namespace. See code below:
/ CODEGEN: Generating message contract since the operation transferPayments is neither RPC nor document wrapped.
[System.ServiceModel.OperationContractAttribute(Action="urn:CorporateService:transferPayment", ReplyAction="*")]
[System.ServiceModel.XmlSerializerFormatAttribute()]
transferPaymentsResponse transferPayments(transferPayment1 request);
[System.ServiceModel.OperationContractAttribute(Action="urn:CorporateService:transferPayment", ReplyAction="*")]
System.Threading.Tasks.Task<transferPaymentsResponse> transferPaymentsAsync(transferPayment1 request);
I need to add this "transferPayment" action to the SOAP Action Header field in the adapter.
Using the provided example, I've come up with this
<BtsActionMapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Operation Name="TransferPayment" Action="http://bankconnect.dk/schema/2014/CorporateService/TransferPayment" />
</BtsActionMapping>
Where "http://bankconnect.dk/schema/2014" is the namespace, "CorporateService" is the service, and "TransferPayment" is the action. I'm unsure if this is the correct way to go about implementing this.
My question how I should format the SOAP Action Headers, so that they correspond to the c# code used.
I'd suggest you use the BizTalk WCF Service Consume Wizard to generate the schema's inside BizTalk. This would make all the possible Actions for you.
I have a WCF service based on BizTalk, I'm not sure how it was deployed or generated but as far as I know it was made using the BizTalk wizard for publishing WCF services. The problem is the BizTalk server installation was removed and now the service still here but it doesn't work, when i invoke the URL the service responses an exception: The BizTalk receive location may be disabled. I need to generate a WCF service in order to replace that service. I have one example request and response and the folder with the service, with a lot of stuff, XML, definitions, etc but there are no DLLs. The SVC markup has a reference to a BizTalk logic.
<%# ServiceHost Language="c#" Factory="Microsoft.BizTalk.Adapter.Wcf.Runtime.WSHttpWebServiceHostFactory, Microsoft.BizTalk.Adapter.Wcf.Runtime, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
So here goes my question, does anybody know how to generate a service based on request or response to supplant the service.
If you only have the request and response xml then it's a bit tricky. Even if you manage to recreate the service there is no guarantee that existing service consumers will be able to continue to call the service without any change. However, if you want to have a go, this rough guide will help:
Extract the operation signature from the soap request and response
This should be simple. Just look at the part of the request xml which defines the SOAP body. As an example:
<soap:Body xmlns:m="http://www.bookshop.com/prices">
<m:GetBookPrice>
<param1 xsi:type="xs:string">Metro 2033</param1>
</m:GetBookPrice>
</soap:Body>
This shows that the operation name was called GetBookPrice, and that it takes a string as an argument. Now look at the soap body for the response, for example:
<soap:Body xmlns:m="http://www.bookshop.com/prices">
<m:GetBookPriceResponse>
<return xsi:type="xs:decimal">5.99</return>
</m:GetBookPriceResponse>
</soap:Body>
This tells us that the return type of the operation was decimal:
public decimal GetBookPrice(string bookName);
So now you can recreate the service operation in a vanilla WCF service.
It's possible that the service definition included complex types rather than primitives, in which case you need to infer the types from the request/response xml. If the types are too large, you can try to automatically infer them by:
Infer XSD from XML - you'll need to extract just the request and response types from the request/response files, then run them through xsd.exe, which will try to generate the XSD schemas for your request/response types.
Infer CS from XSD - once you have the XSD files, again use xsd.exe to infer the classes for these files. You can then annotate these classes with the DataContract and DataMember attributes and then you can use them in your service definition.
In conclusion, it's not a task I envy you for - even if you manage to faithfully reconstruct the service and type definitions, you may still find that existing clients cannot call the service based on having missed some optional data which was not present in the request/response files you have.
If you create a client for the service in a blank project using Visual Studio (References > "Add Service Reference") you will get the interface that you need to implement (as well as POCOs for all the parameters).
Then create a new WCF project and use that interface and those classes as your contract.
This way you will honour the existing schema without having to manually interpret it.
Look for WcfServiceDescription.xml file in your service folder, its under \App_Data\Temp folder of your service physical folder (you can check IIS virtual directory where its pointing to find the physical path).
Use this file to publish the service again. Based on the definition in it, make sure, you deploy required assemblies to GAC (e.g. schema or orchestration assemblies) before publishing the service again.
Then you can use BtsWcfServicePublishing.exe tool which you can download from http://www.microsoft.com/en-us/download/details.aspx?id=21973 from command prompt. On this exe pass the WcfServiceDescription.xml file along with its full path
In the end, I used an ashx handler for procesing the request (cambined with the other responses were very helpfull) xml-> generate xsd -> parse and read request. The only problem is the .ashx termination.
The ONLY argument I can see for SOAP WCF over REST (json) wcf is the fact that once my service is created I can add a a reference in visual studio and I get a load of strongly typed classes ready for me and a client class that I can call all my webmethod through. It even sets up the web.config as far as I remember.
However when I expose a REST (json) service I still get a WSDL. So Im wondering is there still a way to build my references automatically?
Not using WCF tools. Unlike with SOAP (which has an established protocol for describing services - WSDL), REST doesn't. WADL is one such protocol, but it isn't too widespread and WCF does not support it. You still get a WSDL, because WCF will describe everything it can from the service. However, the WSDL won't have a <wsdl:port> element, which would describe the REST endpoint, which is why you get the WSDL, but cannot generate a reference to it.
The post at http://blogs.msdn.com/b/carlosfigueira/archive/2012/03/26/mixing-add-service-reference-and-wcf-web-http-a-k-a-rest-endpoint-does-not-work.aspx has a lot more info on this issue.
Very old question, newer answer.
today using openapi (swagger) I can achieve this by using swagger inspector doing samples i can document my rest services as well as create a spec yml/json file allowing for validations and acceptance criteria as well as automated clients for java,python,c#,ruby,javascript and others I'm sure
I would like top elaborate:
Although it is true you cannot get a WSDL add service reference with a JSON REST WCF service, what I do is create two met data hooks:
is the operations returning JSON
is a single XML op returning a class wrapper which includes all the service classes I allow, I call it Discover:
i.e.
public class Discover
{
public Manager Manager {get;}
public Employee Emp {get;}
....
}
[OperationContract]
public Discover DiscoverDTOs()
You can, indirectly. While the client generated by Visual Studio won't work, that client implements an interface, also generated, that you can use like this:
WebChannelFactory<IService> factory = new WebChannelFactory<IService>(new Uri(endpointAddress));
IService proxy = factory.CreateChannel();
int result = proxy.Operation(1, 2, 3);
WebChannelFactory has another overload which accepts a WebHttpBinding, you can configure based on the service configuration, or you can make this configuration manually in your app.config file.
Which one of this two ways of using wcf service is better? why?
Generating proxy from Service Reference
using ChannelFactory
ex.
ChannelFactory<IMyContract> factory = new ChannelFactory<IMyContract>();
IMyContract proxy1 = factory.CreateChannel();
proxy1.MyMethod();
It is a bit boring to call wcf service like so
IMyContract proxy1 = null;
try
{
proxy1 = factory.CreateChannel();
proxy1.MyMethod();
((ICommunicationObject)proxy1).Close();
}
catch
{
((ICommunicationObject)proxy1).Abort();
}
Should we repeat this snippet for every proxy call? Or Is there generic way to create a wrapper class for closing and aborting proxies?
Is writing class like this ServiceExecution.Execute(proxy=>proxy.MyMethod()); which creates proxy, and closes or aborts it good way to do that?
Here is an MSDN post, that recomends not to use generated proxies in .Net 3 because it creates ChanelFactory each time, .Net 3.5 ChanelFactory is cached.
But personally I prefer to use ChanelFactory myself, generated code is always a pain even after partials come out
In first case when you use VS to add Service Reference it generates all the code for you including ServiceContrcats and DataContracts.
But when you use ChannelFactory you must have service contracts and etc on client side already.
I suggest using approach 1.
I've found this blog with an example including source code that also explains how to properly handle the connection (closing, aborting, etc.). The blog also contains links for more details at MSDN.
Manually creating the service proxies from a running service might be a good alternative. The tool svcutil is what Visual Studio uses under the hood when adding a service reference. Using this, you can generate the proxy class in a common location, and then link to it in each project you require, and also gain better control over your proxy classes.
For example, to generate a proxy for a service called TestService running locally on port 8000, you would run the following in the Visual Studio command prompt, generating a proxy class TestServiceProxy.cs in the proxies directory.
cd "C:\src\proxies"
svcutil /noLogo /out:TestServiceProxy http://localhost:8000/TestService
There are some other useful parameters for the tool, for example:
Add /n:*,WcfServices.TestService will specify a namespace for the proxy class.
Add /config:TestServiceProxy.config and svcutil will generate a sample configuration file for using TestService including endpoints, bindings etc.
Add /r:"Common.dll" and the proxy class emitted by svcutil will not have definitions for types used by the service, but defined in the assembly Common.dll.
Use svcutil /? for more information.