解决一个通过 WebReference 调用 WCF 时自定义 DataContract 类参数提交的问题
先看一下VS2013自动创建默认的IService1.vb,注意自定义的数据契约 CompositeType
' 注意: 使用上下文菜单上的“重命名”命令可以同时更改代码和配置文件中的接口名“IService1”。 <ServiceContract()> Public Interface IService1 <OperationContract()> Function GetData(ByVal value As Integer) As String <OperationContract()> Function GetDataUsingDataContract(ByVal composite As CompositeType) As CompositeType ' TODO: 在此添加您的服务操作 End Interface ' 使用下面示例中说明的数据约定将复合类型添加到服务操作。 <DataContract()> Public Class CompositeType <DataMember()> Public Property BoolValue() As Boolean <DataMember()> Public Property StringValue() As String End Class
通过添加 WebReference 引用后的客户端代码
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Dim wrClient As New localhost.Service1 Dim data As New localhost.CompositeType data.BoolValue = True 'data.BoolValueSpecified = True data.StringValue = "Hello world" Dim result As localhost.CompositeType = wrClient.GetDataUsingDataContract(data) MessageBox.Show(result.StringValue) End Sub
注意被注释掉的那一行,在没有显式地指定 data.BoolValueSpecified = True 的情况下,BoolValue 的值不会被客户端提交到服务端,服务端接收到的 data 参数中BoolValue 将赋值为其默认值(false)。
类似的还有服务契约中的参数如果不是String类型,则必须指定 [参数名]Specified = True,该参数才会被执行提交,如
<OperationContract()> Function GetDataUsingBoolValue(ByVal boolValue As Boolean, ByVal StringValue As String) As String
对应的客户端调用代码
MessageBox.Show(wrClient.GetDataUsingBoolean(True, True, "Hello World"))
如果你打算客户端省点功夫,不想总是显式地设置 Specified = True, 那么在声明服务契约和数据契约时,就要多做一点工作
<ServiceContract()> Public Interface IService1 <OperationContract()> Function GetData(ByVal value As Integer) As String <OperationContract()> Function GetDataUsingDataContract(ByVal composite As CompositeType) As CompositeType ' TODO: 在此添加您的服务操作 ''' <summary> ''' 存在非String类参数的方法 ''' </summary> ''' <param name="boolValue"></param> ''' <param name="StringValue"></param> ''' <returns></returns> ''' <remarks> ''' 注意:DataContractFormat(Style:=OperationFormatStyle.Rpc) ''' 如果没有设置此属性,非String类的参数默认不会被提交,是否被提交将由 [非String类参数名]Specified 的取值决定 ''' </remarks> <OperationContract(), DataContractFormat(Style:=OperationFormatStyle.Rpc)> Function GetDataUsingBoolValue(ByVal boolValue As Boolean, ByVal StringValue As String) As String End Interface ' 使用下面示例中说明的数据约定将复合类型添加到服务操作。 <DataContract()> Public Class CompositeType ''' <summary> ''' 非String类的参数 ''' </summary> ''' <value></value> ''' <returns></returns> ''' <remarks> ''' 注意:IsRequired:=True ''' 如果没有设置此属性,该参数默认不会被提交,是否被提交将由 BoolValueSpecified 的取值决定 ''' </remarks> <DataMember(IsRequired:=True)> Public Property BoolValue() As Boolean <DataMember()> Public Property StringValue() As String End Class
具体的解释,可以参见这里
今天为这个问题折腾了老半天,尤其是 DataContract 里面的 DataMember(IsRequired:=True) 藏得比较深,特别是在客户端通过 ServiceReference 引用的时候没有这个问题,到了用 WebReference 引用的时候,发现非String类型(如 Integer, Double, Single, DateTime等,不过 Byte数组除外)的参数死活提交不上去了。
立此存照,希望能帮到不小心掉进这个坑里的同行,:)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现