zoukankan      html  css  js  c++  java
  • WCF Rest:不使用UriTemplate使用post方式传参解决HTTP400问题以及参数映射问题

    在使用POST方式向服务提交数据时,出现HTTP400异常,以下代码描述:

        服务接口定义:

        [OperationContract]
        [WebInvoke(ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, Method = "POST", BodyStyle =             WebMessageBodyStyle.Bare)]
        Stream HelloData(MyData data);

        [OperationContract]
    [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Bare)]
    Stream HelloDataStr(String data);

        实现只是简单的把传入的数据打印出来,略

        客户端调用:

        方法一、 

        private static void HelloDataClient()
        {

          WebClient client = new WebClient();
          client.Headers["Content-Type"] = "application/json";
          string data = "{"ID":1,"Name":"ss"}";
          string str = client.UploadString("http://localhost:1122/HelloData", "POST", data);
          Console.WriteLine(str);
        }

        方法二

        private static void HelloDataStrClient()
        {
          WebClient client = new WebClient();
          string str = client.UploadString("http://localhost:1122/HelloDataStr", "POST", "ss");
          Console.WriteLine(str);
        }

        以上两个方法对用调用两个不同的服务,问题在于使用Mydata数据契约的方法一OK,方法二出现HTTP400错误。为什么自定义类型的可以,而基本数据类型的不可以?起初认为自定义数据类型自己已经做了序列化,而string不是自己做的可能跟序列化有关。那没有用UriTemplate是不是参数映射出了问题?因为方法一已经成功,说明WCF会将HTTP请求参数默认映射到仅有的一个服务接口的参数上。排除此猜测。

        方法后来做了以下迭代测试:

        将方法二改为:

        private static void HelloDataStrClient()
        {
          WebClient client = new WebClient();
          string str = client.UploadString("http://localhost:1122/HelloDataStr", "POST", String.Empty);
          Console.WriteLine(str);
        }

        发现调用成功,说明数据有问题。数据有问题就是数据的格式有问题,但是服务契约二没有声明Request的格式为JSON。那么他默认为什么呢?把方法二再改如下:

        private static void HelloDataStrClient()
        {
          WebClient client = new WebClient();
          client.Headers["Content-Type"] = "application/json";
          string str = client.UploadString("http://localhost:1122/HelloDataStr", "POST", ""ss"");
          Console.WriteLine(str);

        }

        调用成功。

          注意:JSON格式默认为“”引起,所以 ""ss""不能写为“ss”,否则还是HTTP400错误。因为未识别数据,将数据拼接到其他字节了吧。

        问题描述二、

          没有使用UriTemplate做参数的映射,那多个参数是怎么映射的?将方法二改为:

        服务契约二:

        [OperationContract]
        [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped)]
        Stream HelloDataStr(String data1,string data2);

        客户端:

        private static void HelloDataStrClient()
        {
          WebClient client = new WebClient();
          client.Headers["Content-Type"] = "application/json";
          string str = client.UploadString("http://localhost:1122/HelloDataStr", "POST", "{"data1":"hh","data2":"ss"}");
          Console.WriteLine(str);

        }

        调用成功,并且成功打印了两个参数。注意服务契约的接口定义属性WebMessageBodyStyle.Wrapped,此属性将两个参数进行了包装,否则无法映射。

        附:JAVA调用代码:

        

    public static void main(String[] args) {
    // TODO Auto-generated method stub
      HelloClient();

      HelloDataClient();

      HelloDataStrClient();

    }
    private static void HelloClient(){
      URLClient client = new URLClient();
      String resultStr = client.getDocumentAt("http://localhost:1122/Hello");
      MyData data = assembleModel(resultStr);
      System.out.print("Hello Response content: " +resultStr);
      System.out.println("MyData Name: " +data.getName());
    }

    private static void HelloDataClient(){
      try {

    String postUrl = "http://localhost:1122/HelloData";
    String postData = "{"data1":1,"data2":"ss"}";
    HttpClient hClient = new DefaultHttpClient();
    HttpPost post = new HttpPost(postUrl);
    StringEntity s = new StringEntity(postData);
    s.setContentEncoding("UTF-8");
    s.setContentType("application/json");
    post.setEntity(s);
    HttpResponse response = hClient.execute(post);
    HttpEntity responseEntity = response.getEntity();

    String resultStr = inputStream2String(responseEntity.getContent());
    MyData data = assembleModel(resultStr);
    System.out.println("HelloDataStr Response content: " 
    + resultStr); 
    System.out.println("MyData Name: " +data.getName());

    } catch (Exception e) {

      // TODO: handle exception

      }

    }

    private static void HelloDataStrClient(){
      try {

    String postUrl = "http://localhost:1122/HelloDataStr";
    String postData = "{"data1":1,"data2":"ss"}";
    HttpClient hClient = new DefaultHttpClient();
    HttpPost post = new HttpPost(postUrl);
    StringEntity s = new StringEntity(postData);
    s.setContentEncoding("UTF-8");
    s.setContentType("application/json");
    post.setEntity(s);
    HttpResponse response = hClient.execute(post);
    HttpEntity responseEntity = response.getEntity();

    String resultStr = inputStream2String(responseEntity.getContent());
    System.out.println("HelloDataStr Response content: " 
    + resultStr);

      } catch (Exception e) {
    // TODO: handle exception
        }
    }

    public static String inputStream2String(InputStream is) throws IOException { 
      ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
      int i = -1; 
      while ((i = is.read()) != -1) { 
        baos.write(i); 
      } 
      return baos.toString(); 

    private static MyData assembleModel(String jsonStr) {
      MyData model = null;
      try {
          JsonConvertor jsonConvertor = new JsonConvertor();
          MyData[] stus = (MyData[]) jsonConvertor
        .convertToObj(jsonStr,MyData.class);
          model = stus[0];
        } catch (Exception e) {
          e.printStackTrace();
      }
      return model;
    }

  • 相关阅读:
    Linux-获取当前正在执行脚本的绝对路径
    Linux-SSL和SSH和OpenSSH,OpenSSL有什么区别
    Nginx-SSI
    Linux-TCP/IP TIME_WAIT状态原理
    Linux-IP地址后边加个/8(16,24,32)是什么意思?
    Nginx-/etc/sysctl.conf 参数解释
    Linux-内核缓存区和write行为
    常用音频软件:Cool edit pro
    常用音频软件:Wavesufer
    【转】智能音箱技术概览
  • 原文地址:https://www.cnblogs.com/keyyang/p/4324017.html
Copyright © 2011-2022 走看看