Create assembly with datacontracts of WCF service - c#

Here is my issue: in a project I have to consume 3 third-party wcf services. 2 of those contain the same objects and largely the same methods.
The user's role within the application determines which service to use. For example: Let's say the 2 services are ServiceRoleA en ServiceRoleB. Both services contain the method GetInfo() end return the InfoDetails object. The InfoDetails object has the exact same signature for both services.
If I just add 2 service references to my project I'll get the objects ServiceRolaA.InfoDetails and ServiceRoleB.InfoDetails. Instead, I need just one object InfoDetails. I only want to write just one routine to handle the InfoDetails etc.
My initial thought was to create an assembly with the datacontracts of the services and reference the assembly in my project. This way the service references can use the common set of objects. For this to work I have create the datacontract classes using svcutil and the wsdl, but I get error upon error.
When I try the following:
svcutil *.wsdl /dataContractOnly /n:*,DataContracts
/language:C# /out:XxxData.cs
I get the following error:
"Error: Type 'AuthenticationBase' in namespace 'http://schemas.datacontract.org/2004/07/xxx' cannot be imported. It references 'KindOfModule' from namespace 'http://schemas.datacontract.org/2004/07/yyy' but schema does not contain appropriate statement. Either change the schema so that the types can map to data contract types or use ImportXmlType or use a different serializer.
If you are using the /dataContractOnly option to import data contract types andare getting this error message, consider using xsd.exe instead. Types generatedby xsd.exe may be used in the Windows Communication Foundation after applying the XmlSerializerFormatAttribute attribute on your service contract. Alternatively, consider using the /importXmlTypes option to import these types as XML types to use with DataContractFormatAttribute attribute on your service contract."
Exporting the datacontracts as XML types is no option for my so the next thing to try was:
svcutil *.wsdl /dataContractOnly /n:*,DataContracts
/serializer:XmlSerializer /language:C# /out:XxxData.cs
Which resulted in the exact same error. So I decided to try the other mentioned option to use XSD.exe. But that is also nog working since I only have a WSDL and XSD.exe requires a XSD file. Are there any more options I can try? Please help!

You don't need to add service references or using svcutil to create the client proxies, that is easily done by hand.
Create a contracts assembly that contains all service interfaces and data contracts.
Reference that assembly from both the server(s) and the client (be sure to update the web.config and .svc files to reflect these changes)
Create client proxy classes for your services.
A client proxy is as simple as adding a class like
public class ServiceRoleAClient : ClientBase<IServiceRoleA>, IServiceRoleA
{
public InfoDetails GetInfo(GetInfoRequest request)
{
return Channel.GetInfo(request);
}
}
The only drawback is that you'll have to maintain the system.serviceModel node in the app.config file yourself.

Related

Generate Proxy from WSDL

I have a single self-contained (third party) WSDL file with say 10 operations. (server is not .net)
All operations have their own XML namespaces defined for operations, messages and all the underlying types.
Some of the underlying types in different operations have same names and sometimes same content or same structure (not always) as well but they are actually different as they are defined in different xml/xsd namespaces (so they are unique).
When I import this WSDL into my c# client project, I can give it one unique namespace in the VS porject and it generates the proxy/stub.
The problem is wherever the different operations have same (xml type) names for the underlying types then it generates the c# class names like: MyType1, MyType2...
Additionally the third party server, can update the service and so the WSDL is updated and the underlying types are generated again into .net classes like MyType1, MyType2... but this time, maybe previously generated MyType6 is generated as MyType7 and this breaks the client/consumer code.
What solution exists to address this problem?
We are thinking to customize the wscfblue code but it seem to be a cumbersome work and would require maintenance..
Environment:
-VS2013 Ultimate (Client)
-.net 4.5 (Client)
-Unknown technology (Server) -> generates WSDL and provides the endpoint.
You can generate the proxy using svcutil.exe and provide mappings from xml namespaces to CLR namespaces with /n. It also supports multiple mappings, which it sounds like you need.
Example: use svcutil to map multiple namespaces for generating wcf service proxies

Project structure for Schema First Service Development using WCF

I have WSDL and XSD as starting point. (WSDL is generated from XSD using WCSF Blue tool). From the WSDL, using a tool, the service code is generated. The project name is “Autogenerated_Service_Project”. Inside this project it will have [ServiceContract] and [DataContract] classes. It has a data contract named “EmployeeDataContract”. In the GetEmployee() service operation, this datacontract is returned to the client.
I have a business layer project named “Business_Project”. It has a method that returns “Employee” entity object.
At present, I am referring the “Business_Project” inside “Autogenerated_Service_Project”.
Business_Project.MyClass b = new Business_Project.MyClass();
EmployeeDataContract d = b.GetAssociate();
return EmployeeDataContract;
The challenge comes when there happens a change in WSDl. When the WSDL is the changed the “Autogenerated_Service_Project” will be recreated and the code mentioned above will be lost.
What is the solution to overcome this code lose?
Note: The “Autogenerated_Service_Project” is the top most project. Ideally, it cannot be referred by any other projects.
You may change the way calling Business layer(may your solution needs additional layer)
But in simple way, you can generate the proxy once, when changes happen to WSDL
handle the changes manually,Or use the tool only for new services.
If the services on WSDL are finely grained, the solution may be applicable.
This can be resolved by using Partial Classes in a different file. The code given in the question can be moved to this new partial class file. This file will persist even if the auto generated file is re-created.

Storing classes transmitted over wcf

When I use svcutil or some other proxy generator it creates appropriate classes in client. I wonder what is the best way to store this classes to avoid conflicts.
In some other "Common" project and remove generated classes from proxy?
Or just use original classes in service and theese duplicated in proxy?
There are two ways to handle the code for service and data contract classes WCF clients.
Generate everything using svcutil.exe. Don't have any kind of reference from your client project to the service assembly. Just use the classes generated by svcutil.
Reference the assemblies containing the types directly. I sometimes use a separate assembly for my DTO classes, that is references from both the client and the server. When generating the client code with svcutil, use the /reference:<file path> option to tell svcutil to reuse the types from an existing assembly instead of regenerating them.
If you reference the origin assembly, without passing it with /reference to svcutil you'll end up with a mess of conflicts. I guess that's what happened to you.

Is there a way to export an XSD schema from a DataContract

I'm using DataContractSerializer to serialize/deserialize my classes to/from XML. Everything works fine, but at some point I'd like to establish a standard schema for the format of these XML files independent of the actual code. That way if something breaks in the serialization process I can always go back and check what the standard schema should be. Or if I do need to modify the schema the modification is an explicit decision rather then just a later affect of modifying my code.
In addition, other people may be writing other software that may not be .NET based that would need to read from these XML files. I'd like to be able to provide them with some kind of documentation of the schema.
Is there some relationship between a DataContract and an XSD schema. Is there a way to export the DataContract attributes in classes as an XSD schema?
Yes, you can use XsdDataContractExporter.
An example is provided in the MSDN article Exporting Schemas from Classes.
Svcutil.exe can "export metadata for compiled data contracts".
There is relationship between DataContract and XSD:
The DataContractSerializer maps CLR types to XSD when metadata is exported from a Windows Communication Foundation (WCF) service using a metadata endpoint or the ServiceModel Metadata Utility Tool (Svcutil.exe). For more information, see Data Contract Serializer.
The DataContractSerializer also maps XSD to CLR types when Svcutil.exe is used to access Web Services Description Language (WSDL) or XSD documents and generate data contracts for services or clients.
You can get the XSD(s) at run-time as well, even in your browser, by setting up a MEX endpoint.
The WSDL by default will contain references to XSD(s) that can be accessed through the endpoint as well.
You might be able to generate schema files from DataContracts using the svcutil.exe tool that comes with Visual Studio.
svcutil myAssembly.dll
- Generate metadata documents for Service Contracts and associated types in an assembly
svcutil myServiceHost.exe /serviceName:myServiceName
- Generate metadata documents for a service, and all associated Service Contracts and data types in an assembly
svcutil myServiceHost.exe /dconly
- Generate metadata documents for data types in an assembly
I believe I messed with this at one point in the past, and may or may not have gotten it to work. Another easy way to generate schemas is to stand up a WCF service that uses your data contracts, and access the WSDL. The WSDL will import all the xsds for the DataContracts.

/sharedtypes equivalent for svcutil.exe?

Building an app that is relying on a 3rd party provider who has a very verbose set of SOAP services (we're talking 50+ WSDL files). Each individual WSDL however has numerous shared type declarations. When generating client code with wsdl.exe, there used to be a /sharedtypes flag that would merge duplicate entries if a type was found several times.
When I attempt to generate my client code, I bomb on these overlapping types that the 3rd party includes in all their WSDL files.
svcutil /t:code /importxmltypes [mypath]/*.wsdl
Results in error messages alluding to the type collisions. For example, a couple samples of the error messages below:
Error: There was an error verifying some XML Schemas generated during export:
The simpleType 'http://common.soap.3rdparty.com:CurrencyNotation' has already been
declared.
Error: There was an error verifying some XML Schemas generated during export:
The complexType 'http://common.soap.3rdparty.com:NumberFormat' has already been
declared.
I do not have control over the output of the WSDLs. I do not want to have to edit the WSDLs by hand for fear of an error that breaks in a fashion at runtime that would be highly difficult to track back to our editing of the WSDL files. Not to mention that there are 50 some WSDL files that range from 200-1200 lines of XML. (Remind me again why we thought SOAP was the great salvation to us all back in the late 90s?)
Try specifying all the WSDLs in one command:
svcutil http://example.com/service1?wsdl http://example.com/service2?wsdl ...
This should automatically take care of duplicate types. Another option is to take a look at the /reference command switch:
/reference:<file path> - Add the specified assembly to the set of
assemblies used for resolving type
references. If you are exporting or
validating a service that uses 3rd-party
extensions (Behaviors, Bindings and
BindingElements) registered in config use
this option to locate extension assemblies
that are not in the GAC. (Short Form: /r)
This means that if you already have some types defined in some assembly you may include this assembly and svcutil will exclude types from it to avoid duplicates:
svcutil /reference:someassembly.dll http://example.com/service?wsdl
I was having similar problems. By defining different CLR namespaces for the different xml namespaces (using the /namespace argument of svcutil) i was able to get it working.
/namespace:http://www.opengis.net/gml,OpenGIS.GML
I have been using wsdl.exe to get round this because I work with some SOAP webservices which define the same data transfer objects at different endpoints. So I use wsdl.exe because it has the sharetypes switch. I'm not a WPF developer so I don't really care that the output does not implement IWhatever for WPF, but the classes generated are all partial so you can do some work to implement interfaces you care about in a separate file.

Categories