I have some WCF services and have separated out the data contracts for these services into their own assembly. I then have a client of the services that references the data contracts assembly.
I have turned on the option to Reuse types in referenced assemblies. This works, but not for collections. The proxy generator instead generates its own version of collections, even though that version is exactly the same as the one in my data contracts assembly.
Is there any way to tell the proxy generator to reuse the collections defined in my data contracts assembly rather than generating its own, redundant collection types?
If you have controll of both the server and the client, you do not need to generate a provy.
There is a good explaination in this screencast.
We have stopped using generated proxies. We have saved weeks of work compared with continually having to update the generated proxies, and debugging when the problem was that someone forgot to update the proxy.
Related
I went through many posts but, i did not able to clear my some of basic doubts related to WCF service as follow:
Why should we keep separate class library projects assembly for Service.Contracts and Service.Implementation ?
we can implement one interface multiple times even it in single assembly.
It suppose to create - WCF Application project and maintain interfaces into separate folder and SVC.cs file separately.
Add service reference is not good option as it adds all the schemas into client side.
svcutil.exe is also do same thing. Then, what is the best way to consume wcf service at client side ?
All is explained in this great article - WCF the Manual Way…the Right Way.
Essentially, Add Service Reference and svcutil just lead to client proxies that become out of date over time; and the fact that the solution has multiple types defined for what are essentially the same class.
Update: Since writing this answer I have learnt not to have answers in another castle so I update below:
Essentially, WCF the Manual Way…the Right Way describes that rather than using Add Service Reference, you instead divide your WCF system into separate dlls for:
Contracts
Service implementation
Roll-your-own client proxies
Both the service and client add normal code references (not service references) to the contracts dll.
In this way, the service and client are using the same types (and not code-generated ones in the client) and when the contract changes - both the service and client are forced to update less a compile error appears. No more out-of-date clients.
I found an issue but it refers to the BETA version of VS 2010. I am interested in knowing if this issue has been fixed in RTM?
Basically it states (saw it via EF 4 Self Tracking Entities does not work as expected )
Make certain to reuse the
Self-Tracking Entity template’s
generated entity code on your client.
If you use proxy code generated by Add
Service Reference in Visual Studio or
some other tool, things look right for
the most part, but you will discover
that the entities don’t actually keep
track of their changes on the client.
I am very used to using Add Service Reference, and its always worked great for me in the past but of course I wasn't using STE (Self tracking entities). Is this problem still apparent with VS 2010 RTM and the STE template?
If I do create the proxy via code instead of add service then all the classes won't be created will they?
This is not an issue and it never was an issue. It is absolutly expected and correct behavior. STEs are classes which contains data and logic (the logic tracks changes).
When adding service reference your client proxy code is generated from service's metadata. Metadata are exposed in form WSDL. WSDL is XML based description of the service which also contains XSD description of transfered data types. XSD can describe only data format but not related logic implemented by the type. By default all unknown data types described in WSDL are generated on the client. So when you generate client proxy with all data types by Add service reference the tracking logic is lost.
To overcome this issue you have to do two things:
Create separate assembly and place all your STEs to this assembly. Then share this assembly among all involved layers (yes you have to use Add reference in your client).
Then you can use Add service reference with "Reuse types in referenced assemblies" checked.
I am building a set of WCF services that share common data contracts (or entities if you prefer). These are simple data transfer objects that are decorated with DataContract and DataMember attributes. I am explicitly specifying the name and namespace. In trying to follow the principles of IDesign's recommendation of averaging 12 members per service contract, I am breaking my service project into multiple services.
My data contracts are in a separate assembly that I can provide to our clients if they are using .Net. They can tell their service reference to reuse types in referenced assemblies. However, if they are not using .net and they use 2 services that both use the same entity then they will, I assume, get an ambiguous reference message. I can see this in Visual Studio if I don't reference the data contract dll.
My question is, is there anything I can do in my services, or they can do in a client app to get around having to qualify which proxy the data contract came from?
Nice article that describes how to solve this issue.
Sharing DataContracts between WCF Services
I also tend to keep all my Data Contracts in one assembly which is referenced by multiple services and numerous client apps, which works great but I've never tried consuming the service outside of .NET.
It might be helpful to know what technology they are using to consume the service other than .NET? What is throwing the ambigious reference message?
I happen to have multiple services that share objects on my end. I am not certain why you are having this problem. In my case, I am able to access the objects in this way. . . .
SERVICE1 client = new SERVICE1()
client.CommonLibrary.Address. . .
SERVICE2 client2 = new SERVICE2()
client2.CommonLibrary.Address . . . .
It depends on what tools they are using on the client side. For instance, with Axis2 for Java the wsdl2java tool can share types by using the -u switch.
how can I share proxy objects across multiple Axis2 web service clients?
From my understanding and working with WCF, either one of the data contract used by the client app would not matter as long as the fully qualified name is the same and has the same data members. Internally it just create the object dynamically and reassign those data member property using the public setter.
A better approach I think is to refactor your data contract so that you will put all the common across more than one service into one assembly and refer to them hence you will not have this ambiguious or conflict issues regardless how many services are used by the client app.
We generate our service proxies not through the Visual Studio assistant but by custom batch files calling slsvcutil.exe (as we use Silverlight). There you can specify a namespace mapping using the /n parameter like this:
"C:\Program Files (x86)\Microsoft SDKs\Silverlight\v5.0\tools\slsvcutil.exe "^
http://ServiceUrl/MyService.svc^
**/n:http://youruri.org/CustomerService/DataContracts,CLR.Namespace.CustomerService^**
/n:*,CLR.Namepsace.MyService^
/r:"%ProgramFilesFolder%\Reference Assemblies\Microsoft\Framework\Silverlight\v5.0\System.Windows.dll"^
/ct:System.Collections.ObjectModel.ObservableCollection`1^
/edb^
So all data contracts having the namespace http://youruri.org/CustomerService/DataContracts are generated to the clr namespace CLR.Namespace.CustomerService in the proxy file and so on. Given you have generated this proxy in advance in the same proxy assembly, you can cut this whole namespace out of your second file and everything works fine - we wrote a small tool for the last step. All other contract namespaces will be generated to the CLR.Namepsace.MyService namspace (see the asterisk meaning catch all)
The process is some hazzle to set up because you have to hand craft the batch files, but once this is done it works well.
i have two web services. One with user functionality, one with admin functionality.
Both services effectively work with the same object types, for instance:
AdminService provides functionality for deleting/modifying Customer objects
UserService provides functionality for listing/reading Customer objects
Now in the client i have two service references, Webservices.Admin and Webservices.User.
If i use the UserService to retrieve Customer objects, i cannot manipulate those via the AdminService, since the UserService retrieves objects of type Webservices.User.Customer, however the AdminService works with objects of type Webservices.Admin.Customer.
On the server side both types are identical, just belong to different namespaces in the client.
Now the question: How can i share types across different service references?
Check out https://github.com/geersch/WcfSvcMap
By tweaking the Reference.svcmap file you can make sure only one class is generated for each DataContract used by the different service references.
Note: Remember to delete the content of the node before pressing 'Update Service Reference'
If you're controlling both ends of the communication, and both ends are .NET only, you could do this:
put all your contracts, including your data contracts, into a separate "Contracts" assembly
reference that assembly in both the server side implementation code, as well as the client side code
If you do this, when adding the service references, WCF will find and use that shared assembly, and not create new types for the entitites. In your case, you'd only ever have one type Contracts.Customer or whatever you're dealing with.
This works only if you control both ends of the wire and have .NET on both ends! But in that case, it's a great way to share contracts - especially data contracts - across both the server and any number of clients.
Use the slsvcutil to create the WCF proxy on the clientside (assuming the clientside is a .net application), reference the DLL which contains your objects and it will be used for all endpoints that pass the same object in the DLL
Open Visual Studio Command prompt from the Start -> Visual Studio 2008 -> Tools -> Visual Command Prompt
goto directory similar to
C:\Program Files\Microsoft SDKs\Silverlight\v3.0\Tools
type slsvcutil and follow the syntax
slsvcutil http://somewcfservice:8080 /r:CommonLibrary.dll
where CommonLibrary.dll is the dll that contains the business objects
[edit] fixed the fact that the project is a silverlight project
There is an easy way to share types between client and service, just by adding reference to shared type assembly to your client BEFORE adding the service reference.
You can find the detailed scenario and sample project there:
http://blog.walteralmeida.com/2010/08/wcf-tips-and-tricks-share-types-between-server-and-client.html
Greetings!
I am using a WCF library on an application server, which is referenced by an IIS server (which is therefore the client). I would like to put my validation in a place so that I can just call .Validate() which returns a string array of errors (field too short, missing, etc). The problem is, such functions don't cross the WCF boundary and I really don't want to code the same logic in the WCF service and in IIS/WCF client. Is there a way to use extension methods or something similar so both side can use use a .Validat() method which calls the same code?
Many thanks for any ideas!
Steve
If you control both sides of the wire, i.e. the server-side (service) and the client-side, then you could do the following:
put all your service and data contracts into a shared assembly
reference that "Contracts" assembly from both the server and the client
manually create the client proxy (by deriving from ClientBase<T> or by creating it from a ChannelFactory<T>) - do not use "Add Service Reference" or svcutil.exe!
put all validation logic into a shared assembly
reference that shared validation assembly from both projects
If you want to use a shared validation assembly, you must make sure the data types used on your server and client are identical - this can only be accomplished if you also share service and data contracts. Unfortunately, that requires manual creation of the client proxy (which is really not a big deal!).
If you'd use "Add Service Reference", then Visual Studio will inspect the service based on its metadata, and create a new set of client-side objects, which look the same in terms of their fields and all, but they're a separate, distinct type, and thus you wouldn't be able to use your shared validation on both the server-side and the client-side objects.
Do you have a problem with sending the data over to the server to be validated? In other words, your service interface actually offers the "Validate" method and takes a data contract full of data, validates it and returns a List where T is some kind of custom ValidationResult data contract that contains all the info you need about validation warnings/errors.
In a service architecture, you can't trust the client, who could theoretically be some other company altogether, to have done proper data validation for you. You always need to do it at the service layer and design for communication of those validation issues back to your client. So if you're doing that work at the server anyway, why not open that logic up to the clients so they can use it directly? Certainly the clients can (should) still do some kind of basic input validation such as checking for null values, empty strings, values out of range, etc, but core business logic checks should be shipped off to the service.