Tuesday, October 20, 2009

Silverlight Web Services deployment

One of the usual issues a newbie developer has with silverlight is with the webservice deployment. Everything would work fine when the services are developed along with the silverlight application but it won't work when it gets deployed to the target server.


The usual reason for this is the url references of the application won't be updated when the deployment is done. In order to make sure that this issue doesn't repeat every time, we can invoke the web services in the silverlight app in such a way that it never needs updating the urls.


A sample snippet of how to do this is as below. We use the Application.Current.Host.Source.AbsoluteUri variable which holds the value of the abolute path of the uri being accessed.



int index = Application.Current.Host.Source.AbsoluteUri.IndexOf(Application.Current.Host.Source.AbsolutePath);
String myCurrentHostUrl = Application.Current.Host.Source.AbsoluteUri.Remove(index + 1);

myCurrentHostUrl contains the value of the website where I am hosting this. Now I can invoke my webservice with this url.



BasicHttpBinding basicHttp = new BasicHttpBinding();
EndpointAddress endPoint = new EndpointAddress(myCurrentHostUrl + @"WebServices/MyWebService.svc");
MyWebServiceClient client = new MyWebServiceClient(basicHttp, endPoint);

We can simply put this code in a reusable function and keep using this as and when needed. Hope this helps.

Thursday, April 23, 2009

Checklist for Hosting a Silverlight Application

I used to have some small if not huge issues because of some issues not known before. So thought a compilation of some notes will be helpful to others as well. Feel free to send me a few more to add to these points.

Creating the application
:
The Silverlight Application can be created normally along with class libraries supporting silverlight. The final compiled control is a .xap file. This is a no brainer, I have just used this as a filler to start the blog post. :)

Web Service Reference Urls:
Many people miss this part. We need to update the service reference urls to the new server where we are going to host the application. Instead if we want this to dynamically change, you can use the following code snippet to invoke the Web Services. This is the best idea instead of manually changing it either by update reference or change in servicereferences.clientconfig.


BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
EndpointAddress endPoint = new EndpointAddress(GetApplicationUrl("/MyService.svc"));
MyWebServiceClient client = new MyWebServiceClient(basicHttpBinding, endPoint);
client.CallYourFunction();

In the above code, you need to write the Get Application Url function.

Security & HttpContext issue:
I had a problem with the Asp .net Application Security. I can login and logout using the Membership provider using Brad Adam's article . But I wanted to verify the security at different places in my web services.
And the problem is WCF does not carry the HttpContext with it and different calls to WCF web services will result in HttpContext returning null references to the logged on member.
The solution is to use host headers and send it back and forth. For example we can send the username and password as headers and then call the Membership.ValidateUser(username, password). A sample snippet is as below.

Snippet on the Silverlight Side:
You can download the code for the client side use from Microsoft site at Silverlight Message Inspector.

Snippet on the Web Service Side:
String userName = OperationContext.Current.IncomingMessageHeaders.GetHeader("UserName", "");
String password = OperationContext.Current.IncomingMessageHeaders.GetHeader("Password", "");

bool isAuthenticated = Membership.ValidateUser(userName, password);


WCF Service Issues:
The first thing you can try when there is an issue with web service is to load the webservice.svc file directly in Internet Explorer. If you are hosting on a shared hoster who already supports silverlight and webservice, then you will usually need to create your own service host factory.
Otherwise the error will be displayed like "WCF does not support multiple IIS bindings for the same protocol (here it is HTTP) for the same web site". A short blog post regarding this can be found at http://www.darkside.co.za/archive/2008/02/21/custom-servicehostfactory-for-wcf-and-iis.aspx

IIS Settings:
If you are hosting on your personal machine or a dedicated server, then you will have to set the "Advanced Multiple WebSite Configuration".
We need to add our website name into the IIS Console --> Properties --> Web Site Tab --> click "Advanced" button. This will enable our web services to return the host url as our website instead of returning the machine name, which won't be visible to the outside public.

Also I have seen occasional problems because the .svc is not registered. In order to do this use the command

C:\WINDOWS\WinFX\v3.0\Windows Communication Foundation\servicemodelreg.exe -i


Support for Firefox and IE:
There are issues with hosting a silverlight application in an aspx page and using it in firefox. So what I do is to detect the requesting browser and if it is FireFox then I redirect the request to the silverlighthost.html file. A sample snippet is below.


window.onload = function()
{
if (navigator.appName == 'FireFox')
{
window.location = 'silverlighthost.html';
}
else
{
document.getElementById('Xaml1').focus();
}
}

Monday, April 13, 2009

Dynamically creating a DIV control in Silverlight

By now everyone would have gotten a clear idea that HtmlPage, HtmlDocument along with HtmlElement is the way to display a div item in silverlight pages. Now here are few samples to create some controls dynamically from a silverlight page using Html Dom bridge.
For those who wonder what is the difference between a Html Silverlight Dom bridge and HTML Overlay, Html overlay needs the windowless parameter to be set and gives the rendering job to the browser, but Html Silverlight Dom model won't.
There is an excellent FAQ article by erikreitan on the Html and Java script in silverlight http://blogs.msdn.com/erikreitan/archive/2008/12/02/silverlight-html-bridge-faq.aspx. Take a look at this article when you get some time.

HtmlDocument doc = HtmlPage.Document;
HtmlElement dynamicDiv = doc.CreateElement("div");
dynamicDiv.SetAttribute("id", System.Guid.NewGuid().ToString());
dynamicDiv.SetStyleAttribute("height", "20px");
dynamicDiv.SetStyleAttribute("width", "800px");
dynamicDiv.SetProperty("innerhtml", "A small sample of dynamically added div from silverlight");
doc.Body.AppendChild(dynamicDiv);

Remember to include the 'System.Windows.Browser' namespace for this code to compile.