Reusing service proxies - silverlight

I have a set of webservices that I connect to using Silverlight Client. I use proxies generated by "Add service reference" or SLSVCUTIL.exe tool to connect to this service. So far, I have only used one single service. Now I want to use another service on the same server.
The problem is that, first service generated set of proxy classes for me, and second service will reuse the same set of classes (plus extra services/classes), e.g.
CustomerService.SaveCustomer(Customer customer);
OrderService.CheckCustomerLevel(Customer customer);
The problem is when I add reference to the second service, I can not reuse the same namespace for the second one (VS error), and when I use a different namespace, the generated classes, although are essentially the same, reside in different namespace, hence different and I end up with two Customer classes in two different namespaces.
Anyway around this? I just neeed to have two set of services, reusing the Customer class. I have already tried "reuse types in assembly / all assemblies" check mark when generating proxy classes, but it seems to have no effect.
any help is greatly appreciated.

I've run into this problem before, and the only solution I could come up with was to combine both web services into a single web service. This seems to be a limitation of the Add Service References/SLSvcUtil way of doing things.
If you're using Silverlight 4, you could conceivably try Silverlight/.NET assembly sharing to get around this (though I haven't tried it myself). In other words, compile the assembly that contains your data transfer objects in Silverlight, and then share it with the .NET/WCF back-end. That way, if you choose "Reuse types in assemblies", it would (in theory) actually re-use the existing Silverlight types for both service references.

Related

Obfuscate WCF Proxy Classes

How to obfuscate WCF proxy classes using Dotfuscator ?
I have downloaded Dotfuscator Pro Edition Trial from their website. I obfuscated my app.exe file ,everything was nicely obfuscated but WCF proxy classes were not. (I ILDASMed the exe).
The WCF Proxy classes are giving away structure of my application.Is there any setting I am missing in Dotfuscator application?
Is there a better way to hide WCF service proxy classes?
One way or another, WCF must be able to bind elements in your service's data contract to your client's proxy classes. There is usually little value is obfuscating the proxy classes and their members, but if you do want to obfuscate them you can explicitly set the name of the types and their members using the Name parameter of the [DataContract] or [DataMember] attributes (eg. [DataMember Name="ID"]). Once you've done this, you can disable the "Types and fields marked as serializable" built-in rule from the Rename -> Built-In Rules tab and ensure that "Compatibility with XML serializer" is checked in the Rename -> Options tab. The caveat to this approach is that the names of the serialized properties are still included in your code (in the attributes), and are still sent over the wire.
If you require more protection and you have control of both the service and the client, a better but more cumbersome option might be to put your service contract in its own assembly and process that with Dotfuscator. Again, disable the "Types and fields marked as serializable" built-in rule from the Rename -> Built-In Rules tab and ensure that "Compatibility with XML serializer" is checked in the Rename -> Options tab. Now reference the resulting service contract DLL from both your service and your client application. The tradeoff with this approach is that the contract members will all have obfuscated names (eg. "a") and you will have to reference them as such in your service and client application code. You can examine the map file Dotfuscator produces in order to make sense of the renamed names.

Generating Silverlight service reference - how to tell what is causing proxy classes to be generated

I have a large object structure that I'm wanting to share between a .Net4 backend and a Silverlight 5 front end. I've created two class library projects of the appropriate type, and have my object structure implemented in the .Net library, and linked into the SL library. On the Silverlight client side I am referencing the Silverlight class library. When I generate the service reference I have checked the option to "Reuse types in referenced assemblies". However when I generate the service reference I am finding that types that are in referenced assemblies are still being generated. It is only certain types, and appears to be largely collection types (attributed with <CollectionDataContract>).
I have a main object that has many properties which are generally either List<MyTypeA> or in some cases they are MyListTypeB, where MyListTypeB inherits from List<MyTypeB>. It seems to be the classes similar to MyListTypeB that are causing the proxies to be generated. These are all attributed with <CollectionDataContract> and have a default constructor.
I also find that even though the project where I am adding the service reference to has a reference to the other SL project containing the entities, when I update the service a new reference directly to the dll is also being added to the project. I'm not sure why this is happening, or if it is causing confusion in the service proxy generation
Is there any way to tell what classes/properties are causing the service generation to generate proxy classes? Or is it a case of trial and error having to comment out attributes until they aren't generated and hone in on the problem class?
I have now found out about the use of the svcmap file, and updating the CollecitonMappings elements to include my collection types, described here:
http://mostlydevelopers.com/blog/post/2009/12/14/Configure-WCF-Service-ndash3b-Reuse-Collection-Types-Issue.aspx
It seems a little unusual that the svcmap functionality is so undocumented.
I was able to add an entry int he svcmap file similar to the following:
<CollectionMappings>
<CollectionMapping TypeName="MyNamespace.MyType" Category="List" />
</CollectionMappings>
And then when I updated the service reference the proxy collections are not generated.

What is the correct way to solve the ambiguous reference issue in WCF services?

Project Structure
I have a silverlight project SLProj, that references a silverlight class library project called ServiceClients. ServiceClients has two wcf service references, Svc1.svc and Svc2.svc. Both Svc1.svc and Svc2.svc are in two different WCF projects which use the same set of DataContracts which are again in a different class library project called MyDataContracts.dll.
Problem description
Now in my ServiceClients project I get an ambiguous reference issue when I need to use a datacontract class which is present in both the service references. If this were a winforms or webforms project, I could reference the MyDataContracts.dll and reuse the common types. But since, this MyDataContracts.dll was built using a non silverlight class library, it can't be referenced in the silverlight project
Workaround...
I am not sure if this below is the best method to go about taking care of this issue. Can anybody let me know if there is a cleaner way to solve this problem, or is this the best way we have so far?
create a single service reference.
click the 'show all files' button in the solution explorer
drill into the service reference and find Reference.svcmap and open it
find the MetadataSources section
add a second line to include the address to your second service. for example:
MetadataSource Address="http://address1.svc" Protocol="http" SourceId="1"
MetadataSource Address="http://address2.svc" Protocol="http" SourceId="2"
save, close, and update service reference.
Use Automapper
Map the DataContracts with AutoMapper.
You will have to invest some time in understanding AutoMapper and reworking your application. Also AutoMapper adds overhead because all data objects will be mapped. But first you will have a clean solution without hacks and second you gain a decoupled and simple data object layer just for your client. Once done you can forget the mapping but you stay flexible for future changes.
If you never have worked with Automapper it's important to play around with it before starting. Automapper is special and needs some time to familiarise with it.
So there. These are the rough steps:
1. Create a subdirectory and sub-namespace Data and copy the DataContracts. Remove the attributes and properties your client doesn't need because these mapped classes live only in your client. You can also change some types or flatten some complex properties.
2. Create an AutoMapperInit.cs like described at Automapper (read the Getting Started Guide). Use the conflicting references like this:
using ref1 = YourProjectServiceReference1;
using ref2 = YourProjectServiceReference2;
3. Wrap the service client like this:
Example GetExample() {
return AutoMapper.Map<ref1.Example, Example>(ref1.YourService.GetExample());
}
The wrapper also needs the same using directives as in step 2.
4. In this wrapper add a static initializer like this (assuming your wrapper class is called Wrapper):
static Wrapper() {
AutoMapperInit.CreateMaps();
}
5. Omit service references in the client and use using YourClient.Data;, the namespace you created in step 1.
Your client is now decoupled from the service and you don't have conflicts anymore.
Disclaimer: I am not affiliated with AutoMapper. I just used it in a project with a similar problem and am happy with it and wanted to share my experience.
Your workaround is actually quite OK. We've used it in several projects like this with 3 service references. It is actually a workaround for the IDE which for some reason only allows to select one service to create a service reference at a time.
Another thing you could try-out is to multi-target your shared contract to .NET and Silverlight, using the same codebase. Details on how to do such thing is described in http://10rem.net/blog/2009/07/13/sharing-entities-between-wcf-and-silverlight. Might be more work but feel less hacky.

WCF from Silverlight without using Add Service Reference

David Betz describes in his article how to create reference to WCF without using "Add Service Reference" option:
http://www.netfxharmonics.com/2008/11/Understanding-WCF-Services-in-Silverlight-2
Once WCF service is created, these are the statements within the silverlight:
BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
EndpointAddress endpointAddress = new EndpointAddress("http://localhost:1003/Person.svc");
IPersonService personService = new ChannelFactory<IPersonService>(basicHttpBinding, endpointAddress).CreateChannel();
...
How does one references the types (such as IPersonService interface) created in WCF from Silverlight when I do not use "Add Service Reference" to buid proxies?
Idea is to reference assemblies that contain WCF data contracts in silverlight application, and to do that you need to fool VS so it thinks assembly is a SL assembly, he describes this in detail here
http://www.netfxharmonics.com/2008/12/Reusing-NET-Assemblies-in-Silverlight
and its not so easy, here is what needs to be done
Just use the same ILDasm/Edit/ILAsm
procedure already mentioned to tell
the assembly to use the appropriate
Silverlight assemblies instead of the
.NET assemblies. This is an extremely
simple procedure consisting of nothing
more than a replace, a procedure that
could easily be automated with very
minimal effort. It shouldn't take you
much time at all to write a simple
.NET application to do this for you.
It would just be a simple .NET to
Silverlight converter and validator
(to test for assemblies not supported
in Silverlight). Put that application
in your Post Build Events (one of the
top 5 greatest features of Visual
Studio!) and you're done. No special
binary hex value searching necessary.
All you're doing is changing two well
documented settings (the public key
token and version).
Second solution is a file level solution , you use add link option on files that contain your required data contracts implementations to SL and make sure they only contain types that allow to build SL and dont reference a lot of external assemblies , usually those conditions should be met for WCF services & data contracts.
I can write more but it would be just the copy paste from that link
You also have to split all methods declaration in you IPersonService according to Async pattern (BeginXXX/EndXXX) since Silverlight supports only asyncronous WCF (even in background threads).
As a help to do this, you may add Service Reference, then copy generated IPersonService (all methods will be decoupled) from Reference.cs. Then you may remove the reference.
However, if your service contract is often changed, you have to repeat Add-Service procedure again, and starting from this, I would say, it's easier just use Add-Service-Reference feature, rather than sharing the contract with your app server.
Only one thing that I would like detect. Often you need in namespaces with more complex support of NET within your WCF service. Therefore you must have real reasons to reference to Silverlight subset within your WCF service (or service library). There are many ways to
use so named traditional ways by Add Service Reference. They are presented in good article enter link description here.

Generate Silverlight service proxies with same namespace

I need to generate service proxies for multiple WCF services within the same namespace, which is not possible when using the Add Service Reference function of Visual Studio.
How can I do this in an automated way? I've considered using SLsvcUtil, but that would require that I make sure that I have my WCF services accessible, and, assuming I'm using the ASP.NET Development Server, I'd need to manually check the URL.
Ideally, I'd have some way of specifying an assembly, a service type, the configuration (web|app.config) and a target namespace, and then my code would be generated. Any Ideas?
Edit
To clarify, I'm trying to solve the same problem that is outlined in this connect issue:
http://connect.microsoft.com/VisualStudio/feedback/details/426791/adding-multiple-service-references-from-same-application-should-not-require-multiple-namespaces
I want a no-hassle, automated way to generate service proxies within a single namespace. It's unacceptable for me to have to specify a unique namespace for each service reference. Using SLsvcUtil is an option, but it requires that I have my service up-and-running so it can read the metadata - which is a problem because I don't always have the latest version of the service running at any given point in time.
The "Add Service Reference" functionality in VS handles this well - it automatically hosts the service just long enough to grab the metadata, and then generates the service contract interfaces and proxies. Once again, it requires that each service be code-gen'd in its own, unique namespace, which I don't want.
All I need is a way to generate the service proxies with a single, shared namespace, without having to go through the hassle of manually hosting and firing up an instance of my services. Ideally, I'd just double click a script file.
What I normally do is to inform a composite namespace. When the "Add Service Reference" dialog pops up, I put in the namespace something like Services.ServiceA or Services.ServiceB. Then all service namespaces share the common root Services.*.
If I'm understanding the question correctly, you're concerned because the way Add Service Reference functions, the ServiceContract interfaces are not exactly the same as the ones you define in your source assembly.
The only real difference is that the ServiceContract interface that Add Service Reference generates for SL has asynchronous operations defined (since SL doesn't support synchronous WCF calls). The rest of it (the XXXClient : ClientBase class) can be completely bypassed if you just use the ChannelFactory<TServiceContractInterface> directly.
I personally ended up sharing the synchronous ServiceContract interface, but creating a service contract with asynchronous operations using a System.Reflection.Emit.TypeBuilder. Then using a custom ChannelFactory, I created a wrapper around the dynamically generated asynchronous ServiceContract interface.
I hope that helps.

Resources