REST中GET方法URI地址定义问题:MessageContract无法配合UriTemplate使用
这个坑我之前踩过!WCF里确实不能直接把MessageContract和UriTemplate搭配使用——原因很直白:MessageContract是用来定义完整消息体结构的(不管是SOAP还是REST),而UriTemplate是负责从URL路径/查询串里提取参数,两者的参数绑定逻辑根本不兼容,所以才会报错。
给你两个可行的解决方案,根据你的需求选:
方案一:用普通DTO类+FromUri特性(推荐,保留GET语义)
放弃MessageContract,改用普通的POJO类封装参数,然后通过[FromUri]特性告诉WCF:把URL里的参数映射到这个类的属性上。
步骤1:修改输入类
去掉MessageContract和MessageBodyMember特性,改成普通类:
public class RetrievePublishedDataInput { public string id { get; set; } public string fieldsParam { get; set; } }
步骤2:修改服务方法
给参数加上[FromUri]特性,同时保留原来的UriTemplate定义:
[OperationContract] [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "Product/{id}?fields={fieldsParam}")] Message JSONData([FromUri] RetrievePublishedDataInput input);
这样WCF会自动把URL里的id和fieldsParam查询参数,映射到input对象的对应属性上,完美适配原来的GET请求语义。
方案二:改用POST请求(仅当必须用MessageContract时)
如果你的业务场景必须用MessageContract,那只能把请求改成POST——因为GET请求的参数本来就应该在URL里,而MessageContract是针对请求体的,GET请求通常没有请求体,两者天然不匹配。
这种情况下你需要:
- 保留
RetrievePublishedDataInput的MessageContract定义 - 修改
WebInvoke的Method为POST,并去掉UriTemplate里的参数占位符:
[OperationContract] [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "Product")] Message JSONData(RetrievePublishedDataInput input);
然后客户端需要把参数放在POST请求的Body里发送,但这就改变了原来的GET请求逻辑,所以除非必要,不推荐这种方式。
补充说明
你原来的代码能正常运行,是因为方法参数是直接对应UriTemplate里的占位符,WCF可以直接从URL提取并绑定到单个参数上;而换成MessageContract后,WCF会尝试从消息体里解析这个对象,GET请求没有消息体,同时UriTemplate的参数也没法绑定到MessageContract的成员上,自然就冲突报错了。
内容的提问来源于stack exchange,提问作者Artyom Valeev

