Silverlight on SharePoint

这两天花了点时间在Silverlight上。Silverlight blueprint在RTM之前有一个MediaViewer的Web Part,可是在RTM里这个web part没有了。而http://mssharepointdeveloper.com/上关于Silverlight的hands-on中,第三个是MediaViewer,但是它的代码也是基于Silverlight 2 beta 2的,在Silverlight 2上不能正常工作。Silverlight control可以在Web Part中正常加载,但媒体内容无法正常显示,只显示一个白色画布。我对Silverlight也没有太多的认识,为了修复代码中的问题,debug的过程真实一波三折,总算最终找到了问题所在并修复了。修复后的代码可以从这里下载。

原先的代码中有两个问题,这两个问题其实是相关的。

1. 这个MediaViewer通过调用SharePoint的web service来取得媒体文件的信息,特别是媒体文件的URL。这个web service的调用是通过Ajax的异步方式实现的。源代码如下:

        private void BuildPreviewBar()
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(siteUrl + "/_vti_bin/Lists.asmx", UriKind.Absolute));
            request.Method = "POST";
            request.ContentType = "application/soap+xml; charset=utf-8";
            request.BeginGetRequestStream(new AsyncCallback(RequestCallback), request);
            request.BeginGetResponse(new AsyncCallback(ResponseCallback), request);
        }

这里request和response运行在两个线程里,这两个线程的timing和同步就变成了一个问题。解决方法是将request.BeginGetResponse放入RequestCallback方法的最后,当request已经写完之后,再来获取response。

2. 这样做了之后,随之而来的第二个问题是,在ResponseCallback方法中有一些代码是用来更新UI的,比如更新PreviewControl,由于ResponseCallback是运行在一个工作线程里,这就引起了Cross thread的问题。最终在Silverlight的论坛里找到了解法,就是将ResponseCall里的调用,用Dispatcher.BeginInvoke的delegate包装,Dispatcher保证了代码运行在UI线程里。

在debug这个Silverlight应用的过程中,除了一些Silverlight的基本资料,我看得最多的就是Silverlight论坛和一些牛人的博客,也对Silverlight有了一些认识。Silverlight说穿了就是一个WPF的子集,它包含了一些有用的组件,比如MediaElement,使得浏览器不必依赖客户端的媒体播放器就能够播放媒体文件。这一点Flash早就可以做到,但是如果用Silverlight结合Expression系列以及Visual Studio,就能很容易地开发出具有全新用户体验的web应用了。目前Silverlight比较大的一个问题是,各个版本之间变化太大,换了版本之后原有的代码可能就不能工作了,现在就将已有的应用迁移到Silverlight上来,还真需要一些决心。