我正在编写一个WCF WebMethod来上传文件,我从网上获取了一些片段。 WCF界面如下所示:
<ServiceContract()>
Public Interface ITransferService
<OperationContract()>
Sub UploadFile(ByVal request As RemoteFileInfo)
End Interface
<MessageContract()>
Public Class RemoteFileInfo
Implements IDisposable
<MessageHeader(MustUnderstand:=True)>
Public FileName As String
<MessageHeader(MustUnderstand:=True)>
Public Length As Long
<MessageBodyMember(Order:=1)>
Public FileByteStream As System.IO.Stream
Public Sub Dispose() Implements IDisposable.Dispose
If FileByteStream IsNot Nothing Then
FileByteStream.Close()
FileByteStream = Nothing
End If
End Sub
End Class
在ASP.NET中,当使用Web方法时,由于某种原因,只有在将接口用作RemoteFileInfo
实例化的一部分时,它才有效:
Protected Sub btn_Click(sender As Object, e As EventArgs) Handles btn.Click
If fu.HasFile Then
Dim fi As New System.IO.FileInfo(fu.PostedFile.FileName)
' this is the line in question --------------
Dim cu As ServiceReference1.ITransferService = New ServiceReference1.TransferServiceClient()
' -------------------------------------------
Dim uri As New ServiceReference1.RemoteFileInfo()
Using stream As New System.IO.FileStream(fu.PostedFile.FileName, IO.FileMode.Open, IO.FileAccess.Read)
uri.FileName = fu.FileName
uri.Length = fi.Length
uri.FileByteStream = stream
cu.UploadFile(uri)
End Using
End If
End Sub
任何人都可以建议使用以下方法创建TransferService
实例的原因:
Dim cu As New ServiceReference1.TransferServiceClient()
如果我尝试以上操作,就会打破这一行:
cu.UploadFile(uri)
...必须使用三个参数(FileName,Length,FileByteStream)调用UploadFile,即使没有使用此签名的方法。
为什么在创建这个类的实例时需要接口?
答案 0 :(得分:2)
使用&#34;添加服务参考&#34;为您的服务创建代理时对话框,默认情况下,代理创建代码将&#34;展开&#34;消息合同,就像你拥有的那样。如果您希望邮件合同按照您在代理服务器端定义的那样显示,则需要选择&#34; Advanced&#34;选项卡,然后选中&#34;始终生成邮件合同&#34;选项。有了它,您也可以在您的客户端获得消息合同。
答案 1 :(得分:1)
问题在于,当遇到MessageContract
作为参数时,WCF客户端生成默认情况下假定您要实现消息传递样式接口,并提供消息协定中的离散属性作为客户端接口。
MSDN中的Using Messaging Contracts文章包含了对消息传递合同可以做些什么的非常详细的描述,我怀疑微软选择了这种默认行为,因为你可以使用这些消息来播放一些“游戏”
但是,如果你在客户端检查为UploadFile生成的代码,那么有一些有趣的花絮可以帮助解释发生了什么。
第一个是界面中UploadFile方法的注释:
'CODEGEN: Generating message contract since the operation UploadFile is neither RPC nor document wrapped.
...
Function UploadFile(ByVal request As ServiceReference1.RemoteFileInfo) As ServiceReference1.UploadFileResponse
这意味着如果消息合同具有不同的实现,则合同将以不同方式生成。
第二,您将看到用于实际进行服务调用的代码没有什么特别之处:
Public Sub UploadFile(ByVal FileName As String, ByVal Length As Long, ByVal FileByteStream As System.IO.Stream)
Dim inValue As ServiceReference1.RemoteFileInfo = New ServiceReference1.RemoteFileInfo()
inValue.FileName = FileName
inValue.Length = Length
inValue.FileByteStream = FileByteStream
Dim retVal As ServiceReference1.UploadFileResponse = CType(Me,ServiceReference1.ITransferService).UploadFile(inValue)
End Sub
因此,在这种情况下,您的代码正在完成生成的代码所做的事情。但是,如果MessageContract更复杂,我怀疑这种情况将不再如此。
所以,对于你的问题:
任何人都可以建议为什么不可能创建一个实例 TransferService使用以下方法......
只要您验证方法调用的实现是否与您的代码等效,就没有理由不采用这种方法。
有几个选项可以更改客户端中方法的默认生成:
1)从MessageContract
类中删除RemoteFileInfo
属性。
2)虽然它看似违反直觉,但您可以查看Configure Service Reference Dialog Box中的Always generate message contracts
复选框。