Perl / Soap lite:“服务器无法处理请求。对象引用未设置为对象的实例”

时间:2012-05-25 09:38:57

标签: web-services perl soap soaplite

我正在尝试使用已经存在的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 个答案:

答案 0 :(得分: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;

<强> [UPDATE]

根据您发布的信息,我建议您执行直接HTTP::Request代码,而不使用库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;
}

答案 1 :(得分:1)

  

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

     

经过一些研究,我得到的印象是错误发生在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时的默认地址。这是我在官方例子中可以看到的,但也许我不应该使用它?

这是一个疯狂的猜测,但是a user in another discussion got a NullReferenceException because he didn't supply the correct URL for the SOAPAction header。这是你可以检查的东西。找出SOAPAction标题应该是什么,并确保相应地设置它。如果您可以访问有助于调试的服务器软件,当然,因为最终错误显然是服务器端。

答案 2 :(得分:1)

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

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

如果需要,进一步备份您的案例,这是Web服务代码中的缺陷,通过使用SOAPUi

重现错误,消除Perl客户端是问题的根本原因

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

答案 3 :(得分:0)

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

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

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

另外,请使用严格;使用警告;

将shebang线移到顶部(#!perl)

启用调试:

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

确保系统中安装了LWP :: Authen :: Ntlm。

目前您正在收到HTTP / 1.1 500内部服务器错误&#39;错误。这意味着服务器代码死了,无法正常工作。它应该向您发送一些有意义的错误消息......

此致