做即时通信项目时,需要与OA系统对接接口,主要目标是实现在OA里进行一项事项,通过调用我们的接口,即时通知过来,并弹出消息框提示一下。我们的即时通信使用的WCF服务进行通信,在客户端调用通信时,用的就是直接添加服务引用的方式,无可厚非,但是OA系统对接了太多项目,不能使用添加服务引用的方式,问题就来了,不得已只能更改我们的接口。
因为不熟悉这一块,浪费了不少时间,总结一下过程,方便以后使用。
微软官方文档:https://msdn.microsoft.com/zh-cn/library/dd315413.aspx#id0070003

一、修改
首先,说一下用到的技术。REST编程模型,为了能够让OA这边用他们通用的方法直接调用api,上网查找post调用wcf的方法,我见识浅薄,只知道使用REST编程的方式。

1.修改接口
主要是添加一个特性【WebInvoke】,该属性指示服务操作在逻辑上就是调用操作,且可由wcf REST编程模型调用。
这里可以指定是GET调用或者POST调用,一般的格式如下:

GET:
[OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "Say")]
string Say();
[OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "SayHello/{value}/{a}")]
string SayHello(string value, string a);
POST:
[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, Method = "POST")]
string PostDataTest(string value,string content);
[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped,ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, Method = "POST")]
void WorkSend(string Title, string ReceiverId, string SenderId, string Content, string URL, string MsgType);
推荐一个网址,里面有REST的介绍与详细的步骤:
http://www.cnblogs.com/wuhong/archive/2011/01/13/1934492.html(方法的参数是类对象,我这里用参数就可以实现)

2.修改服务端app.config/web.config
需要完全修改原来提供的接口配置。
首先在<bindings>标签内添加webHttpBinding,简单描述一下这种绑定协议:
WebHttpBinding允许开发人员通过 HTTP 请求(这些请求使用“Plain old XML”(POX) 样式消息,而不是使用基于 SOAP 的消息)来公开 Web 服务,可以很便利的实现REST。
与其他绑定不同的是:必须使用WebHttpBehavior对服务的终结点进行配置。还要求使用WebGetAttribute或WebInvokeAttribute属性将各个服务操作映射到 URI,同时定义调用和返回结果的消息格式。
下面是我的绑定:
<webHttpBinding>
<binding name="NewBinding3" maxReceivedMessageSize="2147483647" transferMode="Buffered">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="12000000" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
<security mode="None">
<transport clientCredentialType="None"></transport>
</security>
</binding>
</webHttpBinding>
然后行为的配置,必须使用WebHttpBehavior对服务的终结点进行配置。
如下:
<endpointBehaviors>
<behavior name="webHttp"> <!--必须设置-->
<webHttp helpEnabled="true" automaticFormatSelectionEnabled="true"/>
</behavior>
</endpointBehaviors>
因为我的wcf服务是寄宿在后台服务程序里的,会明确指定端口与ip,所以我还需要添加一个服务行为
<behavior name="RESTBehaviors">
<!-- 将下列元素添加到服务行为配置中。 -->
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://192.168.1.192:8008/IMWCF/OpenAPI/"/>
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
最后就是添加<services>配置终结点了:
<service name="WCFService.OPenApi" behaviorConfiguration="RESTBehaviors">
<endpoint address="http://192.168.1.192:8008/IMWCF/OpenAPI/" binding="webHttpBinding" bindingConfiguration="NewBinding3" contract="WCFContract.IOPenApi" behaviorConfiguration="webHttp">
</endpoint>
</service>

3.修改客户端调用方式
这里提供两种方式,一种是常规的通过HttpWebRequest的方式,一种是直接通过WebClient的方式,个人感觉第二种更方便一些。(重要的是参数数据的传递)
另外提一下,上面推荐的网址中,提供了C#编程直接访问HTTP的方式与使用jqueryGET和POST访问的方式,消息的格式不一样,一种是xml,一种是json格式,这里我没做细的研究,都用的json格式。
常规方式
代码如下:
public string PostHelper(string uri, string postData)
{
try
{
Encoding myEncode = Encoding.GetEncoding("UTF-8");
//转换为字节数组
byte[] data = Encoding.UTF8.GetBytes(postData);

Uri uRI = new Uri(uri);
HttpWebRequest req = WebRequest.Create(uRI) as HttpWebRequest;
req.Method = "POST";
req.KeepAlive = true;
//req.ContentType = "application/json";
req.ContentType = "application/json;charset=utf-8";

req.ContentLength = data.Length; ////填充POST数据
req.AllowAutoRedirect = true;
//这个在Post的时候,一定要加上,如果服务器返回错误,他还会继续再去请求,不会使用之前的错误数据,做返回数
req.ServicePoint.Expect100Continue = false;

Stream outStream = req.GetRequestStream();
outStream.Write(data, 0, data.Length);
outStream.Close();

//发送POST数据请求服务器
HttpWebResponse res = req.GetResponse() as HttpWebResponse;
//获取服务器返回信息
Stream inStream = res.GetResponseStream();
//StreamReader sr = new StreamReader(inStream);
StreamReader sr = new StreamReader(inStream, myEncode);
string htmlResult = sr.ReadToEnd();

return htmlResult;
}
catch (Exception ex)
{
return "网络错误:" + ex.Message.ToString();
}
}
调用:
string url = "http://192.168.1.192:8008/IMWCF/OpenAPI/WorkSend";
string postData = @"{'Title': '"+ title + "','ReceiverId': '" + recevier + "','SenderId': '" + sender + "','Content': '" + content + "','URL': '" + invokeurl + "','MsgType': '" + msgtype + "'}";
string mes = PostHelper(url, postData);

WebClient方式
WebClient client = new WebClient();
client.Headers.Add("Content-Type", "application/json");
try
{
var result = client.UploadString("http://192.168.1.192:8008/IMWCF/OpenAPI/PostDataTest", "POST", "{\"value\":\"ading\",\"content\":\"good\"}");
Console.WriteLine("返回值为{0}", result.ToString());
}

二、问题
在配置好服务端后,客户端写好调用方式后,遇到最多并且花费我大量时间的问题就是,400错误,
远程服务器返回错误: (400) 错误的请求。

一到这里就报错,上网查找好多400错误,都没有解决,最后看到一条评论说这种问题就是,参数不匹配或者调用方式get、post搞错的导致的。
通过第三方的Postman调用我的接口,发现能正常调用,排除问题出在服务端的可能,只能是自己的客户端调用或者配置存在问题,因为json转换这块不是很熟,着重排查这里,一番修改,发现参数也没什么问题。
实在没办法,在服务端添加测试接口,只传递一个参数的方法,调用后发现没问题,然后对比两个接口方法的锲约,发现缺少了BodyStyle = WebMessageBodyStyle.Wrapped,添加后,发送可以调用了,查看描述,得知BodyStyle = WebMessageBodyStyle.Wrapped设定包装参数。
添加属性BodyStyle = WebMessageBodyStyle.WrappedRequest,
[WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped,ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, Method = "POST")]
并且需要保证后台传递数据中包含参数的传递
例如 string postData = @"{""value"": ""hello""}";,value及服务中方法的参数名。

三、总结

自工作以来,一直从事CS端方向项目,对于BS端得很多知识都靠得在学校学的基础,BS端的网络协议、json数据格式等都不熟,需要好好补充一下知识了。最后感谢网上其他同仁们的无私分享。

POST调用WCF方法-项目实践的更多相关文章

  1. c# 动态调用WCF方法笔记!

    //动态调用wcf方法 string url = "http://localhost:54379/ServiceWCF.svc"; IDoubleService proxy = W ...

  2. .NET Core调用WCF的最佳实践

    现在.NET Core貌似很火,与其他.NET开发者交流不说上几句.NET Core都感觉自己落伍了一样.但是冷静背后我们要也看到.NET Core目前还有太多不足,别的不多说,与自家的服务框架WCF ...

  3. WCF基础教程之开篇:创建、测试和调用WCF

    一转眼,又半个月没有更新博客了.说实话,最近确实是有点忙.不过即使再忙忙,也要抽空来学习一些东西.最近用WCF比较多,就来跟大家分享一下关于WCF的知识吧!为了让大家都能看懂,照顾一些没有学过WCF的 ...

  4. MVC项目实践,在三层架构下实现SportsStore-09,ASP.NET MVC调用ASP.NET Web API的查询服务

    ASP.NET Web API和WCF都体现了REST软件架构风格.在REST中,把一切数据视为资源,所以也是一种面向资源的架构风格.所有的资源都可以通过URI来唯一标识,通过对资源的HTTP操作(G ...

  5. 学习调用WCF服务的各种方法

    1.开发工具调用WCF 这中方法很方便也很简单,很多工作VS就帮我们完成了.相信大家也不会对这种方法陌生.这里简单提一下.打开VS,在项目中添加服务引用: 在config中自动声明了有关服务的节点信息 ...

  6. [转]学习 WCF (6)--学习调用WCF服务的各种方法

    转自:http://www.cnblogs.com/gaoweipeng/archive/2009/07/26/1528263.html 作者这篇博文写得很全面. 根据不同的情况,我们可以用不同的方法 ...

  7. 学习之路十四:客户端调用WCF服务的几种方法小议

    最近项目中接触了一点WCF的知识,也就是怎么调用WCF服务,上网查了一些资料,很快就搞出来,可是不符合头的要求,主要有以下几个方面: ①WCF的地址会变动,地址虽变,但是里面的逻辑不变! ②不要引用W ...

  8. 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理

    [微信小程序项目实践总结]30分钟从陌生到熟悉 前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05- ...

  9. jquery或者JavaScript调用WCF服务的方法

    /****************************************************************** * Copyright (C): 一心堂集团 * CLR版本: ...

随机推荐

  1. FileOutputSream文件字节输出流

    1.FileOutputSream文件字节输出流:  输入--写出--使用:  输出--写入--存储: 写出写入是对硬盘而言: 其中,OutputStream为所有类型的字节输出流的超类: FileO ...

  2. Java多线程编程的常见陷阱

    .在构造函数中启动线程 我在很多代码中都看到这样的问题,在构造函数中启动一个线程,类似这样: public class A{ public A(){ ; ; this.thread=new MyThr ...

  3. CCF CSP 201809-1 卖菜

    题目链接:http://118.190.20.162/view.page?gpid=T79 问题描述 试题编号: 201809-1 试题名称: 卖菜 时间限制: 1.0s 内存限制: 256.0MB ...

  4. python———day1

    1.计算机基础:CPU,内存,硬盘,操作系统 2.python出生于应用 3.python2与python3的区别(宏观): python2:源码不标准,混乱,重复代码太多 python3:统一标准, ...

  5. Object.prototype的成员介绍

    3.Object.prototype的成员介绍        Object.prototype是js中所有的对象的祖宗        Object.prototype中所有的成员都可以被js中所有的对 ...

  6. self study 权限 permission

    demo 测试成功, import 'package:permission/permission.dart'; Future requirePermission()async { await Perm ...

  7. Vue 组件&组件之间的通信 之 使用slot分发内容

    slot详细介绍网址:https://cn.vuejs.org/v2/api/#slot 有时候我们需要在自定义组件内书写一些内容,例如: <com-a> <h1>title& ...

  8. LOJ #10070 最小生成树计数

    一道mst-- 最开始是毫无头绪,于是就点开了--->题解 大部分题解都是矩阵树--然而第一篇题解告诉了我们暴搜也能过( 思路大概是说,对于一个图\(G\),它的所有最小生成树的相同权值的边的数 ...

  9. spring框架-jdbc

    一.实体层的不同名字    entity 实体类 :就是和数据库表一一对应的JavaBean  pojo 简单的java对象:任何应用场景的JavaBean  po 持久化对象 :就是和数据库表一一对 ...

  10. windows eclipse直接访问远程linux hadoop开发环境配置(符合实际开发的做法)

    CDH 5.x搭建请参考CentOS 7离线安装CDH 5.16.1完全指南(含各种错误处理). 如果使用的是cloudera quickstart vm,则只能在linux服务器中使用eclipse ...