Generate Silverlight service proxies with same namespace - silverlight

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.

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.

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.

How to implement DI using DbContext in Windows Form

I have a class running in a winforms app which uses EF Code First. The DbContext is created via DI through the class constructor. All works well.
The problem is the data being referenced is also being modified via a web site, using the same DI pattern with EF Code First, and the data changes are not being reflected in the context instance in the winforms app.
I can solve this by recreating the DbContext object in winforms every time I access it, but seems to be more of a service location pattern to me?
Is there a true DI technique to achieve this?
Or should I remove the context from the DI and use service location?
Were you not happy with the answer to your other question (http://stackoverflow.com/questions/7657643/how-to-force-ef-code-first-to-query-the-database) which suggested using Detach, AsNoTracking or Overwrite Changes?
1) Maybe you could pass an interface that has the ability to create a DbContext, instead of the context itself.
using(var context = _contextFactory.Create()) {
var entity = from table in context.Blah...;
}
The Create method could either create the concrete class itself (defeating the DI pattern a bit), or use service location to have one created for it. Not that nice, but it's better than embedding service location calls everywhere and still means you're controlling the lifecycle yourself.
2) Change the WinForm to read from a webservice run by the website, effectively similar to disabling caching.
3) Deep in the heart of MVC (well not really that deep) it is referencing the DI container directly and using it as a service locator to pass as arguments for newly created objects. Technically you could do something similar in WinForms, but it would need you to split your application up into little chunks (controllers) that don't have a very long lifetime. Maybe it's worth looking at some MVC/MVP frameworks for WinForms, although I found myself cringing at most I saw after a quick google.
The problem is the data being referenced is also being modified via a web site, using the same DI pattern with EF Code First, and the data changes are not being reflected in the context instance in the winforms app.
This is a problem with your expectations.
If your web service and window forms app are in separate processes, they won't share in-memory data.
If you want to sync their in-memory data, simply re-query in one context after committing to the database in the other. This is the same as trying to share data between different SQL connections.
I can solve this by recreating the DbContext object in winforms every time I access it, but seems to be more of a service location pattern to me?
If you want to recreate the DbContext repeatedly, you could use an abstract factory to allow manual re-creation of the object, yet allow you to inject the specific implementation into the factory.
This is not (necessarily) the Service Locator pattern, and you would have to ensure that you manually dispose your DbContext instances. I'd give you some example code, but different DI containers have totally different ways of accomplishing a factory pattern.
Or you could simply make sure that you commit your data on the web service side, and re-query the data on the WinForms app side.

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.

Reusing service proxies

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.

Resources