我有一个简单的应用程序,通过SOAP获取数据记录。 SOAP Web服务通过“服务引用”添加到项目中。通话工作正常。当数据为参考代码存储到0000-00-00
- 对象的日期保存值DateTime
时,我遇到了问题。 DateTime
类已经预见到0001-0-01
的最小值,这最终会在反序列化SOAP调用的响应时导致错误。
执行以通过SOAP提取数据的代码如下:
TopixSOAP.TOPIXRPCClient soap = new TopixSOAP.TOPIXRPCClient();
soap.GetProjekt(out error_code, out start_date, out end_date, instance, user, passwd, project_number);
所以我向SOAP调用提供了必要的信息,如果start_date和end_date是=>它会表现良好。 0001-01-01
。但由于数据有时包含0000-00-00
日期的值,因此应用程序在将值反序列化为DateTime
对象时会自然崩溃。
我试图将所有out参数包装到一个名为TopixProject的单独类中:
public class TOPIXProject
{
public TOPIXProject()
{
}
public string ErrorCode
{
get
{
return ErrorCode;
}
set
{
ErrorCode = value;
}
}
public DateTime StartDate
{
get
{
return StartDate;
}
set
{
StartDate = DateTime.MinValue;
}
}
public DateTime EndDate
{
get
{
return EndDate;
}
set
{
EndDate = DateTime.MinValue;
}
}
这里是修改过的电话:
soap.SOAP_GetProject(out p.ErrorCode, out p.StartDate, out p.EndDate, instance, user, passwd, project_number);
该类应将值设置为DateTime.MinValue
,以便我不再收到错误。它不能按我的意图工作:类TOPIXProject
的成员不能用作函数的out或ref参数。
如果我提供我在SOAP调用之前声明的“原始”变量,那么如果日期在0001-01-01
类定义的有效范围(=> DateTime
)中,它就会起作用:< / p>
string error_code = "";
DateTime start_date, end_date;
soap.GetProjekt(out error_code, out start_date, out end_date, instance, user, passwd, project_number);
但我有很多数据记录,其中日期为0000-00-00
并且无法更改(它是无法终止项目的内部标记)。
那么我需要做些什么来获得有效的SOAP响应呢?
0000-00-00
我想获得DateTime.MinValue
我现在使用来自服务引用的部分SOAP调用(基本上所有没有传递日期的地方)。其余的我实现了一个SOAPHelper类,它提供对SOAP端点的必要调用,并主要返回字符串或XML。代码示例here
答案 0 :(得分:1)
您最好的选择是手动生成客户端(或使用Svcutil工具) 并修改合同以接收消息,而不是datetime。这样您就可以与消息本身进行交互并处理无效的日期时间值。关于在msdn上使用here更多关于Using Message Contracts的功能有一篇很好的帖子。
答案 1 :(得分:0)
我们想出了一个不同的解决方案:由于Web服务并不是在考虑XML中的xsi:type属性,我们认为它是代理流量和操纵WSDL文件以及进出XML消息的最简单方法。
因此我们编写了一个通过$ _GET变量控制的PHP脚本:
这不是最干净的方式,而是规避问题的唯一方法。
<?php
/** A simple HTTP/SOAP proxy server with response manipulation
*
* @author: Dipl.-Ing. (FH) Tom Gottschalk, tom.gottschalk@gmail.com
*
* Usage:
* 1. proxy.php?wsdl:
* - gets the original WSDL file content from the SOAP server
* - manipulates the types `date` and `time` to `string`
* - manipulates the SOAP service URI binding to `proxy.php?proxy`
* 2. proxy.php?proxy
* - forwards the original HTTP request to the SOAP server
* - fetches the HTTP response
* - manipulates the types `date` and `time` to `string` in the HTTP response
* - returns the manipulated SOAP (HTTP) response
*/
// suppress deprecated and strict standard messages
error_reporting(E_ALL & ~E_STRICT & ~E_NOTICE & ~E_DEPRECATED);
// what to do: serve WSDL or work as Proxy server
if(array_key_exists("proxy", $_GET)) {
proxy();
}
elseif(array_key_exists("wsdl", $_GET))
{
wsdl();
}
// manipulate data types in the XML WSDL or SOAP response
function manipulate($xml)
{
$xml = str_replace('type="xsd:date"', 'type="xsd:string"', $xml);
$xml = str_replace('type="xsd:time"', 'type="xsd:string"', $xml);
return $xml;
}
function proxy()
{
// fetch all HTTP request headers from the current request
$headers = apache_request_headers();
// get all raw POST data
$rawPostData = file_get_contents("php://input"); # alternatively: $HTTP_RAW_POST_DATA
// URI to request
$uri = "http://<server:port>/INCOMING_PORT/";
// do request and get response
$request = new HttpRequest($uri, HttpRequest::METH_POST);
$request->addHeaders($headers);
$request->setRawPostData($rawPostData);
$response = $request->send();
// send headers
foreach($response->getHeaders() as $key => $value) {
header(sprintf("%s: %s", $key, $value));
}
// edit response body
$body = $response->getBody();
$body = manipulate($body);
// return response
echo $body;
}
function wsdl()
{
// get original WSDL file
$uri = "http://<server:port>/WSDL/";
$wsdl = file_get_contents($uri);
// manipulate data types
$wsdl = manipulate($wsdl);
// manipulate SOAP service URI binding
$wsdl = str_replace('http://<server:port>/INCOMING_PORT/', 'http://url_to_php_proxy_script/proxy.php?proxy', $wsdl);
// return result
header("Content-Type: text/xml");
echo $wsdl;
}
?>
TL,DR:我们使用了代理的WSDL,因为服务器没有注意到xsi:type。