We have an existing ServiceContract
[ServiceContract(Namespace = "http://somesite.com/ConversationService")]
public interface IConversationService
{
[OperationContract(IsOneWay = true)]
void ProcessMessage(Message message);
[OperationContract(IsOneWay = true)]
void ProcessMessageResult(MessageResult result);
}
and we need to add a method to it
[ServiceContract(Namespace = "http://somesite.com/ConversationService")]
public interface IConversationService
{
[OperationContract(IsOneWay = true)]
void ProcessMessage(Message message);
[OperationContract(IsOneWay = true)]
void ProcessMessageResult(MessageResult result);
[OperationContract(IsOneWay = true)]
void ProcessBlastMessage(BlastMessage blastMessage);
}
Will this break any existing wcf clients that are using this service? Or will we have to update all existing wcf clients?
EDIT: This service is using both netTcpBinding and netMsmqBinding
I think your existing clients will continue to work. After all this is very similar to SOAP and web services in that the client will connect to the given URL and request a specific service. If you take methods away you will risk breakage (only if the method is used I believe) but adding should be pain free.
I've only dabbled in WCF but have used the ASP.NET web services in this way to great success.
I just tested this with a WCF client Windows app (UWP) and it continued to work after updating the WCF service application. So no: as previously answered, your clients will not break when you add a method.
I thought it was worth mentioning, however, how easy it is to update your service clients with Visual Studio 2015:
Make sure your WFC service is running.
Simply go to the Solution Explorer,
Expand Service References
Right-click on your service reference
Click Update Service Reference
If you get an error message, repeat the last step. I had to try a few times for some reason.
No, I wouldn't expect that - adding new functionality / new service methods that does NOT alter any of the existing methods / function calls will not affect "old" clients. Of course, they won't know about the new methods until their proxies have been recreated from metadata, or adapted manually.
But existing calls should be unaffected, as long as their signature (the data they exchange) stays the same.
Marc
I take the more extreme view on this. Why ever change anything? Instead, why not create a new contract, inheriting from the old, and adding the new operation? The new contract can be exposed in a separate endpoint in the same service.
It may be paranoia uninformed by formal proof, but it seems to me that, if it's possible to construct a client that can tell the difference, then it's possible that some client will "break" when you make the change. Consider that, when you change the service contract you're not just changing service code - you're changing the proxy code in any client that happens to update his service reference. Some, more conservative customers, might consider that a reason to re-test their client code - after all, they may well have rules that say they have to retest their code whenever any change is made to it.
The existing client will be referring to the original endpoint, so will not be affected by adding a new endpoint - no code would change if an "Update Service Reference" was performed.
Besides, why even think about it, if you don't have to?
In general, adding to a message in SOA solutions does not break the contract. I believe that as long as you're not using a binary protocol (net.tcp), you'll maintain backward compatibility.
I'm not sure about whether or not it will break your clients using binary bindings, though?
Related
I have inherited a couple of large legacy C# code bases that make extensive use of SOAP/WCF to talk to each other and some third party software. I am somewhat new to WCF. I've run across a situation I can't quite explain. The URL pattern being used for the contracts in one of the service classes is definitely invalid (The top level domain it specifies does not exist).
[OperationContract(Name = "TestMethod", Action = "http://hard.coded.URL.that.is.definitely.invalid/TestMethod")]
[WebMethod(MessageName = "TestMethod")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
string TestMethod(string x);
Is it possible that this could work, or is the explanation simply that it has never been used?
I don't know for sure that this service has actually been used for anything. The commit messages on all revisions of this file (and most other files) are useless. This is in one of the modules that talks to third party software that I don't currently have the ability to deploy in a test environment. There are a lot of other WCF endpoints in the project that use valid URL patterns.
Maybe they were doing something really weird with the DNS configuration(?) This service most likely would be run over a local network.
The ONLY argument I can see for SOAP WCF over REST (json) wcf is the fact that once my service is created I can add a a reference in visual studio and I get a load of strongly typed classes ready for me and a client class that I can call all my webmethod through. It even sets up the web.config as far as I remember.
However when I expose a REST (json) service I still get a WSDL. So Im wondering is there still a way to build my references automatically?
Not using WCF tools. Unlike with SOAP (which has an established protocol for describing services - WSDL), REST doesn't. WADL is one such protocol, but it isn't too widespread and WCF does not support it. You still get a WSDL, because WCF will describe everything it can from the service. However, the WSDL won't have a <wsdl:port> element, which would describe the REST endpoint, which is why you get the WSDL, but cannot generate a reference to it.
The post at http://blogs.msdn.com/b/carlosfigueira/archive/2012/03/26/mixing-add-service-reference-and-wcf-web-http-a-k-a-rest-endpoint-does-not-work.aspx has a lot more info on this issue.
Very old question, newer answer.
today using openapi (swagger) I can achieve this by using swagger inspector doing samples i can document my rest services as well as create a spec yml/json file allowing for validations and acceptance criteria as well as automated clients for java,python,c#,ruby,javascript and others I'm sure
I would like top elaborate:
Although it is true you cannot get a WSDL add service reference with a JSON REST WCF service, what I do is create two met data hooks:
is the operations returning JSON
is a single XML op returning a class wrapper which includes all the service classes I allow, I call it Discover:
i.e.
public class Discover
{
public Manager Manager {get;}
public Employee Emp {get;}
....
}
[OperationContract]
public Discover DiscoverDTOs()
You can, indirectly. While the client generated by Visual Studio won't work, that client implements an interface, also generated, that you can use like this:
WebChannelFactory<IService> factory = new WebChannelFactory<IService>(new Uri(endpointAddress));
IService proxy = factory.CreateChannel();
int result = proxy.Operation(1, 2, 3);
WebChannelFactory has another overload which accepts a WebHttpBinding, you can configure based on the service configuration, or you can make this configuration manually in your app.config file.
I am trying to get data form a web service inside a silverlight app. Unfortunately the silverlight app (Bing map app) just hangs when trying to connect.
I use the same code in a console app and it works just fine.
Is there anything special I need to do in silverlight to get it to work? I don't get any exceptions - it just hangs.
I based my service and client code off of this example
http://www.switchonthecode.com/tutorials/wcf-tutorial-basic-interprocess-communication
Problems and Questions:
1. Why can't I set breakpoints in my sliverlight code?
2. How can I successfully call WCF service from a silverlight app? (links to SIMPLE working examples would be great - all the ones I seem to find seem to be quite advanced (RIA, Duplex, etc) Many of these also show xml and other non C# "code" - frankly I don't know what those do and how they relate to the projects, code and services.
(Clearly I am quite ignorant about WCF and silverlight)
As per request for code:
[ServiceContract]
public interface ILGSMapServer
{
[OperationContract]
List<double> GetLatitudes();
}
public class TreeWorkClient
{
ChannelFactory<ILGSMapServer> httpServer;
public ILGSMapServer httpProxy;
public TreeWorkClient()
{
httpServer = new ChannelFactory<ILGSMapServer>(new BasicHttpBinding(), new EndpointAddress("http://localhost:8000/GetLatitudes"));
httpProxy = httpServer.CreateChannel();
}
public List<TreeWorkItem> GetLocations()
{
List<double> lats = httpProxy.GetLatitudes();
//... do stuff in code
return ret;
}
}
I agree with John Saunders - it would be easier to answer this if you published the client code.
However as a guess, a common problem with calling services from Silverlight applications is the restriction Silverlight puts on cross domain calls.
In summary, if your service is at a different domain from the site-of-origin of the Silverlight application, you need to create a client access policy file at the service location.
See this for details:
http://msdn.microsoft.com/en-us/library/cc197955(v=vs.95).aspx
Given your example code you should be seeing the
System.InvalidOperationException: The contract 'ILGSMapServer'
contains synchronous operations, which are not supported in
Silverlight. Split the operations into "Begin" and "End" parts and set
the AsyncPattern property on the OperationContractAttribute to 'true'.
Note that you do not have to make the same change on the server.
You'd need to change your service contract to the following
[ServiceContract]
public interface ILGSMapServer {
[OperationContract( AsyncPattern = true )]
IAsyncResult BeginGetLatitudes( AsyncCallback callback, object context );
List<double> EndGetLatitudes( IAsyncResult result );
}
This also means you'll need to do something completely different in your GetLocations() function as this function will return before the results from the Web have been returned.
Try taking a look at the examples here.
Other options involve using the "Add Service Reference" rather than manually defining it in code.
I believe you need to have this attribute on WCF service for SL to consume it:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
As for debugging - you can debug Silverlight, try using IE for that, its most natural browser for SL debugging (sadly).
Once you start debugging it will be more clear whats wrong when you catch cross domain exception or some other.
I have a versioning issue with a WCF service contract in which one of the many endpoints which are called for the operation is missing one method from the contract.
My question is, how can I make sure the command is available on the client before attempting to call it?
I tried:
foreach (var od in proxy.Endpoint.Contract.Operations)
{
if (od.Name == "MyMethodName")
{
hasMethod = true;
break;
}
}
Unfortunately, this is using the contract from the calling app and does not actually describe the implementations on the endpoint itself. As a result, it returns true even though the endpoint has failed to implement the command.
You'll never actually know until you try it. What you have is a proxy of the implemented contract, but what is on the server side could have changed since you created/generated it.
Assuming it's an http/httpws implementation I suppose you could call and check the service reference and download the wsdl file. That will tell you what methods etc are supported. The problem you're going to have is that even though the name of the method maybe the same, you'll also have to check the return type and parameters to really be sure that it's the same method and that you can call it with the proxy you currently have.
Here is a link on versioning in WCF:
http://msdn.microsoft.com/en-us/library/ms731060.aspx
Here is a link on versioning best practices for WCF:
Best practices for versioning your services with WCF?
I have two websites, both using .Net framework 3.5. One website is hosting a soap web service and the other is referencing this service.
I'm having some unexpected happenings with my web method signatures. I have a simple method in my web service with a signature such as:
[WebMethod]
public string[] HelloWorld()
{
return new[] { "Hello World" };
}
But when I reference this web service using the 'Add Service Reference' feature in VS2008, with configuration set to "Always generate message contracts" (although when i check the 'reuse types in referenced assemblies', i seem to have the same issue), the signature seems to be changed by the auto generated proxy objects to the following:
HelloWorldResponse HelloWorld(HelloWorldRequest request)
I've tried to look this up on the net, but having trouble finding something that will simply explain to me why this is happening, and whether I can/should try to work around it?
I also have this question:
How does one determine whether they should choose the service reference configuration option to "reuse types in referenced assemblies" and "always generated message contracts"?
The message-contracts option might have this effect; the purpose here being to allow fine-grained control over the underlying request. Ultimately, what you are sending (behind the scenes) is a request payload.
The reuse-types option is more typically used with objects (not things like string[]) - and means that if you have a 100% matching Customer (say) class locally, it can re-use that for the web-service rather than generating a proxy type.
Additionally, note that you aren't actually consuming a WCF service ([WebMethod] is the older web-service style). As such you may have better results with a "Web Reference"; when adding the service, hit "Advanced", then "Add Web Reference...". This uses the older UI and wsdl.exe to generate code intended for [WebMethod] (asmx), rather than WCF (svc).
Of course, rather than hosting a [WebMethod], you could (since the server is also 3.5) host a WCF service; this may make things easier.
A final point of WCF; if you really want the same contract at client and server, you can use either assembly or class sharing to use the very same types at both end. This is not supported for [WebMethod], though.