发布:2021/7/13 16:43:58作者:管理员 来源:本站 浏览次数:948
背景
之前一个WebService服务用java写的,想改为.net重新开发一下,客户端的代码不变,却遇到了一个比较棘手的问题(当时客户端代码写的不够灵活),就是SOAP协议的响应格式中关于命名空间和命名空间前缀的问题。
举个最简单的例子:
java的WebService相关代码(基于Spring boot)如下:
WebService接口-IWebServiceTest.java
package com.example.soapdemo;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService
public interface IWebServiceTest {
@WebMethod
String sayHello();
}
WebService实现类-WebServiceTestImpl.java
package com.example.soapdemo;
import javax.jws.WebService;
@WebService
public class WebServiceTestImpl implements IWebServiceTest {
@Override
public String sayHello() {
return "Hello World";
}
}
服务启动类-SoapdemoApplication
package com.example.soapdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import javax.xml.ws.Endpoint;
@SpringBootApplication
public class SoapdemoApplication {
public static void main(String[] args) {
SpringApplication.run(SoapdemoApplication.class, args);
String url = "http://localhost:8081/ws";
Endpoint.publish(url, new WebServiceTestImpl());
System.out.println("发布webservice成功!");
}
}
SoapUI调用示例:
在这里插入图片描述
请求结果中会自动增加一个命名空间和命名空间前缀。
改为C#实现后代码如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Xml.Serialization;
using System.Text;
/// <summary>
/// WebService 的摘要说明
/// </summary>
[WebService]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。
// [System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService {
private System.Xml.Serialization.XmlSerializer serializer = null;
public WebService () {
//如果使用设计的组件,请取消注释以下行
//InitializeComponent();
}
[WebMethod]
public string SayHello()
{
return "Hello World";
}
}
SoapUI调用示例如下:
在这里插入图片描述
方法调用结果对比
java
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
<S:Body>
<ns2:sayHelloResponse xmlns:ns2="http://soapdemo.example.com/">
<return>Hello World</return>
</ns2:sayHelloResponse>
</S:Body>
</S:Envelope>
.net
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<SayHelloResponse xmlns="http://tempuri.org/">
<SayHelloResult>Hello World</SayHelloResult>
</SayHelloResponse>
</soap:Body>
</soap:Envelope>
解决办法
使用了一个笨方法实现把c#的WebMethod的返回结果改为象java的结果一样。
增加一个HttpMoudle,代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// AllHttpModule 的摘要说明
/// </summary>
public class AllHttpModule : IHttpModule
{
public AllHttpModule()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
public void Dispose()
{
//throw new NotImplementedException();
}
public void Init(HttpApplication context)
{
context.PreSendRequestContent += context_PreSendRequestContent;
}
private void context_PreSendRequestContent(object sender, EventArgs e)
{
HttpApplication ctx = sender as HttpApplication;
if (ctx.Request.Url.ToString().Contains("WebService.asmx"))
{
if (ctx.Request.HttpMethod == "POST")
{
string result = ctx.Context.Request.RequestContext.HttpContext.Items["cust-result"] as string; //从RequestContext中获取过滤处理后的返回结果
if (!String.IsNullOrEmpty(result))
{
ctx.Response.Clear(); //清除原返回结果
ctx.Response.Write(result); //返回新结果
}
}
}
}
}
web.config中增加配置如下
<?xml version="1.0" encoding="utf-8"?>
<!--
有关如何配置 ASP.NET 应用程序的详细信息,请访问
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<!--<httpModules>
<add name="AllHttpModule" type="AllHttpModule"/>
</httpModules>-->
</system.web>
<system.webServer>
<modules>
<add name="AllHttpModule" type="AllHttpModule"/>
</modules>
</system.webServer>
</configuration>
修改webservice代码,如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Xml.Serialization;
using System.Text;
/// <summary>
/// WebService 的摘要说明
/// </summary>
[WebService]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。
// [System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService {
private System.Xml.Serialization.XmlSerializer serializer = null;
public WebService () {
//如果使用设计的组件,请取消注释以下行
//InitializeComponent();
}
[WebMethod]
public string SayHello()
{
#region 可以根据需要对返回结果的数据做处理
StringBuilder sb = new StringBuilder();
sb.AppendLine("<S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\">");
sb.AppendLine(" <S:Body>");
sb.AppendLine(" <ns2:sayHelloResponse xmlns:ns2=\"http://soapdemo.example.com/\">");
sb.AppendLine(" <return>Hello World</return>");
sb.AppendLine(" </ns2:sayHelloResponse>");
sb.AppendLine(" </S:Body>");
sb.AppendLine("</S:Envelope>");
//把要返回的内容放入RequestContext
HttpContext.Current.Request.RequestContext.HttpContext.Items["cust-result"] = sb.ToString();
#endregion
return "Hello World";
}
}
重新使用SoapUI调用如下:
在这里插入图片描述