C#以post方式调用struts rest-plugin service的问题

时间:2014-10-27 14:01:27   收藏:0   阅读:368

struts2: 玩转 rest-plugin 一文中,学习了用struts2开发restful service的方法,发现用c#以post方式调用时各种报错,但java、ajax,包括firefox 的rest client插件测试也无问题。

 

先给出rest service中的这个方法:

bubuko.com,布布扣
 1     // POST /orders
 2     public HttpHeaders create() throws IOException, ServletException {
 3         ordersService.doSave(model);
 4         HttpServletResponse response = ServletActionContext.getResponse();
 5         HttpServletRequest request = ServletActionContext.getRequest();
 6         String ContentType = request.getHeader("Content-Type").toLowerCase();
 7         if (ContentType.startsWith("application/xml")) { // 返回xml视图
 8             response.sendRedirect("orders/" + model.getId() + ".xml");
 9         } else if (ContentType.startsWith("application/json")) { // 返回json视图
10             response.sendRedirect("orders/" + model.getId() + ".json");
11         } else {// 返回xhtml页面视图
12             response.sendRedirect("orders/");
13         }
14         return null;
15     }
View Code

代码不复杂,post一段String过来(xml/json/html格式均可),自动映射成Order对象的实例model,然后根据请求HttpHeader中的Content-Type,如果是xml(application/xml),则返回model对应的xml,如果是json(application/json),则返回model对应的json,其它则返回页面

 

c#的调用代码:

bubuko.com,布布扣
 1 static string PostDataByWebClient(String postUrl, String paramData, String mediaType)
 2 {
 3     String result = String.Empty;
 4     try
 5     {
 6         byte[] postData = Encoding.UTF8.GetBytes(paramData);
 7         WebClient webClient = new WebClient();
 8         webClient.Headers.Add("Content-Type", mediaType);
 9         byte[] responseData = webClient.UploadData(new Uri(postUrl), "POST", postData);
10         result = Encoding.UTF8.GetString(responseData);
11     }
12     catch (Exception e)
13     {
14         Console.WriteLine(e);
15         result = e.Message;
16     }
17     return result;
18 }
19 
20 static string PostDataByWebRequest(string postUrl, string paramData, String mediaType)
21 {
22     string result = string.Empty;
23     Stream newStream = null;
24     StreamReader sr = null;
25     HttpWebResponse response = null;
26     try
27     {
28         byte[] byteArray = Encoding.UTF8.GetBytes(paramData);
29         HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(new Uri(postUrl));
30         webReq.Method = "POST";
31         webReq.ContentType = mediaType;
32         webReq.ContentLength = byteArray.Length;
33         newStream = webReq.GetRequestStream();
34         newStream.Write(byteArray, 0, byteArray.Length);
35         response = (HttpWebResponse)webReq.GetResponse();
36         sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
37         result = sr.ReadToEnd();
38     }
39     catch (Exception ex)
40     {
41         Console.WriteLine(ex);
42         result = ex.Message;
43     }
44     finally
45     {
46         if (sr != null)
47         {
48             sr.Close();
49         }
50         if (response != null)
51         {
52             response.Close();
53         }
54         if (newStream != null)
55         {
56             newStream.Close();
57         }
58     }
59     return result;
60 }
View Code

这二种常用的调用方式,居然全跪了,返回的结果是一堆java异常:
 java.lang.NullPointerException
        at org.apache.struts2.convention.ConventionUnknownHandler.handleUnknownActionMethod(ConventionUnknownHandler.java:423)
        at com.opensymphony.xwork2.DefaultUnknownHandlerManager.handleUnknownMethod(DefaultUnknownHandlerManager.java:96)

...

无奈百度了一圈,发现还有另一种方法,利用TcpClient调用

bubuko.com,布布扣
 1 static string PostDataByTcpClient(string postUrl, string paramData, String mediaType)
 2 {
 3     String result = String.Empty;
 4     TcpClient clientSocket = null;
 5     Stream readStream = null;
 6     try
 7     {
 8         clientSocket = new TcpClient();
 9         Uri URI = new Uri(postUrl);
10         clientSocket.Connect(URI.Host, URI.Port);
11         StringBuilder RequestHeaders = new StringBuilder();//用来保存HTML协议头部信息
12         RequestHeaders.AppendFormat("{0} {1} HTTP/1.1\r\n", "POST", URI.PathAndQuery);
13         RequestHeaders.AppendFormat("Connection:close\r\n");
14         RequestHeaders.AppendFormat("Host:{0}\r\n", URI.Host);
15         RequestHeaders.AppendFormat("Content-Type:{0}\r\n",mediaType);
16         RequestHeaders.AppendFormat("\r\n");
17         RequestHeaders.Append(paramData + "\r\n");
18         Encoding encoding = Encoding.UTF8;
19         byte[] request = encoding.GetBytes(RequestHeaders.ToString());
20         clientSocket.Client.Send(request);
21         readStream = clientSocket.GetStream();
22         StreamReader sr = new StreamReader(readStream, Encoding.UTF8);
23         result = sr.ReadToEnd();
24     }
25     catch (Exception e)
26     {
27         Console.WriteLine(e);
28         result = e.Message;
29     }
30     finally
31     {
32         if (readStream != null)
33         {
34             readStream.Close();
35         }
36         if (clientSocket != null)
37         {
38             clientSocket.Close();
39         }
40     }
41     return result;
42 }
View Code

总算调用成功了,但是由于java端是用SendRedirect在客户端重定向的,所以该方法得到的返回结果如下:

HTTP/1.1 302 Found
Server: Apache-Coyote/1.1
Location: http://localhost/struts2-rest-ex/rest/orders/230.xml
Content-Length: 0
Date: Mon, 27 Oct 2014 03:18:56 GMT
Connection: close

是一堆http头的原文,只能曲线救国,将其中的Location:后的部分(即重定向的url),取出来再次get请求,这里还有一个坑,该url返回时,把port弄丢了,正确的重定向url应该是:

http://localhost:8080/struts2-rest-ex/rest/orders/230.xml

手动把端口拼上,再次get,总算返回正确了

 

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!