最近论坛上谈论Silverlight应用程序安装部署问题很多,多数方法是手工解决方案,能够有效解决问题的方案并不多,后来发现采用手工解决方案的多数是使用Blend平台开发的,因为这个平台几乎没有提供自动化的部署能力,对于使用VS2008开发平台的用户帮助不大。因为我长期使用VS2008开发平台,所以总想找到一种与一般开发项目类似的通过平台生成的安装部署方案,经过一段时间得到论坛上朋友的帮助和个人的努力,对问题:VS2008+Silverlight2+WCF+Linq和VS2008+Silverlight3+WCF+linq的安装部署问题得到了基本满意的结果,从中也发现了微软VS2008和Silverlight结合开发应用程序的严重Bug,从中可以看出为什么微软短时间内多次升级Silverlight版本的原因,本人找到了解决这些Bug的办法,在这里总结一下发帖给大家,希望能够给Silverlight开发的朋友们有所帮助。
本贴针对使用VS2008开发平台,前提是在VS2008解决方案中建立三个项目:mySilverlight,mySilverlight.web,mySilverlightSetup,其中mySilverlight是Silverlight用户控件项目;mySilverlight.web是相应的Web托管项目,用来实现Silverlight用户控件项目;mySilverlightSetup是解决方案的安装部署项目,关于这三个项目解决方案的建立这里不再赘述。这里需要注意的是WCF服务要在mySilverlight.web项目中添加,因为在添加WCF项目时VS2008提供了两个WCF项目选择,许多书籍都没有特别指出来,在添加时一定要特别注意选择“启用了Silverlight功能的WCF”项,这里的添加的项目名是:mySilverlightWCF,相应的文件名是:mySilverlightWCF.svc。在mySilverlight项目添加引用,引用名称是myServiceReference。mySilverlightSetup项目是通过安装向导生成的,需要注意的是在选择要包括的输出项目时只选择来自mySilverlight.web的输出项目(这一点对于Silverlight3的安装部署尤为重要)的本地化资源、xml序列化程序集、内容文件、主输出、符号调试和文档文件,不必选择源文件。
项目使用的是VB代码,对于喜爱C#的朋友可使用SharpDevelop软件转换即可,这个软件对使用Vb的朋友也很有帮助,因为网上大部分的例子是C#,如果没有C++经验的朋友可以使用它进行转换。
一、先谈VS2008+Silverlight2+WCF安装部署问题
在引用WCF时应该使用下面的代码才能保证部署到其他服务器后的引用地址正确:
Dim myClient As myServiceReference.mySilverlightWCFClient
Dim binding As New _
BasicHttpBinding( _
If(Application.Current.Host.Source.Scheme.Equals( _
"https", StringComparison.InvariantCultureIgnoreCase), _
BasicHttpSecurityMode.Transport, BasicHttpSecurityMode.None))
binding.MaxReceivedMessageSize = Integer.MaxValue
binding.MaxBufferSize = Integer.MaxValue
myClient = New myServiceReference.mySilverlightWCFClient( _
binding, newEndpointAddress( _
New Uri(Application.Current.Host.Source, "../mySilverlightWCF.svc")))
二、再谈VS2008+Silverlight3+WCF安装部署问题
如果以为同样的方法在Silverlight3中也会好用那就错了,我在开始使用Silverlight3就犯了这样的错误,折腾我好长一段时间,后来发现应该把代码修改一下,实际上在Silverlight3中不必使用BasicHttpBinding了。
Dim myClient As myServiceReference.mySilverlightWCFClient
Dim myEndpointaddress As endpointaddress
myEndpointaddress = New EndpointAddress( _
New Uri(Application.Current.Host.Source, "../mySilverlightWCF.svc"))
myClient=new myServiceReference.mySilverlightWCFClient
myClient.Endpoint= myEndpointaddress;
三、linq to sql带来的问题安装部署问题
问题到这里似乎应该结束了,实际上并不是那么简单。Linq to sql 是vs2008的一项新技术,通过linq to sql 解决方案为开发者定义了与所连接数据库表和列相应的类和属性,开发者在项目中可以直接使用它们,免去了大量简单重复的为使用数据库表列定义的手写代码,它要比ado.net更方便很多,但它的安装部署时同样出现问题,问题描述如下:
Linq to sql 项在mySilverlight.web项目中添加,名称为DataClass1.dbml,把DataClass1.dbml连接到northwind数据库并将表categories拖放到设计窗口中,数据库northwind表categories及列的定义都在隐含的托管代码DataClass1.dbml.Designer.vb中,在解决方案文件夹中可以找到这个隐含代码,以后要用到。
在mySliverlightWCF.svc中添加如下代码可以在mySilverlight项目中通过WCF饮用访问数据库northwind中的表categories
<OperationContract()> Public Function get_a_categories() As Categories
Dim dc As New DataClasses1DataContext
Dim q = From s In dc.Categories Select s
Return q.First
End Function
<OperationContract()> Public Function get_categories() As List(Of Categories)
Dim dc As New DataClasses1DataContext
Dim q = From s In dc.Categories Select s
Return q.ToList
End Function
第一个方法返回表categories中的第一个记录,第二个方法返回整个表categories,在调试环境下使用这两个方法不存在任何问题,但部署到其他服务器上就不能正常使用了,在服务去浏览器上访问http://../mySilverlightWCF.svc,系统报错大意是categories没有序列化。我查看前面提到的隐含代码DataClasses1.designer.vb,有关内容如下:
<System.Data.Linq.Mapping.DatabaseAttribute(Name:="northwnd")> _
Partial Public Class DataClasses1DataContext
…
End Class
<Table(Name:="dbo.Categories")> _
Partial Public Class Categories
<Column(Storage:="_CategoryID", AutoSync:=AutoSync.OnInsert, DbType:="Int NOT NULL IDENTITY", IsPrimaryKey:=true, IsDbGenerated:=true)> _
Public Property CategoryID() As Integer
…
End Property
<Column(Storage:="_CategoryName", DbType:="NVarChar(15) NOT NULL", CanBeNull:=false)> _
Public Property CategoryName() As String
…
End Property
<Column(Storage:="_Description", DbType:="NText", UpdateCheck:=UpdateCheck.Never)> _
Public Property Description() As String
…
End Property
<Column(Storage:="_Picture", DbType:="Image", UpdateCheck:=UpdateCheck.Never)> _
Public Property Picture() As System.Data.Linq.Binary
…
End Property
…
End Class
这些代码是解决方案自动生成的,但是微软没有添加序列化声明,造成部署后不能序列化使这些代码无法使用,经修改的代码如下:
<DataContract(), System.Data.Linq.Mapping.DatabaseAttribute(Name:="northwnd")> _
Partial Public Class DataClasses1DataContext
…
End Class
<DataContract(),Table(Name:="dbo.Categories")> _
Partial Public Class Categories
<DataMember(),Column(Storage:="_CategoryID", AutoSync:=AutoSync.OnInsert, DbType:="Int NOT NULL IDENTITY", IsPrimaryKey:=true, IsDbGenerated:=true)> _
Public Property CategoryID() As Integer
…
End Property
<DataMember(),Column(Storage:="_CategoryName", DbType:="NVarChar(15) NOT NULL", CanBeNull:=false)> _
Public Property CategoryName() As String
…
End Property
<DataMember(),Column(Storage:="_Description", DbType:="NText", UpdateCheck:=UpdateCheck.Never)> _
Public Property Description() As String
…
End Property
<DataMember(),Column(Storage:="_Picture", DbType:="Image", UpdateCheck:=UpdateCheck.Never)> _
Public Property Picture() As System.Data.Linq.Binary
…
End Property
…
End Class
方法是为类增加DataContract()序列化声明,为属性增加了DataMember()序列化声明,这样在安装部署后问题就解决了。
我认为这是微软的bug,既然能够自动产生代码为什么不多加一个序列化声明呢?加了序列化声明并不影响代码的结果,只是在需要序列化时使用即可,在安装部署VS2008+Silverlight+WCF+Linq解决方案中正好要使用序列化,而微软却没有这样做,也许在Silverlight4中解决了这个bug。
手工修改这几个类和属性还可以,如果项目数据库中的表和列多了,相应的类和属性就会增加,手工完成费时费力易错,建议使用替换方法修改,另外因为在开发调试环境中不会出现序列化问题,所以在调试时不刻意必修改,只有到最后需要安装部署时最后修改一次即可。
说到这里时我已经基本上可以放心地使用VS2008+Silverlight3+WCF+Linq解决方案了而无安装部署的后顾之忧,以后再遇到什么问题再解决什么问题。
VS2008+Silverlight3+WCF+linq的安装部署
最新推荐文章于 2024-11-13 12:02:36 发布