zoukankan      html  css  js  c++  java
  • 让WCF支持Http调用

    自己有一个项目是使用WCF写的,使用的是wsHttpBind,现在的新需求是要做Web版的,如果再写一套WebApi那工作量有点大了

    WCF是可以使用Http进行访问的,只要在配置中开启了

     <serviceBehaviors>
            <behavior>
              <!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false -->
              <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
              <!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 -->
              <serviceDebug includeExceptionDetailInFaults="true"   httpHelpPageEnabled="true"/>
            </behavior>
          </serviceBehaviors>
    

      

    但因为是使用的wsHttpBind进行绑定,所以有一个问题,http在发送POST或GET请求时,需要将参数封闭成Soap式的XML信封形式,然后写入到请求正文中,大致如下

    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Body>
    <!-- 请求方法名称 --> <Login xmlns="http://tempuri.org/" xmlns:a="http://schemas.datacontract.org/2004/07/PSerivce" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <!-- 请求参数 name --> <name>super</name>
    <!-- 请求参数 pwd-->
    <pwd>123456</pwd>
    <!-- 复杂参数 person-->
    <person xmlns:a="http://schemas.datacontract.org/2004/07/PublicModel" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
      <a:gender>boy</a:gender>
    </person>
    </Login>
    </s:Body>
    </s:Envelope>

      

    上面的信封的意思就是我要 访问的方法是Login,有三个参数,name,pwd,以及一个自定义类型person,可以看到

    封装成xml的形式很麻烦,特别是针对复杂类型,而wcf返回的正文也是一样的形式,很不好解析,而且在请求标头里还需要加一个自定义的SOAPAction属性,值为 "http://tempuri.org/IPublicSerivce/Login" (注意,引号也是必须的,该值的组成为 "命名空间/契约接口/方法名称"

    换另一种更简单的方式

    这是配置文件

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
     
      <appSettings>
        <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
      </appSettings>
      <system.web>
        <compilation debug="true" targetFramework="4.5.2" />
        <httpRuntime targetFramework="4.5.2"/>
      </system.web>
    
      <!--配置WCF-->
      <system.serviceModel>
    
        <!--配置行为-->
        <behaviors>
          <!--终结点行为-->
          <endpointBehaviors>
            <!--配置一个web行为-->
            <behavior name="WebBehavior">
              <!--以下参数的释义
              1.是否启用帮助页面
              2.参数与响应的封装类型(此处为都封装)
              3.默认的返回主体格式化(此处为返回json格式)
              4.是否自动选择请示正文和响应正文的格式化(如果为true,则会先去找http请示标头上的Accept,
                再找契约方法上有无 RequestFormat/ResponseFormat,如果没有,则找此配置中有无
                defaultOutgoingResponseFormat
              5.启用异常输出
              -->
              <webHttp helpEnabled="true"
                       defaultBodyStyle="Wrapped"
                       defaultOutgoingResponseFormat="Json"
                       automaticFormatSelectionEnabled="true"
                       faultExceptionEnabled="true"
                         />
            </behavior>
          </endpointBehaviors>
          <serviceBehaviors>
            <behavior>
              <!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false -->
              <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
              <!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 -->
              <serviceDebug includeExceptionDetailInFaults="true"   httpHelpPageEnabled="true"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
    
        <!--添加绑定-->
        <bindings>
          <!--添加web绑定-->
          <webHttpBinding>
            <!--是否启用跨域-->
            <binding   crossDomainScriptAccessEnabled="true" />
          </webHttpBinding>
        </bindings>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"  />
        <!-- 我们手动添加 -->
        <services>
          <!--添加一个服务-->
          <service name="PublicSerivce.PSerivce">
            <!--绑定一个用来http访问的web终结点
              注意该终结点的属性 address 因为这里绑了两个终结点
              所以它们的路径不能一致,使用http调用的时候
              此处的地址可能为 http://localhost:56599/pSerivcce.svc/SerivceWeb/请示的方法名称
            -->
            <endpoint address="SerivceWeb"
                      behaviorConfiguration="WebBehavior"
                    binding="webHttpBinding"
                    contract="PublicInterFace.IPublicSerivce"   />
    
            <!--绑定第二个终结点-->
            <endpoint binding="basicHttpBinding"
                      contract="PublicInterFace.IPublicSerivce" />
          </service>
        </services>
      </system.serviceModel>
      <system.webServer>
        <modules runAllManagedModulesForAllRequests="true"/>
        <!--
            若要在调试过程中浏览 Web 应用程序根目录,请将下面的值设置为 True。
            在部署之前将该值设置为 False 可避免泄露 Web 应用程序文件夹信息。
          -->
        <directoryBrowse enabled="true"/>
      </system.webServer>
    
    </configuration>
    

      

    配置好了文件后,在契约接口中应当打上WebGet或WebInvoke标记

    WebGet:允许http以Get方式调用,但要指定UriTemplete(指定参数形式,一般来说不太常用,请参见 https://docs.microsoft.com/zh-cn/dotnet/framework/wcf/feature-details/uritemplate-and-uritemplatetable

    WebInovke:默认为POST请求,如果要使用Get,则设置其Method属性

    以下为契约接口示例

    [ServiceContract(SessionMode = SessionMode.Allowed)]
        public interface IPublicSerivce
        {
         //这个标记还是可以使用以前的访问模式 [OperationContract]
              //下面这个标记是允许使用http方式调用 //因为在配置文件中已经设置了默认的 requestMessageFormat,responseMessageFormat,BodyStyle,所以此处不用设置属性 //而UriTemplate未设置,则直接使用方法名称 (UriTemplate可以给方法指定别名) [WebInvoke] string GetErroMsg(); [OperationContract] [WebInvoke] bool Login(string name1, string pwd, out UserInfoModel userInfo); [OperationContract] [WebInvoke] bool FindPartsForType(string name, out DataTable dt); [OperationContract] [WebInvoke] bool FindTypeForPart(string name, out DataTable dt); }

      

    现在就OK了,现在我们就可以使用http调用wcf了,以下为POSTMAN的调用截图

    示例为调用 

    FindTypeForPart

    请求头

    请求主体

     响应

    可以看到,请求和响应的时候都是json,但out参数datatable类型却输出的是xml,这个暂时我还不知道怎么弄成json的

    另外特别注意

    参数是自定义类型:

     需要完整属性,不能是自动属性,否则返回的json中属性名称可能就不是你的预期了(自己试下就知道了)

     另外如果是DateTime属性,最好换成DateTime?类型,而且此属性一定不能给其赋值 DateTime.MinValue,否则会进入两次调用,而且wcf会关闭连接导致获取不到响应(这个我也不知道为嘛)

  • 相关阅读:
    C++11并发之std::thread<转>
    YUV420格式解析<转>
    在windows、linux中开启nginx的Gzip压缩大大提高页面、图片加载速度<转>
    curl 超时设置<转>
    C++中map用法详解《转》
    同一台服务器配置多个tomcat服务的方法
    找出两个排好序的数组的中位数
    mysql中设置默认字符编码为utf-8
    大步小步攻击算法_完全版
    ACL登陆认证
  • 原文地址:https://www.cnblogs.com/rbzz/p/14352477.html
Copyright © 2011-2022 走看看