8

我正在尝试使用已经存在并且运行良好的 Web 服务。在阅读了许多教程和示例之后,我终于设法从服务器获得了答案:

服务器无法处理请求。你调用的对象是空的

WS 只允许您从 NT 登录中获取 ID(一个字符串参数,一个字符串答案)。

这是我的 perl 脚本:

#!perl -w
use strict;
use warnings;

use LWP::UserAgent; 
use SOAP::Lite on_action => sub { "$_[0]$_[1]"; };
use LWP::Debug; LWP::Debug::level('+'); SOAP::Lite->import(+trace => 'all');
#use SOAP::Lite  +trace =>  'debug';
#sub SOAP::Transport::HTTP::Client::get_basic_credentials { return ('user' => 'pwd') };
use Data::Dumper;

my $var = SOAP::Data->new(name => 'NTLogin', value => "1234", type =>'s:string');

my $resultLogin = SOAP::Lite
  -> uri('http://xxxxx')
  -> proxy('http://yyyyy/zzzzz/directory.asmx')
  -> on_action( sub { join '/', @_ } )
  -> GetUIDFromNTLogin($var);

print "lets test it...\n\n";

  print $resultLogin;
  print "\nresult():\n";
  print $resultLogin->result();

这是输出:

Launching NT to UID conversion
SOAP::Data::new: ()
SOAP::Lite::new: ()
LWP::UserAgent::new: ()
SOAP::Transport::HTTP::Client::new: ()
SOAP::Lite::call: ()
SOAP::Serializer::envelope: ()
SOAP::Serializer::envelope: GetUIDFromNTLogin SOAP::Data=HASH(0x______)
SOAP::Data::new: ()
SOAP::Data::new: ()
SOAP::Data::new: ()
SOAP::Data::new: ()
SOAP::Data::new: ()
SOAP::Transport::HTTP::Client::send_receive: HTTP::Request=HASH(0x______)
SOAP::Transport::HTTP::Client::send_receive: POST http://yyyyy/zzzzz/directory.asmx
Accept: text/xml
Accept: multipart/*
Content-Length: 534
Content-Type: text/xml; charset=utf-8
SOAPAction: http://tempuri.org/GetUIDFromNTLogin

<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:xsi="http://www.w
3.org/1999/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/e
ncoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="
http://www.w3.org/1999/XMLSchema" SOAP-ENV:encodingStyle="http://schemas.xmlsoap
.org/soap/encoding/"><SOAP-ENV:Body><namesp1:GetUIDFromNTLogin xmlns:namesp1="ht
tp://tempuri.org"><NTLogin xsi:type="s:string">1234</NTLogin></namesp1:
GetUIDFromNTLogin></SOAP-ENV:Body></SOAP-ENV:Envelope>
LWP::UserAgent::request: ()
LWP::UserAgent::send_request: POST http://yyyyy/zzzzz/directory.asmx
LWP::UserAgent::_need_proxy: Not proxied
LWP::Protocol::http::request: ()
LWP::Protocol::collect: read 441 bytes
LWP::UserAgent::request: Simple response: Internal Server Error
SOAP::Transport::HTTP::Client::send_receive: HTTP::Response=HASH(0x______)
SOAP::Transport::HTTP::Client::send_receive: HTTP/1.1 500 Internal Server Error
Cache-Control: private
Date: Mon, 04 Jun 2012 15:54:47 GMT
Server: Microsoft-IIS/6.0
Content-Length: 441
Content-Type: text/xml; charset=utf-8
Client-Date: Mon, 04 Jun 2012 15:54:47 GMT
Client-Peer: 10.94.61.146:80
Client-Response-Num: 1
Set-Cookie: BIGipServer_____________-http=_________________; path=/
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET

<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.
xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance
" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><faultcode
>soap:Server</faultcode><faultstring>Server was unable to process request. ---&g
t; Object reference not set to an instance of an object.</faultstring><detail />
</soap:Fault></soap:Body></soap:Envelope>
SOAP::Deserializer::deserialize: ()
SOAP::Parser::decode: ()
SOAP::SOM::new: ()
SOAP::Lite::DESTROY: ()
SOAP::Deserializer::DESTROY: ()
SOAP::Transport::DESTROY: ()
SOAP::Transport::HTTP::Client::DESTROY: ()
SOAP::Serializer::DESTROY: ()
SOAP::Data::DESTROY: ()
SOAP::Data::DESTROY: ()
SOAP::Data::DESTROY: ()
SOAP::Data::DESTROY: ()
SOAP::Data::DESTROY: ()
lets test it...

1
result():
SOAP::SOM::DESTROY: ()
SOAP::Data::DESTROY: ()
SOAP::Parser::DESTROY: ()
SOAP::Transport::DESTROY: ()
SOAP::Serializer::DESTROY: ()
SOAP::Deserializer::DESTROY: ()
SOAP::Lite::DESTROY: ()
Press any key to continue . . .

经过一些研究后,我的印象是错误出在 WS 服务器端。然而 WS 似乎工作得很好,所以我猜我的 Perl 脚本有问题,但我不知道是什么......

任何帮助将不胜感激!

谢谢,

[更新#1]

以下是 WS 页面给出的示例:

要求

POST /zzzzz/directory.asmx HTTP/1.1
Host: yyyyy
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://xxxxx/GetUIDFromNTLogin"

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetUIDFromNTLogin xmlns="http://xxxxx/">
      <NTLogin>string</NTLogin>
    </GetUIDFromNTLogin>
  </soap:Body>
</soap:Envelope>

回复

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <GetUIDFromNTLoginResponse xmlns="http://xxxxx/">
      <GetUIDFromNTLoginResult>string</GetUIDFromNTLoginResult>
    </GetUIDFromNTLoginResponse>
  </soap:Body>
</soap:Envelope>

[更新#2]

这是 user1215106 建议的输出:

<HTML>
<HEAD><TITLE>An Error Occurred</TITLE></HEAD>
<BODY>
<H1>An Error Occurred</H1>
400 Bad Request
</BODY>
</HTML>
4

4 回答 4

3

请测试下面的代码,让我们知道你的经验和你得到的输出。

#!perl -w 

use strict; 
use warnings;
use LWP::UserAgent; 
use SOAP::Lite

use LWP::Debug; LWP::Debug::level('+'); SOAP::Lite->import(+trace => 'all');

print SOAP::Lite 
  -> uri('http://xxxxx') 
  -> proxy('http://yyyyy/zzzzz/directory.asmx') 
  -> on_action(sub { sprintf '"%s"', shift })
  -> on_fault(sub {
       my($soap, $res) = @_; 
       die ref $res ? $res->faultstring : $soap->transport->status, "\n";
     })
  -> GetUIDFromNTLogin(SOAP::Data->type('string')->name('NTLogin')->value(1234))
  -> result;

[更新]

根据您发布的信息,我建议您执行直接HTTP::Request代码,而不使用 library SOAP::Lite。使用您拥有的确切信息修改以下代码:

#!perl -w          

use strict;          
use warnings;

use LWP::UserAgent;
use HTTP::Request;

my $message = '<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/1999/XMLSchema" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><namesp1:GetUIDFromNTLogin xmlns:namesp1="http://tempuri.org"><NTLogin xsi:type="s:string">1234</NTLogin></namesp1: GetUIDFromNTLogin></SOAP-ENV:Body></SOAP-ENV:Envelope>';

my $userAgent = LWP::UserAgent->new();
my $request = HTTP::Request->new(POST => 'http://...');
$request->header(SOAPAction => '"http://tempuri.org/GetUIDFromNTLogin"');
$request->content($message);
$request->content_type("text/xml; charset=utf-8");

my $response = $userAgent->request($request);

if ($response->code == 200) {
  print $response->as_string;
}
else {
  print $response->error_as_HTML;
}
于 2012-06-03T19:48:09.323 回答
1

我们都同意HTTP 500 服务器错误表明服务器端出现错误。

因此,第一个调用端口是从 WebService 应用程序中检索完整的调试日志,并将它们发送给该 WebService 的开发人员/供应商。将此报告为他们实施中的错误。这里不容忍废话。即使您的 Perl 客户端将错误(或丢失)的数据传递给 Web 服务,它们也不应响应 HTTP 500 服务器错误。那是一个错误。错误消息应该围绕有缺陷的客户端请求,并给出一条错误消息,应该是这样的:“啊,看这里。你给我发的是什么?我不是在我可爱的文档中告诉你的吗? NTUser 必须存在于系统上吗?(或任何问题)再次发送该请求,但这次将它与我可以使用的真实数据一起发送给我。HTTP 400 范围

如果需要,为了进一步备份您的案例,即这是 Web 服务代码中的缺陷,通过使用SOAPUi重现错误来消除您的 Perl 客户端作为问题的根本原因

然后,您可以与 Web 服务开发人员共享 Soap UI 项目,它应该可以帮助他们轻松找到这个错误。

于 2012-06-06T01:02:35.473 回答
1

“服务器无法处理请求。对象引用未设置为对象的实例”</p>

经过一些研究后,我的印象是错误出在 WS 服务器端。然而 WS 似乎工作得很好,所以我猜我的 Perl 脚本有问题,但我不知道是什么......

这绝对是服务器端错误。这是由于 .NET 服务器代码中的一个可以说是错误的原因。这是一个System.NullReferenceException,易于复制:

D:\temp :: more nr.cs
class Program {
        static void Main() {
                object o = null;
                string s = o.ToString();
        }
}

D:\temp :: csc /nologo nr.cs

D:\temp :: nr.exe

Unbehandelte Ausnahme: System.NullReferenceException:
Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.
   bei Program.Main()

这与您的 SOAP 客户端没有任何关系,只是客户端通过引发错误消息来暴露错误。

在对另一条回复的评论中,您写道:

顺便说一句,xxxxx 是 tempuri.org,我猜它是您编写 .Net WS 时的默认地址。无论如何,这是我在官方示例中可以看到的,但也许我不应该使用它?

这是一个疯狂的猜测,但另一个讨论中的用户得到了一个NullReferenceException,因为他没有为SOAPActionheader提供正确的 URL 。这是你可以检查的。找出SOAPAction标题应该是什么,并确保您进行了相应的设置。当然,如果您可以访问服务器端发生的事情,这将有助于调试,因为最终错误显然是服务器端的。

于 2012-06-05T07:03:17.300 回答
0

我发现了这个:http ://www.perlmonks.org/?node_id=719987

这家伙在他们的代码中添加了这一行:

sub SOAP::Transport::HTTP::Client::get_basic_credentials { 
    return ('user' => 'password') 
};

另外,请使用 use strict;使用警告;

移动顶部的 shebang 行 (#!perl)

启用调试:

use LWP::UserAgent;
use LWP::Debug;
LWP::Debug::level('+');
SOAP::Lite->import(+trace => 'all');

确保 LWP::Authen::Ntlm 已安装在您的系统中。

目前您收到“HTTP/1.1 500 Internal Server Error”错误。这意味着服务器代码死了,不能正常工作。它应该向您发送一些有意义的错误消息...

问候,

于 2012-06-01T09:43:55.543 回答