SOAP - WCF: OperationContract not receiving input parameters - wcf

I am building a new SOAP API in WCF to replace old service in an already established communication with client server.
The catches here are:
I am not allowed to edit the client side
Current API (the one I am replacing) is very old and generates everything in wsdl file, not singleWsdl and wsdl
I managed to establish a connection to the client and my operation is being called, but I am receiving no input parameters. I am sure the parameters are being sent because I have another solution which is working like the current client for my testing purposes. When it's pointing to the old API, it all works fine and inputs are sent, but when I point it to my API it only calls the operation but without inputs as mentioned.
I added Service References to each of the APIs in my test solution to see the differences and I noticed the namespace of the input complex type is different, but here is my current problem:
The name of the operation is the same as the name of the complex type it takes as an input parameter and they both need to be on the same namespace (I presume). I didn't expect this to be a problem, but in my singleWsdl file I can see all my operations listed also as elements in <types> and their input nested as <complexType>s.
I am also wondering whether the problem are imports in my wsdl file or the simple fact I am replacing old wsdl file structure in already establish communication with new wsdl/singleWsdl file structure and it doesn't know where to look for the complex types.
old API Reference.cs (added Service Reference as Web Reference):
[System.Web.Services.Protocols.SoapRpcMethodAttribute("http://www.namespaceURL.com/InternalApi/UpdateScheduler", RequestNamespace="http://www.namespaceURL.com/InternalApi", ResponseNamespace="http://www.namespaceURL.com/InternalApi", Use=System.Web.Services.Description.SoapBindingUse.Literal)]
[return: System.Xml.Serialization.XmlElementAttribute("return")]
public returnUpdateScheduler UpdateScheduler([System.Xml.Serialization.XmlElementAttribute("UpdateScheduler")] UpdateScheduler UpdateScheduler1) {
object[] results = this.Invoke("UpdateScheduler", new object[] {
UpdateScheduler1});
return ((returnUpdateScheduler)(results[0]));
}
new singleWsdl file types:
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.namespaceURL.com/InternalApi">
<xs:import namespace="http://schemas.datacontract.org/2004/07/PairLeague"/>
<xs:element name="UpdateScheduler">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="UpdateScheduler" nillable="true" type="tns:UpdateScheduler"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</wsdl:types>
new wsdl file imports:
<wsdl:types>
<xsd:schema targetNamespace="http://www.namespaceURL.com/Imports">
<xsd:import schemaLocation="http://localhost:18139/IPairLeague.svc?xsd=xsd0" namespace="http://www.namespaceURL.com/InternalApi" />
<xsd:import schemaLocation="http://localhost:18139/IPairLeague.svc?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/" />
<xsd:import schemaLocation="http://localhost:18139/IPairLeague.svc?xsd=xsd2" namespace="http://schemas.datacontract.org/2004/07/PairLeague" />
</xsd:schema>
</wsdl:types>
This is my first time working with SOAP and WCF so my understanding might be incorrect or I might be simply looking at a wrong place. If anybody have any sort of idea, I would be very grateful if you shared it with me please.

The final solution was to set OperationFormatStyle of [ServiceContract] to 'Rpc'
[ServiceContract(Namespace = "http://www.example.com/Service"),
XmlSerializerFormat(Style = OperationFormatStyle.Rpc)]
It seems like when trying to establish a connection with 3rd party service, you need to use the same names and namespaces as well as match the same message structure. Since I am mimicking a SOAP interface of RPC structure, I am not allowed to use MessageContracts, but I need to specify the structure of the messages in which DataContracts are being sent. By setting the style parameter to RPC, DataContracts (ComplexTypes) in wsdl get formatted in message tags correctly. Without the style set to Rpc my operation was not recognising any input type parameter and when I set the DataContract as MessageContract, the input type was recognised, but never populated with passed values when the operation was called. Please note this is just my deduction based on experimenting with the code, the true reason why it now works might be completely different, but most importantly for me now - it's working!
My message element in wsdl was also automatically formated which included incorrect name and namespace parameters.
In my case the name included the namespace of my project, service name and the specific operation name whereas I needed it to be only the operation name.
I also focused on producing only one big wsdl file without any includes as the 3rd party service is expecting this format. At the moment it didn't seem to give me any problems, but it is possible I would encounter a problem there later in the process.
My solution in this matter was implementation of WCFExtrasPlus package through NuGet. In Visual Studio you can open NuGet package Manager through Project panel menu and search for WCFExtrasPlus package and install it.
To set your project to use the package I followed these notes:
http://george2giga.com/development/wcf-merge-wsdl-in-a-single-file/

Related

WCF change attribute nillable to nil

I developed a WS and the WSDL in visual studio, using c#, the WSDL contains nillable="true", but the client does not support, how can I change nillable="true" to xsi:nil="true".
You are confusing the XSD schema nillable attaribute with the XSD schema-instance nil attribute. They are linked, but not equivalent.
Please see http://www.w3.org/TR/xmlschema-0/#Nils for clarity.
The XSD schema nillable attribute is a decorator on the element to allow an explicit null value to be assigned to the element in conforming XML documents.
The XSD schema instance nil attribute is the way to define an explicit null value in a XML document.
the WSDL contains nillable="true", but the client does not support
You need to explain exactly what you mean by this. Is the client unable to consume the WSDL from your service? What is the error they are getting?

WCF xs:date using Groovy

I have a WSDL I need to write a WCF client against (in C#). In the WSDL one of the elements is:
<xs:element name="TransactionDateTime" type="xs:date" />
For the moment I'm using a mock service created through SoapUI with that wsdl, so I can get mock responses where I'm trying to populate that TransactionDateTime using a groovy script.
My problem is whatever I use it seems to raise an exception in the client when trying to deserialize the reply body
String was not recognized as a valid DateTime
These are examples of what I've tried to return in the groovy script
new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").format(new Date())
javax.xml.datatype.DatatypeFactory.newInstance().newXMLGregorianCalendar(GregorianCalendar.getInstance())
If I try to hardcode it in the xml that I use as a response as
2014-09-11T10:11:555
which is by the way the format specified in the docs that came along with the WSDL it raises the same exception
Further more if I just hard code in the response a date like this '2014-09-12' instead of raising an exception it populates it as 01/01/0001 00:00:00 in the DateTime property of the C# class the response is populating
Can anyone give me any hint on which path should I follow?
UPDATE:
Wasn't 100% sure but I reckon the reason is the same as for this question or explained in other webs, WCF doesn't support xs:date. So I would ask the third party to change the WSDL and send the date as a string that I will parse. Can't thinkg of a better option

How can I make svcutil build a proxy to a schema with a jagged array?

We publish the functionality contained in our business layer via a WCF SOAP service.
We use VS2008 and write the XSD using visual design tools (XMLSpy) and generate the WSDL using WSCF.blue
In one of our schemas we have what is effectively a jagged array:
<xs:element name="CriteriaGroups" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="CriteriaGroup" type="SearchCriterion" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
When I generate a client, all calls to the service fail with this error:
Unable to generate a temporary class (result=1) error CS0030: Cannot convert type 'SearchCriterion[]' to 'SearchCriterion'
Common solutions on the net are to change the following line in Reference.cs from:
public SiDemSearchCriterion[][] CriteriaGroups
To:
public SiDemSearchCriterion[] CriteriaGroups
And all references from and to that property.
But that's no use because it may run, but it doesn't work.
It discards most of the data.
The setting to do it all as Lists just does nothing.
Any way to do this without changing the schema?
It's our schema so changing it is not too much of a problem.
I'd just rather not design it in a "Microsoft Schema" way.
The contract (WSDL + XSD) set is supposed to be platform independent and based on generic standards.
So:
Is there a way to make SVCUTIL build a working client without changing the schema?
How do I change the schema to make SVCUTIL build the client out of the box?

How to create a WCF web service within an ASP.NET application that can return instances of an interface as a transparent proxy

My use-case:
I already have a working ASP.NET application
I would like to implement a new Web Service as part of that application
I am supposed to use a WCF service (*.svc), not an ASP.NET web service (*.asmx)
The service needs to have one operation, let’s call it GetInterface(), which returns instance of an interface. This instance must reside on the server, not be serialized to the client; methods called on that interface must execute on the server.
Here’s what I tried (please tell me where I went wrong):
For the purpose of testing this, I created a new ASP.NET Web Application project called ServiceSide.
Within that project, I added a WCF Service using “Add → New Item”. I called it MainService. This created both a MainService class as well as an IMainService interface.
Now I created a new Class library project called ServiceWorkLibrary to contain only the interface declaration that is to be shared between the client and server, nothing else:
[ServiceContract]
public interface IWorkInterface
{
[OperationContract]
int GetInt();
}
Back in ServiceSide, I replaced the default DoWork() method in the IMainService interface as well as its implementation in the MainService class, and I also added a simple implementation for the shared IWorkInterface. They now look like this:
[ServiceContract]
public interface IMainService
{
[OperationContract]
IWorkInterface GetInterface();
}
public class MainService : IMainService
{
public IWorkInterface GetInterface()
{
return new WorkInterfaceImpl();
}
}
public class WorkInterfaceImpl : MarshalByRefObject, IWorkInterface
{
public int GetInt() { return 47; }
}
Now running this application “works” in the sense that it gives me the default web-service page in the browser which says:
You have created a service.
To test this service, you will need to create a client and use it to
call the service. You can do this using the svcutil.exe tool from the
command line with the following syntax:
svcutil.exe http://localhost:59958/MainService.svc?wsdl
This will generate a configuration file and a code file that contains
the client class. Add the two files to your client application and use
the generated client class to call the Service. For example:
So on to the client then. In a separate Visual Studio, I created a new Console Application project called ClientSide with a new solution. I added the ServiceWorkLibrary project and added the reference to it from ClientSide.
Then I ran the above svcutil.exe call. This generated a MainService.cs and an output.config, which I added to the ClientSide project.
Finally, I added the following code to the Main method:
using (var client = new MainServiceClient())
{
var workInterface = client.GetInterface();
Console.WriteLine(workInterface.GetType().FullName);
}
This already fails with a cryptic exception in the constructor call. I managed to fix this by renaming output.config to App.config.
I notice that the return type of GetInterface() is object instead of IWorkInterface. Anyone know why? But let’s move on...
Now when I run this, I get a CommunicationException when calling GetInterface():
The underlying connection was closed: The connection was closed unexpectedly.
How do I fix this so that I get the IWorkInterface transparent proxy that I expect?
Things I’ve tried
I tried adding [KnownType(typeof(WorkInterfaceImpl))] to the declaration of WorkInterfaceImpl. If I do this, I get a different exception in the same place. It is now a NetDispatcherFaultException with the message:
The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:GetInterfaceResult. The InnerException message was 'Error in line 1 position 491. Element 'http://tempuri.org/:GetInterfaceResult' contains data from a type that maps to the name 'http://schemas.datacontract.org/2004/07/ServiceSide:WorkInterfaceImpl'. The deserializer has no knowledge of any type that maps to this name. Consider using a DataContractResolver or add the type corresponding to 'WorkInterfaceImpl' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details.
The InnerException mentioned is a SerializationException with the message:
Error in line 1 position 491. Element 'http://tempuri.org/:GetInterfaceResult' contains data from a type that maps to the name 'http://schemas.datacontract.org/2004/07/ServiceSide:WorkInterfaceImpl'. The deserializer has no knowledge of any type that maps to this name. Consider using a DataContractResolver or add the type corresponding to 'WorkInterfaceImpl' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer.
Notice how this seems to indicate that the system is trying to serialize the type. It is not supposed to do that. It is supposed to generate a transparent proxy instead. How do I tell it to stop trying to serialize it?
I tried adding an attribute, [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)], to the WorkInterfaceImpl class. No effect.
I tried changing the attribute [ServiceContract] on the IWorkInterface interface (declared in the shared library ServiceWorkLibrary) to [ServiceContract(SessionMode = SessionMode.Required)]. Also no effect.
I also tried adding the following magic system.diagnostics element to the Web.config in ServerSide:
<system.diagnostics>
<!-- This logging is great when WCF does not work. -->
<sources>
<source name="System.ServiceModel" switchValue="Information, ActivityTracing" propagateActivity="true">
<listeners>
<add name="traceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="c:\traces.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
This does generate the c:\traces.svclog file as promised, but I’m not sure I can make any sense of its contents. I’ve posted the generated file to pastebin here. You can view this information in a more friendly UI by using svctraceviewer.exe. I did that, but frankly, all that stuff doesn’t tell me anything...
What am I doing wrong?
The use-case I am describing is not directly supported by WCF.
The accepted work-around is to return an instance of EndpointAddress10 which points to the service for the “other” interface. The client must then manually create a Channel to access the remote object. WCF doesn’t properly encapsulate this process.
An example that demonstrates this is linked to from the MSDN article “From .NET Remoting to the Windows Communication Foundation (WCF)” (find the text that says “Click here to download the code sample for this article”). This example code demonstrates both .NET Remoting as well as WCF. It defines an interface that looks like this:
[ServiceContract]
public interface IRemoteFactory
{
IMySessionBoundObject GetInstance();
[OperationContract]
EndpointAddress10 GetInstanceAddress();
}
Notice that the interface-returning method is not part of the contract, only the one that returns an EndpointAddress10 is marked with [OperationContract]. The example calls the first method via Remoting, where it correctly creates a remote proxy as one would expect — but when using WCF it resorts to the second method and then instantiates a separate ChannelFactory with the new endpoint address to access the new object.
What is MainServiceClient()? It is the class marshaling the client messages to the server.
You should take a look at a related SO post on returning interfaces as parameters in WCF. ServiceKnownTypeAttribute may be helpful.
Sessions may also be what you're looking for MarshalByRef as it relates to .NET Remoting behaviors.
Another approach (as mentioned on MSDN Forums) is to return the EndpointAddress of the service interface instead of the interface itself.
WCF does serialize everything - regardless of the binding. The best approach you should take if you need to communicate with the service on the same system is to use IPC transport binding (net.pipe).
What you are trying to do is a direct violation of the SOA Tenet: "Services share schema and contract, not class". What this means it that you don't actually pass implementation code from the service to its consumers, just the return values that are specified in the contract itself.
The main focus of WCF and SOA in general is interoperability, meaning services should be accessible to clients of any platform. How would a Java or C++ consumer be able to use this service you are designing? Short answer is that it couldn't, which is why you will find it difficult if not impossible to serialize this code over messaging standards like SOAP.
A more appropriate way to structure this code would be to host each implementation of IWorkerInterface as its own service (it has been defined as a service contract, after all), and expose each service on a different endpoint. Instead of MainService behaving as remote factory for proxies to an IWorkerInterface, it could act a as an endpoint factory to the different services you have set up. Endpoint metadata could easily be serialized and provided to the client by IMainService. The client could then take that metadata and construct a proxy to the remote implementation, either through some custom IServiceProxy implementation, or even through the objects already provided to you by WCF (such as the ChannelFactory).

How to add service known types from external config file

I am having difficulty understanding how to exactly go about adding known types; for WCF, from a configuration file that is external to my wcf. I found an example of how to set the configuration file up, however, I am a bit confused as to the way the file is set up and I am not sure as to how I am actually supposed to call this configuration file to load the service known types to my wcf. Here is the example of the configuration file containing the known types.
http://codeidol.com/csharp/wcf/Data-Contracts/Data-Contract-Hierarchy/
I am confused about why you have to add the a type and then specify another type as a child of that type just added. It seems to me you would just add the type "Contact", specify its assembly; "Host" and that would be it. Why is it that a knownType element tag follows the add type element tag specifying another type?
Also, once I have configuration file set up properly, when and how do I call it from my wcf? Any assistance would be appreciated. Thanks!
Update 1:
**Ok this gives me a better understanding, Thanks. I did try what you said though, and the ServiceKnownTypes were not found. The only thing I did different in my App.config file is in my service and host is that I didn't have any knownType type = "..." to specify. Here is mine at a glance. Do you have an idea what I'm doing wrong?
<system.runtime.serialization>
<dataContractSerializer>
<declaredTypes>
<add type = "Data,TestService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=57f2af9570299a17"/>
</declaredTypes>
</dataContractSerializer>
</system.runtime.serialization>
Sorry about posting this to comment section earlier, I hope this is clearer.**
Update 2:
Here is something closer to what I am trying to accomplish. What are your thoughts?
http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/6b70e9f4-52bc-4fa9-a0ff-c0859e041e85?prof=required
If you want to specify known types in config, follow this example that you mentioned:
<system.runtime.serialization>
<dataContractSerializer>
<declaredTypes>
<add type = "Contact,Host,Version=1.0.0.0,Culture=neutral,
PublicKeyToken=null">
<knownType type = "Customer,MyClassLibrary,Version=1.0.0.0,
Culture=neutral,PublicKeyToken=null"/>
</add>
</declaredTypes>
</dataContractSerializer>
</system.runtime.serialization>
You don't have to do anything more than this - you don't have to "load" the config or anything - WCF will do that for you. You need to put this into your web.config (if you're hosting your service in IIS and if your client is a web app), or in your app's config (if you have a Windows service on the server side, or a console / winforms app on the client side). Just put the entries in the config, and WCF will handle the rest.
Basically, what you're saying here is: any method that has a Contact from my Host assembly could also be returning a Customer from my MyClassLibrary assembly instead.
So basically, you're defining that MyClassLibrary.Customer is most likely a descendant type of Host.Contact.
That's the same as defining on your data contract:
[DataContract]
[KnownType(typeof(Customer))]
class Contact
{...}
You have an object class Contact, but anywhere you use it, it could also really be a Customer class instance instead.