How can I use web service from Silverlight app? - c#

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.

Related

How to create a WCF Service that has an always running component?

Half a day of googling suggests, that it's a bit niche topic, and my question is quite specific. I'm using: VS2013, .NET 4.5, IIS 8.5
I have a ASP.NET website that needs to query a data source. Opening the data source is costly, but I can keep it open indefinitely.
My idea was: create a Command Line application or a Windows Service that will open the data source and then expose the querable objects to the ASP.NET website.
I don't like the idea of having this unmanaged (CommandLine) or managed apart from website (WinService) application that I have to deploy completely separately.
I've read that it is possible to create an always running WCF service hosted in IIS. I would like it to keep a list of object instances that would be returned as a result of a WCF call. Is that at all possible? If yes, how?
I've tried setting the WCF service AppPool to AlwaysRunning, enabling autostart on service application and I can access the service, but a simple test shows, that the service object is created every time anew:
public class MyService : IMyService{
{
private int _counter;
public int Test(){ return _counter++; }
}
My website creates a MyServiceClient from service reference and calls test - it returns 0 every time.
I've also found, that if I create any class in my WCF service application, I cannot access it from inside MyService methods. I can access though classes referenced from other projects. Why is that?
I think you're looking for a singleton service. By default the ServiceBehaviorAttribute.InstanceContextMode is set to PerSession. Instead set it to Single. Every client will then connect to the same instance of the service.
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class MyService : IMyService{
{
private int _counter;
public int Test(){ return _counter++; }
}
Personally, I prefer the singleton approach over static as discussed in here

Can I generate a service reference automatically for a REST WCF service?

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.

Different proxy class when adding WCF service as web reference and service reference

There is a web service written with WCF that I'm adding as reference. Proxy class generator works flawlessly when I add it to as service reference but it generates a slightly different class when I add it as web reference using service.svc?WSDL. Here's are the differences:
//service reference
public partial class TestServicesClient : ... // correct class name
{
public int TestMethod(string serviceID, int dealID) // correct method signature
{ ... }
}
//web reference
public partial class TestServices: ... //different class name
{
public void TestMethod(string serviceID, int dealID, bool dealIDSpecified, out int TestMethodResult, out bool TestMethodResultSpecified) // different method signature
{ ... }
}
I tried using wsdl.exe for generating web reference class, didn't help.
What is wrong here?
Nothing is wrong here. Service Reference is the "new" way to use a WCF Service, it removes overhead such as the "Specified"-parameter, "Result"-parameter and "Result Specificed"-parameter.
You can still use other properties/methods to check if a parameter is specified or if there is a result. But before WCF, it changed the method signature.
You use a Service Reference and a Web Reference a bit different and that's just the way it is.
Here's some additional reading:
Difference between web reference and service reference?
The Difference Between “Add Web Reference” and “Add Service Reference”
And to quote from a reply to "What is the difference between WCF service and web service"
WCF "web services" are part of a much
broader spectrum of remote
communication enabled through WCF. You
will get a much higher degree of
flexibility and portability doing
things in WCF than through traditional
ASMX because WCF is designed, from the
ground up, to summarize all of the
different distributed programming
infrastructures offered by MS. An
endpoint in WCF can be communicated
with just as easily over SOAP/XML as
it can over TCP/binary and to change
this medium is simply a configuration
file mod. In theory this reduces the
amount of new code needed when porting
or changing business needs, targets,
etc.
ASMX is older than WCF, and anything
ASMX can do so can WCF (and more).
Basically you can see WCF as trying to
logically group together all the
different ways of getting two apps to
communicate in the world of MS; ASMX
was just one of these many ways and so
is now grouped under the WCF umbrella
of capabilities.
There are few difference between the service reference and web reference. WCF serializes using datacontract serializer. So add XmlSerializeFormat attribute to the serivcecontract and then add web reference. Your extra parameters will be removed. But then its like using wcf like web service only. One more retriction is that you need to use web bindings only like http.

c# client calling java axis2 web service, object "resets"

I am very new to web service stuff so please be kind.
I have written a simple POJO class, and deployed it on an axis2 server:
public class Database {
private Project project;
public void login(){
project = new Project();
project.setDescription("Hello there");
project.setName("To me");
}
public Project getProject(){
return project;
}
}
I call the service from a c# client:
localhost.Database db = new WindowsFormsApplication1.localhost.Database();
db.login();
localhost.getProjectResponse pr = new WindowsFormsApplication1.localhost.getProjectResponse();
pr = db.getProject();
When I debug the response is null.
At the java end, when I call getProject, the project object is null.
What's happening?
How do I preserve the state of project between service calls?
For most toolkits, web services are stateless by default. I think axis is no different.
If you want to maintain state between calls then you will need to enable sessions. An example on how to maintain sessions in axis can be found at:
http://kickjava.com/src/test/session/TestSimpleSession.java.htm
On the .NET side you will need to assign a CookieContainer to your request to store the session identifier. See HOW TO: Use CookieContainer to Maintain a State in Web Services for more information.
I think your code would look something like this:
localhost.Database db = new WindowsFormsApplication1.localhost.Database();
// Assign the CookieContainer to the proxy class.
db.CookieContainer = new System.Net.CookieContainer();
db.login();
localhost.getProjectResponse pr = new WindowsFormsApplication1.localhost.getProjectResponse();
pr.CookieContainer = db.CookieContainer;
pr = db.getProject();
I think that should let you do what you want -- but I wouldn't recommend it.
Designing service interfaces is a bit different than designing object oriented interfaces. Service interfaces typically eschew the use of state and instead require the consumer to provide all of the relevant information in the request.
From Service-Oriented Architecture:
Services should be independent,
self-contained requests, which do not
require information or state from one
request to another when implemented.
I would definitely recommend reading that article and perhaps revisiting your design.
I'm not sure why #shivaspk left a comment instead of writing an answer, it is quite correct: web service calls (not just axis calls) are meant to be stateless, so although the project object gets created by
db.login();
when you call
db.getProject();
It is being called on a different instance of your Database class that was created by Axis to service the second call.
There is no really good answer to your question, except for you to rethink what you are trying to do. If you need some kind of authentication (via login), then that authentication needs to be part of every web service call.

Does adding a method to a WCF ServiceContract break existing clients?

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?

Categories