How do I refactor data contracts in WCF services? - c#

We have lots of WCF services that are only used by our own code; the code that uses them is mostly in the same solutions files that contains the services.
However they do not use a shared assembly for the contracts, so each time a data contract is change the reference to the service has to be updated by hand in all projects that use the service. (Then the code needs to be fixed up by hand)
So how do I do a simple refactoring like renamed a data item in a data contract?
Is there a way to update all references to services in a single solution with one command, rather then having to click on each reference in each project?

You may have already answered you own question here.
Move your data contracts to a shared "Contracts" project, which will allow you to use the built in Refactor -> Rename option in Visual Studio to change the name, with the change being reflected in all of the projects in the solution.
Update
To clarify, the Contracts project is an internal "organisation" of your contracts. It allows many of your projects to reference one set of contracts. For example...
WCF service exposes "List GetCustomerById(int id)".
WCF service may call down to a processing layer, which might need to calculate something using another project etc. All of thes projects can use the single "Customer" definition from your Contracts project.
Any consumer of the WCF service would get the definition of the Customer via the service reference. You wouldn't share your Contracts project or send the dll for their use.

With your current settings you can't do it because you are regenerating the proxy each time. This is good from SOA perspective as data contract should not change very often. But if you are controlling both client and service and it is all .Net you can do as Shonee suggested. Use the /r option in svcutil to generate the proxy from the common assembly. Then you can refactor easily.

Related

Adding Service Reference to WCF does not always create .datasource files

In some projects when I add a service reference to a WCF service, it creates datasource files for classes shared in a common class library, however in others the datasources are not created. The Reference.cs file is different where in the first case the types are from the class library and in the latter it's in the Reference.cs file it self. These are not compatible.
What is it that triggers the automatic generation of the datasource files in this case? Advanced options in Add Service Reference dialog are identical so something else must be playing tricks on me.
UPDATE: Turns out the datasource files are not needed. It's the code generated in the Reference.cs file that makes the whole difference. I can manually edit the parameters for the methods to point to the class-library, and it works. This is of course not a solution in the long run, since I have to do this every time I update the Service Reference. Hopefully someone will come along who knows the trigger of this problem.
The file is created by VS when you add a service reference. It's used to enable client UI components to bind to the models (data contracts). I don't know why they are not created for "all" services (but I guess it depends on how that service defines and uses data contracts (as in: no contract no data file)).
Here are some useful links:
https://msdn.microsoft.com/en-us/library/ee373840.aspx
What are the WCF Service Reference .datasource files?
UPDATE: You are right it should not depend on the consumed service. Here are two related links (that impliece that the files are included by VS):
http://objectmix.com/dotnet/797048-wcf-service-reference-datasource-file-name-length-problem.html
Disable automatic generation of datasources file when updating service references
So it looks like the file is created by VS, if you don't wan/need it you can exclude it by creating the proxy with svcutil.exe

Not all namespaces coming across over WCF reference

I have 3 projects in my solution.
A common class library named ReportBuilderLib
A WPF application named ReportClient that contains a service reference to a 3rd project -
A WCF web service which contains web methods for my application to call upon.
Initially when setting up both the service and the application i added the common library to references on both projects so that i could use the classes i needed to in both.
It quickly cam clear that in the process of generating the code to use the web methods in my client application, it was automatically importing certain namespaces that i had used in service application.
This was throwing me conflicting reference warnings as they were effectively being imported from two separate resources.
I then removed the reference to the library in my report client, i could see that VS was only importing one out of the two namespaces my client requires. Both of which are returned by methods in my ServiceContract!
Having looked at the generated code for the client, it seems to be re-creating the classes i have included in the library and providing only the public properties for access.
Is it possible to use librarys like i am trying to with WCF. Or should i scrap the common library idea and simply create some data transfer classes on the service end?
You should be able to reference the common library on both ends, but it may be useful and less of a headache to implement data transfer classes like you suggested. Using special classes (or serialization like JSON) to send and receive data from the service would make it easier for you to re-use the service for multiple client projects.
Any time you decrease the coupling between layers of an application you make it easier to implement changes/upgrades in the future :)

WCF - Service Contract from another assembly

I have tried googling for an answer since last week and haven't found anything. Maybe I'm just searching with incorrect key words...
Basically, we have a running WCF service and then we have a separate dll with another ServiceContract in it. We want to know if it is possible to expose the separate dll in the current running service and if one can, how?
We are still new to WCF, so please excuse if this is a stupid question. :(
We are working with .NET 3.5 SP1 and C#.
Regards
EDIT:
We want to separate our service into "modules". So the service implementations (Methods, ect) and contracts (Interfaces) are all in separate libraries. So lets say you have a module called "Clients". We want everything related to Clients to be in the same separate library (DLL) instead of one big base class that inherits from multiple interfaces. This is a huge service and we need multiple developers to work on different sections of the same service at the same time. This is what I've been instructed to figure out, but if it can be done then it can't. I hope this makes more sens??
Assuming you are asking how you can implement a service contract declared in one DLL in a service running in a separate DLL/Application:
Edits to match post edits
add a reference to the DLL with the service contract to the application containing the service
In the .cs file with service implmentation add a using statement for the namespace of the service contract
derive the service from the service contract (you will have problems if you define your service contracts as concrete classes rather than interfaces and you want to expose multiple contracts on your service
If self hosting then create a ServiceHost passing the type object of the service in the other assembly, if IIS hosting create an .svc file referencing the class in the other assembly as the service
Add a service element in the config file naming the fully qualified name of the service
Add an endpoint to the service at a unique address for the new contract
When you take the other assembly (dll) as a reference in the "main" project, then add a using directive to the file where the WCF service is instantiated. Then you can simply use the referenced service contract to set up a running service with the right endpoints and binding(configuration).
I guess one work around is you have a main ServiceHost hosting your WCFMainLib and then all your clients will connect to WCFMainLib.
WCFMainLib then acts like a proxy to connect to all other WCFModuleLib on localhost (or other servers) to fetch data.
WCFMainlib will implement the IWCFModuleLib1, IWCFModuleLib2 etc service contract interfaces and expose them to the WCFClient. Actual implementation of interfaces will then be a call to the actual WCFModuleLibs.
This may introduce some overhead, but overall also introduces several "features" that may benefit your boss or service availability.
OR, if you are just wanting to delegate programming work, maybe you can tell each team to work with partial classes for your WCFLib with each service contract on a partial class then do a nightly compile.

Namespaces and type resolution in C# solutions with webservices

This might get a little convoluted so please let me know if you need clarification.
I have a solution which contains the following projects
Project A - WPF application
Project B - ASP.NET application (with exposed webservices)
Project C - Class Library
Both project A and project B reference types that are located in project C, but more importantly project A makes webservice calls to project B using types located in project C.
The problem I am running into is it appears that when making webservice calls I have no way of referencing the types located in project C directly but rather need to use the types as exposed by the webservice.
Now the basic idea of why this is done I understand (obviously typically the consumer of your webservice would only have the WSDL to go from) however in my case this is an internal application (which is part of a single solution) so this is not a concern.
The biggest problem I see with continuing this approach is that any updates to the types in project C will need to be reflected in project B and then "refreshed" in project A. This seems pretty nasty to me. Surely there is a smoother path?
Am I wrong? What is a typical approach to this issue?
You may be a little confused here.
The types in Project C and the types you see when you add a reference to your web service are different.
When you added the Web Service reference. Visual Studio used svcutil.exe, read metadata from your web service (I'm assuming .asmx?) and then created proxy classes for you.
Check the types for the Web Service (they will obviously have the same names). Put your cursor on them and pres F12. It'll take you to some designer generated code.
So there is no real workaround as such. When you update your types in Project C and then Update your web services in Project B . You will have to Update Service Reference from Project A Which again uses svcutil.exe and regenerates all your proxies.
Also, this is the same way WCF Services work too.
#giddy is correct - the types exposed by the web service are different to the types contained in Project C - even though their definition may be identical. The web service exposes type information via a wsdl, which Visual Studio uses to generate proxy types.
There is a way around this - you can create an interface which declares all the methods in the web service class, and include it in your shared library. You can then skip the "Add service reference" process, and create the web service proxy with code (you will not need the proxy classes, as you use the classes in the shared library).
Either way, if you make a change to your data transfer objects or the web service class, you will need to update the client by either by requerying the wsdl using "refresh service reference", or by copying the shared library over.

Making one copy of complex type from 2 webservices

In C# (other .Net OOP languages as well), I have 2 webservices. Svc1 returns a complex datatype which becomes the parameter for svc2. Note that it is the same complex type.
Now, I create the 2 proxy classes of these 2 webservices. Which means the same type gets generated twice.
How can I make sure that in 2 proxies only one copy of that type is there? You may assume same or different namespaces of 2 webservices.
Generate the two proxies at the same time:
svcutil http://example.com/svc1?wsdl http://example.com/svc2?wsdl
If the type is really the same (name and namespace) in both services it will generate only a single proxy class for the client.
Yet another possibility is to generate the proxy class for the first service:
svcutil http://example.com/svc1?wsdl
compile the generated .cs file into an assembly for example MyAssembly.dll and use the /reference option when importing the second service:
svcutil /reference:MyAssembly.dll http://example.com/svc2?wsdl
This will look for same types in the WSDL and the supplied assembly.
I've run into a similar issue recently; I haven't tried Darin's advice.
Miguel Castro of IDesign gave a great presentation on "WCF the Manual Way… the Right Way" at the March 2009 DevConnections. In that he showed how to reuse service contracts and proxies. From my notes:
One assembly for Service/Data Contracts
Shared between client & server
One assembly for services
Permits changing host and reusing
One assembly for proxies
Reuse among clients
Separate application for hosting
Do not use "Add Service Reference"
Service (POCO) project references Contracts (interfaces) project and System.ServiceModel
Client Proxies assemblies reference Contracts assembly but not Service project
Client applications instantiate proxies
Our company hasn't made the move to WCF yet, but this looks like the way to go (to me).
EDIT: I found an article by Mr. Castro on this.

Categories