Desktop clients will be pushing data using WCF to a central server.
When the schema changes etc, say 100 computers have the old version of the desktop client while the rest are using the latest build.
What do I have to do on the server end to handle both versions?
Do I create 2 endpoints in WCF or a single smart endpoint that will figure out the version and act accordingly?
note: i will be passing the version info from the client (if required that is)
You have a choice:
Firstly you should be versioning your service contracts anyway, with their namespaces; eg. http://idunno.org/2008/10/numpty would change to http://idunno.org/2008/11/numpty if the service operations have breaking changes.
Ditto with data contracts; however if all you are doing to the data contract is additive then you can mark the new fields as optional;
[DataMember(IsRequired="false")]
And old clients will work. So this should indicate to you that the parameters into a service and parameters out should also be data contracts; it gives you that flexibility.
MSDN has more
Related
Setting: I'm developing an intranet tool set for my department, the main point of which is to centrally manage data quality and accessibility, but also to automate and scale some partial-processes.
Problem: I currently have my business logic in a CLR assembly, which is available on my SQL-Server for other CLR assemblies that run automated ETL directly on the SQL-Server. I am also developing an intranet site, which also needs the code information in that business logic assembly, but referencing the CLR assembly code has been working out sub-optimally, in terms of deployment and code maintenance. Also another department has voiced interest in using the code-base and data for their own intranet site.
Question(s): I've read quite a few Q&A(1,2,3,4,...) on SO to this topic, but I find it a very encompassing, so I'll try to ask questions for a more specific case(i.e. a single BL and Data Access code base)
Is a WCF service the solution I want? All my potential service clients run on the same server, is there maybe another way to reference the same code base both in CLR assembly and website projects? I don't need support for different platforms(ex. Java) - everything is .NET(yay for in-house progr!) - is WCF overkill?
Can code from a WCF service be used like a class library, or do I need to program a new way for accessing classes/methods from the service?
Separation of Development, Test and Productive instances?
Can a WCF service be updated while clients are accessing it, or do I need to schedule maintenance windows? When I update the service, do I need to update the client as well in some way?
Can I dynamically set the service reference, like I currently am dynamically setting the database connection string, depending on if StageConfig = dev, test, or prod?
My CLR assemblies are written for .Net 3.5, but the websites for .NET 4.0, will that pose a problem?
What minimum set of .NET service architecture programming do I need to know to accomplish this? I'll learn more about WCF with time, but I need to evaluate architecting effort and weigh it against getting things done(feature requests). Does the MS tutorial get me the desired skill?
I appreciate answers to only single questions, if you feel you know something, I'll +1 whatever helps me get closer to a complete answer.
OK, so you want to make your code enterprise-wide. There are two fundamental problems to talk about when you want to do this, so I'll structure the answer that way:
You have to understand what WCF is all about.
You have to manage your dependencies correctly.
What WCF is about
WCF is a way of doing RPC/RMI (Remote procedure call/remote method invocation) which means that some client code can call code that is located somewhere else through the network.
A callable WCF service is determined by the ABC triplet:
The service specification is implemented as a .NET interface with a "ServiceContract" attribute. This is the Contract ("C")
The "location" of the service is determined by a pair : Address ("A") and Binding ("B"). The Binding determines the protocol suite to be used for communication between client and server (NetPipe, TCP, HTTP, ...). The Address is a URI following the scheme determined by the Binding ("net.pipe", "net.tcp", "http", ...)
When the client code calls a WCF service at a specific Address, with a specfic Binding, and a specific Contract (which must match what the server at the specific Address and the specific Binding is delivering), WCF generates a proxy object implementing the interface of the contract.
The program delivering the service is any .NET executable. It has to generate one or many WCF Hosts, that will register objects or classes that implement the service contract, and asociate each delivered service to a specific Address and Binding. (possibly many thereof)
The configuration can be through the app .config file, in which you will be specifying ABC triplets and assotiate these triplets with a name that you will use in your application. You can also do it programmatically, which is very easy.
WCF does not address your problem of deploying your application, or the configuration of addresses and binding. It just addresses the problem of letting two executables communicate with each other with strongly-typed objects (through a specific interface). Sharing the service configuration is up to you. You may use a shared .config file on a Windows share, or even set up a LDAP server that will deliver all the data you need to find your service (namely A and B).
Managing your dependencies correctly
In your scenario, there are three actors that want to use your WCF infrastructure:
Your SQLCLR assembly, which will be a client.
The intranet site, which will be another client.
The service host, which will be a server.
The bare minimum number of assemblies will be 4. One for each of the aforementioned actors, and one specifying the contract, which will be used by all three actors. It should contain the following things:
The interface specifying the contract.
All types needed by the interface, which will of course be sent through the network, and therefore must be serializable.
There should be nothing more in it, or else, it will be a maintenance nightmare.
Answer to your questions
I hope that my answer is clear. Let's sum up the answers to your questions.
Is a WCF service the solution I want? All my potential service clients
run on the same server, is there maybe another way to reference the
same code base both in CLR assembly and website projects? I don't need
support for different platforms(ex. Java) - everything is .NET(yay for
in-house progr!) - is WCF overkill?
Everything is overkill. WCF is rather easy to use and scales down very well.
Can code from a WCF service be used like a class library, or do I need
to program a new way for accessing classes/methods from the service?
Setting up a WCF on existing code requires only the implementation of an additional class, and some code creating the Hosts which will serve the aforementioned class.
Calling a WCF service requires the creation of a Channel, which is a .NET (proxy) object implementing the interface.
So basically, your business code remains in the same state.
Separation of Development, Test and Productive instances?
WCF does not take care of that. Different environments, different service addresses. You have to take care of this yourself.
Can a WCF service be updated while clients are accessing it, or do I need to schedule maintenance windows?
It depends on your maintenance policy. Kill the serving process and launch the new version is the basic upgrade mechanism.
When I update the service, do I need to update the client as well in some way?
Provided that you manage your dependencies correctly like I sketched in the previous section, you need to update the clients only if the service specification (the interface) changes.
Can I dynamically set the service reference, like I currently am dynamically setting the database connection string, depending on if StageConfig = dev, test, or prod?
You have to manage that, probably by etting Address and Binding for a service programmatically.
My CLR assemblies are written for .Net 3.5, but the websites for .NET 4.0, will that pose a problem?
Provided that you manage your dependencies correctly like I sketched in the previous section, the only constraint will be the minimum CLR version required by the "contract" assembly.
What minimum set of .NET service architecture programming do I need to know to accomplish this? I'll learn more about WCF with time, but I need to evaluate architecting effort and weigh it against getting things done(feature requests). Does the MS tutorial get me the desired skill?
You'll need the result of these exercises:
Make two executables, a client and a server, that will communicate
through a WCF contract located in a separate DLL. The configuration
should be located in the app .config file.
Make two executables, a client and a server, that will communicate
through a WCF contract
located in a separate DLL. The configuration should be determined programatically.
Try to send a serializable class as a parameter to your service.
Try to send a serializable class as a return value of your service.
After that, you'll need to think about the best/cheapest way to share the Addresses and Bindings of your services.
Hope it helps.
I was just looking to develop .NET WCF API. We may need to frequently update APIs.
How to manage multiple versions of API deployment?
Versioning your services is a huge topic with many considerations and guidelines.
For a start, there are different classes of changes you can make; fully-breaking, semi-breaking, and non-breaking.
Non-breaking changes (no change needed to existing clients) include:
changing the internal implementation of the service while keeping the exposed contract unchanged
changing the contract types in a way which does not break clients, for example, by adding fields to your operation return types (most serializers will raise an event rather than throw an exception when encountering an unexpected field on deserialization)
polymorphically exposing new types (using ServiceKnownType attribute)
changing the instance management settings of the service (per-call to singleton, sessionless to sessionful etc, although sometimes this will require configuration or even code changes)
Semi-breaking changes (usually can be configured on the client) inlcude:
changing the location of a service
changing the transport type a service is exposed across (although changing from a bi-directional to a uni-directional transport - eg http to msmq - can be a fully-breaking change)
changing the availability of the service (through use of service windows etc)
Fully-breaking changes (need new version of the client) include:
changing service operation signatures
changing exposed types in a breaking manner (removing fields, etc)
When you are going to make a semi or fully breaking change, you should evaluate the best way of doing this. Do you force all your clients to upgrade to use the new version, or do you co-host both versions of the service at different endpoints? If you choose the latter then how will you control and manage the propagation of different versionning dependencies which this may introduce?
Taken to an extreme, you could look into dynamic endpoint resolution, whereby the client resolves the suitable endpoint to call at runtime using some kind of resolver service.
There's good reading about this here:
http://msdn.microsoft.com/en-us/library/ms731060.aspx
If I have a web serice and a client consuming tis webservice, and then I change the service location, orI add another parameter, what is the usual way to change the client?
Do you necesarily need to update the client/ Was UDDI helping in this kind of situation?
You should definitely read Service Versioning - it has the information you need.
But the answer to your question is: maybe.
There are two types of changes: breaking and non-breaking. Unfortunately, sometimes it's not obvious what is a breaking or non-breaking change since it could depend on what the client is doing (and you may not have knowledge of how your service is being used).
In terms of changing the service location this is usually a breaking change. However, as you mention, if the client is using UDDI then they should be able to retrieve the new endpoint location and that change would not be a breaking change.
If you add another parameter then that might be a breaking change (or it might not). If the parameter is optional and the client is using lax versioning (e.g. WCF, .asmx) then the change should not be a breaking one. But it might be that the client is expecting a very specific format or they are doing some schema validation etc. and the optional parameter might cause a failure.
It depends on the nature of change you apply in the service definition. If you add something optional that only new clients can consume but the old clients can ommit, you have introduced a backward compatible change so the clients shouldn't be updated unless they decide to use this new feature. Any change that affects the way the existing clients use the service will require a client update as it represents a breaking change.
In the case of WCF, if you use the latest version 4.0, it introduces a new protocol implementation WS-Discovery, which can help clients to find the service url and the right version they can use. Using this approach, you can for instance, deploy a new version in a different url and the client applications can discover it automatically.
Regards
Pablo.
Hey without fully understanding your problem, and from what i can get from your questino it sounds like you need to update your web reference on the client.
If you have updated your references, not changed the location:
So Load up your client solution, then find your References (not dll references) but Web/Service References, and then right-click and select "update web references"
If you have changed the location, you can change the endpoint if you go to properties, but I would just delete the existing one and create a new one using the new location.
Hope it helps.
For more info check out http://msdn.microsoft.com/en-us/library/bb628652.aspx
I have a universal service hosted on IIS7 that accepts a Message and returns Message ( with Action="*"). This service still publishes meta for the clients.
This metadata is explicitly specified using LocationUrl property in ServiceMetadataBehavior.
We have a requirement that the metadata can change during lifetime of the service, so in essence metadata has a lifetime.
I tried adding IWsdlExportExtension to the service endpoint behavior, but the ExportEndpoint method only gets called once (when the service is loaded first time). Is there a way for me to invalidate the loaded metadata so that anytime there is a call for wsdl using HttpGet, the behavior gets called ?
What you are asking for (changing the published service definition at runtime) is not possible - you need to remove the requirement which specifies that the metadata can change over time.
Once you've published a service, the only reason the service specification should change is because the service has been upgraded.
You should look closer at the business requirement which is making this technical requirement necessary, and try to find another way to satisfy it (perhaps post in programmers.stackexchange). Perhaps you can have multiple services available, and switch between the services over time - but this is a bit of a stab in the dark without knowing the business requirement.
No there is no way. Moreover if you needed you are up to your fully custom solution because this is out of scope of web services. Changing metadata means changing the service itself = its internal logic which always result in restarting the hosting process and publishing new metadata.
Is there any metadata versioning support in OData protocol and its WCF Data Services implementation?
Let us suppose that we have OData service that exposes the single Goods collection, and the Goods entity type has three properties: Key (string), Name (string) and AvailableSince(string). The service is already running, and there are some consumers that rely on this metadata schema.
Next, we want to update Goods entity type - for example replace property AvailableSince(string) by something else, or change it type from string to datetime - so we will have two versions of metadata, and consumers thatdepends on the first version of metadata will not be able to send correct requests in terms of 2nd metadata schema.
Is there any way to provide both metadata versions within the single service? If yes, then how consumer can specify metadata version in request, and how it should be processed on WCF side?
Thank to all in advance.
Short answer: NO.
Most metadata changes require either a new service or breaking existing clients.
If the existing set of clients is important, our general recommendation is to create a new service...
i.e. something like:
/v1/myservice.svc
&
/v2/myservice.svc
Alex
OData Program Manager
This recent article describes on what data changes new service version is required, and what changes do not require service update.
http://msdn.microsoft.com/en-us/library/ee473427.aspx