0

我有一个通过 SOAP 获取数据记录的简单应用程序。SOAP Web 服务是通过“服务引用”添加到项目中的。通话工作正常。0000-00-00当数据保存参考代码将存储到DateTime-object中的日期值时,我只是遇到了问题。该类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

我试图将所有输出参数包装到一个名为 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

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
  • 或者我可以告诉服务引用将所有内容解释为字符串吗?(因为服务引用自己构建代码并尝试将 xsd:date 类型解析为 DateTime,这在我的情况下非常糟糕)

编辑:

我现在使用来自服务引用的部分 SOAP 调用(基本上所有没有传回日期的地方)。对于其余部分,我实现了一个 SOAPHelper 类,该类提供对 SOAP 端点的必要调用,并主要返回字符串或 XML。代码示例在这里

4

2 回答 2

1

您最好的选择是手动生成客户端(或使用 Svcutil工具)并修改合同以接收消息,而不是日期时间。这样您就可以与消息本身交互并处理无效的日期时间值。这里有一篇关于使用该功能的好文章,更多关于在 msdn 上使用消息合同。

于 2013-06-03T11:23:58.583 回答
0

我们提出了一个不同的解决方案:由于 Web 服务不关心 XML 中的 xsi:type 属性,我们认为这将是代理流量和操作 WSDL 文件以及传入和传出 XML 消息的最简单方法。

因此,我们编写了一个通过 $_GET 变量控制的 PHP 脚本:

  • 返回 WSDL 文件(操纵)
  • 过滤 xml 内容并替换某些字符串,因此我们将所有 xsi:date 节点作为 xsi:string 节点

这不是最干净的方法,而是规避问题的唯一方法。

<?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。

于 2013-06-11T14:48:29.443 回答