I have five separate services where each one corresponds to a different database table such as Product, User, Orders etc.
I am trying to send my custom exceptions across WCF. I have browsed the internet and i have wrapped my custom exceptions inside a fault exception:
interface
[FaultContract(typeof(NoSuchInstanceException))]
cs
throw new FaultException<NoSuchInstanceException>(e, new FaultReason(e.Message), newFaultCode("UserFault"));
The problem is when i update the service the client proxy disappears. I browsed the internet and found the following solution which says to add a mapping to the service reference SVCMAP file. http://travisspencer.com/blog/2007/11/
<NamespaceMapping
TargetNamespace="http://schemas.datacontract.org/2004/07/MyCompany.MyProject.Exceptions" ClrNamespace="MyCompany.MyProject.Exceptions" />
</NamespaceMappings>
My problem is that every service needs the custom exceptions adding to the mapping but when i do this. An error is displayed saying the exception is already defined in one of the other services. Do i merge the services into one service? Any help is really appreciated. Thanks
I can think of two options:
Merge the services into one - having multiple services sharing the same data types gives this problem on the client.
Move the shared data types into a separate dll (class library project). Then reference that shared data type library from both your server and client. When you create the services reference, choose the option to reuse data types.
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 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
Right now we have around 5 service reference added to our projects in a single solution.
I am force to add service reference even for projects having indirect dependencies calling service methods. Is there a way to get around for this situation.
For every single change in the service method, I have to update every single service reference to effect those changes. It is very time consuming too.
I am just wondering, is there any way i cam manage these things globally by making single service reference for the whole solution.
help appreciated.....:)
You should be able to use the svcutil.exe command line utility to generate a single service file (.cs file for example) from multiple service URL's. The nice thing about this is that you can share clinet-side DTO's and message types accross services if they have the same schema.
SvcUtil Reference: http://msdn.microsoft.com/en-us/library/aa347733.aspx
In regards to the requirement of adding the service reference to projects with indirect dependencies. You should probably not consume the service reference and related types directly from your service client. To improve maintainability and adaptability, you should wrap your service reference(s) in a facade. The facade would map between local types and service reference types, and give you much more agility in terms of responding to service changes. You would then only need to have the service references in a single location (preferably an independent project) along with the facade. The facade, which should change infrequently, will buffer you from the issues you are currently having with your service references.
You won't be able to get a single reference if you have multiple service, unfortunately.I stand corrected - see jrista's answer.
What you could do is create and update the service references automatically: instead of adding them manually in Visual Studio using Add Service Reference check out the svcutil.exe command line tool which will basically do the same thing.
Since it's a command line tool, you can have it run as e.g. part of your continuous build and update the necessary proxy client files every time you build the app.
Check out these additional links for tutorials and explanations about the details of using svcutil.exe:
http://msdn.microsoft.com/en-us/library/ms734712.aspx
http://asadsiddiqi.wordpress.com/2008/10/25/how-to-generate-wcf-client-proxy-class-using-svcutilexe/
http://www.xvpj.net/2008/03/08/wcf-step-by-step-tutorial/
Marc
I am invoking a service through WCF and has encountered a problem with non-matching namespaces.
The object that is beeing sent though the service is in the namespace MyProject.Commons.BuisnessObjects, and I have verified this through WcfTestClient.
When I invoke a method clientside on the service (after initiated this with new MyServiceClient()), the method give me the correct objects, but with different namespaces.
The object is now of Web.MyService.Object. I have tried casting, but that didn't help.
Anyone who has seen this before?
Thanks, Tine
This is the expected behavior. It's how Web Services work. They are meant to be different types.
If you have added a service reference (i.e. WCF) rather than an old fashioned web reference, then you can match these up. Add a reference to the shared library defining your object type to the client before you add the service reference, then there is an option when you add the reference to re-use types.
This is because your types are not shared across service and client. Therefore the client does recreate for you your datastructures, in the Web.MyService namespace.
To avoid this you should share your data structure types between client and service by referencing your assembly containing your type 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