I'm attempting to consume a SOAP service in a Silverlight 5 application and I'm completely lost. This is my first Silverlight app and only my second time using web services in a .NET application.
In a separate .NET application, the only way I was able to get it to work was by adding the WSDL as a Web Reference; the application would not build when I added it as a Service Reference. In talking to the WSDL provider, I discovered that the WSDL was compiled using the .NET 2.0 framework...hence the need to add it as a Web Reference.
From the research I've done thus far, I see that Silverlight doesn't support adding a Web Reference. So I tried adding it to the hosting ASP.NET application as a Web Reference then started the server.
Back in my Silverlight app, I selected the option to add a Service Reference and pointed to the WSDL file now at http://localhost:55265/Web%20References/THINKWebService/SLWebSvc_734_Upgrade.wsdl. Visual Studio seemed to pick it up just fine and generate the proxies.
Here's where I start to get stuck. If my research is correct, a WCF reference was created and should be used in that manner. I've never used WCF so I did some reading on how to send/receive requests and this is the best code I've come up with, based on examples in the MSDN library (I inserted it into a button click event so I would know exactly when the code was executing):
private void Button1Click(object sender, RoutedEventArgs e)
{
var client = new ThinkSoapClient();
var userLoginData = new user_login_data {login = "foo", password = "bar"};
var customerIdentifier = new customer_identifier {customer_id = 6677070};
// the debugger halts on this next line and
// references the "dsn"...it's the 4th argument
client.CustomerLoginInfoSelectAsync(userLoginData, customerIdentifier, "", "myDSN");
// I'm not sure if this next line is even needed
client.CustomerLoginInfoSelectCompleted += CustomerLoginInfoSelectCallback;
MessageBox.Show(string.Format("CustomerLoginInfoSelectAsync({0},{1})", userLoginData, customerIdentifier));
}
// here's the callback method
static void CustomerLoginInfoSelectCallback(object sender, CustomerLoginInfoSelectCompletedEventArgs e)
{
MessageBox.Show(string.Format("CustomerLoginInfoSelect Result: {0}", e.Result));
}
As I mentioned in the code above, the debugger halts when executing the client.CustomerLoginInfoSelectAsync method. Here's the error message: XmlSerializer attribute System.Xml.Serialization.XmlAttributeAttribute is not valid in dsn. Only XmlElement, XmlArray, XmlArrayItem and XmlAnyElement attributes are supported when IsWrapped is true.
From the research I've done, I think this error is being caused because the the SOAP action element contains an attribute dsn (not sure, though, if I would be getting this error if the sub-elements also had attributes).
I did a find/replace for IsWrapped=true to IsWrapped=false in Reference.cs but I got the same error but the last word was false instead of true.
I'm not sure if I'm making any sense as to what I'm after, so here's what the generated XML should look like in case it helps:
...
<customer_login_info_select_request dsn="myDSN">
<user_login_data>
<login>foo</login>
<password>bar</password>
</user_login_data>
<customer_identifier>
<customer_id>6677070</customer_id>
</customer_identifier>
<login/> <!--corresponds to the empty string in the call to CustomerLoginInfoSelectAsync-->
</customer_login_info_select_request>
...
So at this point, I'm completely lost. Any insights would be greatly appreciated. If there's any other info I can provide, please let me know.
While possible the normal solution would be to assume it is "just another data source" and use the Web reference on your Server side instead to provide data (and to provide insulation against future changes).
Silverlight App <=> Silverlight Web Services <= External/Legacy Web Service
Keep your Silverlight app slim and let the server do any heavy lifting for you.
Related
I have created WCF service in .net.
It is called by Java client, how do I read parameters when service is being called?
Here is my code:
public string getMethod(string id, string name)
{
string str = name;
return str;
}
Here is my WPF application code, I have added web reference:
WebReference.Service1Soap client = new WebReference.Service1Soap();
string str = client.getMethod(id, name);
How do I read values of "id" and "name" called from Java client?
I am stuck here, please help me please!!
Any help would be greatly appreciated.
Thanks!!
The simplest way:
Run a local instance of the service in debug mode, or attach the visual studio debugger to WCF service host process.
Put a breakpoint in the getMethod() service operation code
Call the service with the java client.
Check the values using a watch or just mouseover.
EDIT.. from comments...
but I have set debug point, still it is not happening
That means that your java client call is not being made successfully. If your java client cannot call the service then you need to sort that out first. Please post a new question to address this, or there are plenty of stuff on google: https://www.google.co.uk/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=problem+calling+wcf+from+java
I need those parameter values in WPF application and I have to read
it. How to do it?
You can't send a message to a service and then have that data relayed to another client (WPF) unless you use callbacks via a duplex binding like wsDualHttpBinding, which is not a nice solution in my opinion. More reading here: http://www.codeproject.com/Articles/491844/A-Beginners-Guide-to-Duplex-WCF
If your java client needs to call into a WPF then you'll need to use ServiceHost inside your WPF application and host a WCF service from there. Look here for an example: http://blogs.msdn.com/b/brunoterkaly/archive/2013/11/01/wcf-service-hosting-how-to-host-a-wcf-service-from-inside-a-windows-presentation-foundation-application.aspx
EDIT 2
From Java, service client has been made successfully, and it is
getting the response. But how do I read parameters, and is there any
way or code, that "we come to know that .net service is being called".
Then the only thing you can do is either host the WCF service inside your WPF application, or use a duplex WCF binding on the service, and have the WPF application subscribe by registering a callback delegate. This way the service can call back to the client when something happens (a call is made).
Alternatively you could use a shared database which is updated with the call values when the java client makes the call. Your WPF app can then poll or use a SqlDependency to know when the data has changed.
Need an idea on best practise in finding a solution.
We are looking at developing Silverlight controls for CRM forms that will need to reference a common configuration file for data. It is a file that will need to be maintained periodically every once in a while. We don't want to be hardcoding values into the Silverlight control.
My question is... Where/What/How do we provide a config file for a Silverlight control?
I tried uploading a JS web resource that simply was a JSON array full of settings that I tried to access from the Silverlight control. All I got were permission errors when I used both the admin account and my domain account to do a Http get of the file and parse it. Can someone confirm that this could work if I manage to work through these annoying permission errors?
My next thought was having a CRM entity full of settings that the Silverlight control could make ODATA calls to in order to get its config data. I'm not 100% sold on the idea though.
Perhaps there is another way people have been using - if so - I'd love to see what you are doing. This could really prevent us from coming to a Silverlight enriched solution that we are after.
Thanks in advance
We go about this in two ways.
We have a configuration entity for settings that might be changed on a customer site by their administrator.
For other configuration data that is unlikely to be changed, we install an XML web resource. This method means we can store a lot of data without having to create and manage complex entities (or relationships if required). If set as an unmanaged/customizable web resource, then the text editor can be used to make changes, although remember that these changes must not break the XML schema/syntax.
This xml web resource can be retrieved in Silverlight using WebClient.DownloadStringAsync() as shown below.
private void GetXmlConfiguration(string resourceName)
{
var webClient = new WebClient();
webClient.DownloadStringCompleted += OnGetConfigurationXmlCompleted;
webClient.DownloadStringAsync(new Uri("../Data/" + resourceName, UriKind.Relative));
}
private void OnGetConfigurationXmlCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null && !string.IsNullOrEmpty(e.Result))
{
//use xml string here
}
}
We use the configuration entity method quite often and I think it works well.
You should be able to use your initial method as well... I know in a few places we've done some XML configuration in a web resource that we've retrieved in Silverlight, parsed, and done something with.
I'm trying to access a run-of-the-mill REST API through a silverlight application, but can't seem to get basic authentication to work (using silverlight 4.0).
I'm using a .NET WebClient, and setting the webclient.Credentials with a valid username/password (for the API).
I'm running into two main errors:
System.NotSupportedException: BrowserHttpWebRequest does not support custom credentials.
(this only occurs when I set the webclient.UseDefaulCredentials to false)
and
System.NotImplementedException: This property is not implemented by this class.
at System.Net.WebRequest.set_Credentials(ICredentials value)
(occurs when webclient.UseDefaultCredentials isn't set at all)
what am I missing here? Is basic auth still not supported in Silverlight 4.0?
There is an article about it here http://mark.mymonster.nl/2009/12/02/silverlight-4-credentials-weve-got-it/ and it seems the magic line is:
WebRequest.RegisterPrefix("http://", System.Net.Browser.WebRequestCreator.ClientHttp);
In my case it seems to send the credentials, but I still end up with a 401 error but I just grabbed one of my web servers to try and it may not be configured correctly, but this seems like it should work.
I would also suggest trying the open source library Hammock for REST It provides a very useful wrapper around a lot of modern web calls like REST and oAuth.
I have a custom proxy class for a single WCF web-service (takes a string in, sends a string back). The asynchronous web service call works great from my Windows Form app. However, when I call it from a test Silverlight app I get an error: Hresult 0x80000012. This error is for Extension Attributes on files I believe... Go figure.
Using Fiddler I can confirm that no traffic is making it to IIS which is hosting the service, so it isn't the usual cross-domain restriction issue. I've tried using both "localhost" (which works in the Windows Forms app) and a name defined in my hosts file just in case "localhost" was causing the problem.
I've tested it by making the async call from the UI thread and also from a thread-pool queue item with the same results.
The proxy code is basically just simplified down from what the MS proxy generator creates, setting up bindings and settings programatically instead of via config files, and I use basically the same source to compile normal .Net and Silverlight versions of the libraries involved. (Now, the MS proxy code it is based on is from a WCF web service, not from the RIA template code, so maybe there are differences there...)
Four days of fruitless search on this one. Any help or suggestions would be wildly appreciated!
Figured it out. I was using (stupidly) a backslash in part of the URL that I used to set up the service call. Most of the interior parts of the MS code handled that ok and transposed them to forward slashes -- on Windows Forms everything worked seamlessly in fact. However, the Silverlight libraries couldn't handle it and threw the very helpful "HResult 0x80000012" error.
Changing my backslashes to slashes seems to have fixed the problem!
So one of the best parts about the new Silverlight 4 beta is that they finally implemented the big missing feature of the networking stack - Network Credentials!
In the below I have a working request setup, but for some reason I get a "security error" when the request comes back - is this because twitter.com rejected my api call or something that I'm missing in code?
It might be good to point out that when I watch this code execute via fiddler it shows that the xml file for cross domain is pulled down successfully, but that is the last request shown by fiddler ...
public void RequestTimelineFromTwitterAPI()
{
WebRequest.RegisterPrefix("https://", System.Net.Browser.WebRequestCreator.ClientHttp);
WebClient myService = new WebClient();
myService.AllowReadStreamBuffering = true;
myService.UseDefaultCredentials = false;
myService.Credentials = new NetworkCredential("username", "password");
myService.UseDefaultCredentials = false;
myService.OpenReadCompleted += new OpenReadCompletedEventHandler(TimelineRequestCompleted);
myService.OpenReadAsync(new Uri("https://twitter.com/statuses/friends_timeline.xml"));
}
public void TimelineRequestCompleted(object sender, System.Net.OpenReadCompletedEventArgs e)
{
//anytime I query for e.Result I get a security error
}
I found 2 issues that caused this request to throw the security exception
1) - In this video by Tim Heuer it turns out my VS2010 w/ Silverlight 4 toolkit installation didn't match the final build so I'm missing the option that shows up in the "out of browser settings" dialog that provides the checkbox for "Require elevated trust when running outside the browser".
In the video listed above Tim checks this so the Silverlight app can talk to the twitter API
But because my application didn't have this option I had to manually edit the xml file so it looked like the below. You can find this xml under properties in the project folder or inside visual studio directly.
<OutOfBrowserSettings ShortName="TrustedNetworkApp Application" EnableGPUAcceleration="False" ShowInstallMenuItem="True">
<OutOfBrowserSettings.Blurb>TrustedNetworkApp Application on your desktop; at home, at work or on the go.</OutOfBrowserSettings.Blurb>
<OutOfBrowserSettings.WindowSettings>
<WindowSettings Title="TrustedNetworkApp Application" Height="480" Width="640" />
</OutOfBrowserSettings.WindowSettings>
<OutOfBrowserSettings.SecuritySettings>
<SecuritySettings ElevatedPermissions="Required" />
</OutOfBrowserSettings.SecuritySettings>
<OutOfBrowserSettings.Icons />
</OutOfBrowserSettings>
Notice the **security settings ElevatedPermissions="Required"
After you save this it's equivalent to checking this as Tim did in the video.
2) - as I was watching that video by Tim I noticed that you have to debug this outside of the browser to get it working. So install the app and run it outside the browser. This app now works.
I'll write a short blog post to summarize my experience with the networking stack under the beta and link to it for anyone interested.
Update
I finally wrote a blog post about my experience building an out of browser twitter client using Silverlight 4 if anyone is interested.