2014-04-07 3 views
1

모노를 사용하여 우분투에서 .NET 프로그램을 실행하려고합니다.우분투의 Mono와 함께 HttpWebResponse를 사용하는 빈 응답 데이터

프로그램은 원격 서버 API에 연결하고 XML 문자열을 응답으로받습니다. 다음은이 작업을 담당하는 함수의 단순화 된 버전입니다.

using System.Net; 

static string GetProducts(string clientID, string apiKey, string url) 
    { 
     HttpWebRequest req = WebRequest.Create(url) as HttpWebRequest; 
     req.Credentials = new NetworkCredential(clientID, apiKey); 
     req.ContentType = "application/x-www-form-urlencoded"; 

     string result = string.Empty; 

     using (HttpWebResponse resp = req.GetResponse() as HttpWebResponse) 
     { 
      StreamReader reader = new StreamReader(resp.GetResponseStream()); 
      result = reader.ReadToEnd(); 
     } 

     return result; 
    } 

내 Windows 8.1 컴퓨터에서 완벽하게 작동합니다. 하지만 내 목표는 우분투 VPS에서 실행하는 것입니다. 모노를 사용하고 있습니다. 프로그램이 실행되지만 다운로드 된 XML 문자열을 구문 분석 할 때 예외로 중지됩니다.

[ERROR] FATAL UNHANDLED EXCEPTION: System.Xml.XmlException: Document element did not appear. Line 1, position 1. 

약간의 조사를 통해 프로그램이 실제로 XML에서 응답을 얻지 못하고 대신 빈 문자열을 생성한다는 것을 알았습니다. 연결 오류가 발생하지 않으므로 이상합니다.

모노와 우분투에 대한 이전 경험이 있지만 이전에는 이런 문제가 없었습니다.

우분투 서버 또는 모노와 관련이 있습니까? 아니면 코드 자체에 있습니까?

이 문제에 대한 의견이 있으십니까?

+0

우분투 트래픽을 분석 한 후 Windows의 Fiddler에서 볼 수있는 트래픽과 비교해보십시오. 어쩌면 리눅스에서 명시 적으로 설정해야 할 수도있는 윈도우에 의존하는 기본 헤더/설정이있을 수 있습니다. – cgotberg

+0

@cgotberg 몇 가지 테스트를 한 후에 보낸 헤더가 Windows와 우분투에서 조금 다릅니다. 윈도우'콘텐츠 형식에 : 우분투'콘텐츠 형식에 기본 MjY2MjQyOmFmNDhlZjUwZDFiM2Y5MWRiZmE5ZTAwYTNjM2ZhNjg3' : 응용 프로그램/ 인증을 X-WWW-형태-urlencoded를 응용 프로그램/x-www-form-urlencoded를 연결 : 계속 - alive' 의 모습을 우분투는 인증 라인이 없습니다. 그러나 나는 Windows 어디서나 직접 설정하지 않습니다. 이것이 중요 할 수 있습니까? – Aceonace

+0

문제 일 수 있습니다. 이 행은 인증을 설정하고 우분투에서 작동하지 않는 것으로 보입니다. req.Credentials = 새로운 NetworkCredential (clientID, apiKey); 불행히도 나는 왜 그런 경우가 될지에 대한 경험이 없습니다. 이 솔루션과 같은 것을 시도해 볼 수 있습니다. http://stackoverflow.com/a/19851527/1181408 – cgotberg

답변

1

마침내 문제가있는 곳과 다소 해결책을 찾았습니다. 우선, Perl에 간단한 문제 코드를 써서 문제가 어디에 있는지를 살펴 보았다.

#!/usr/bin/perl 
use LWP::UserAgent 6; 
my $ClientID = "id"; 
my $APIKey = "key"; 
my $ua = LWP::UserAgent->new(ssl_opts => { verify_hostname => 0 }); 
my $req = HTTP::Request->new(GET => 'https://server.url'); 
$req->authorization_basic($ClientID, $APIKey); 
my $res = $ua->request($req); 
print "Status: " . $res->status_line . "\n"; 
print "Contents: ". $res->content . "\n"; 

Perl 코드가 작동하여 요청 상태 및 출력 내용을 확인했습니다. 하지만 그것을 작동 시키려면 서버 보안 검사 LWP::UserAgent->new(ssl_opts => { verify_hostname => 0 })을 비활성화해야합니다. 그렇지 않으면 작동하지 않습니다. 그 생각이 들었어. 어쩌면 그 이유는 내 C# 코드에서 응답 데이터를 얻지 못했습니다. 실패한 보안 검사 때문입니다. 추가 테스트를 거친 후 실제로 확인한 결과입니다. 왜 ssl 보안 검사가 실패했는지 찾을 수 없었기 때문에 Perl 코드에서했던 것처럼 검사를 완전히 무시하기로 결정했습니다. 나는 조금 연구를했고이 스레드가 How to ignore SSL Certificate check 인 것을 발견했다. 방금이 코드를 제 기능에 추가하고 작동 시켰습니다.

System.Net.ServicePointManager.ServerCertificateValidationCallback += 
delegate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, 
        System.Security.Cryptography.X509Certificates.X509Chain chain, 
        System.Net.Security.SslPolicyErrors sslPolicyErrors) 
{ 
    return true; // **** Always accept 
}; 

저는 왜 리눅스에서 인증서 확인이 실패하는지 알지 못합니다. 그러나 최소한 수표를 무시함으로써 Windows와 Linux 모두에서 작동합니다. 다음은 최종 코드입니다.

using System.Net; 

static string GetProducts(string clientID, string apiKey, string url) 
{ 
    HttpWebRequest req = WebRequest.Create(url) as HttpWebRequest; 
    req.Credentials = new NetworkCredential(clientID, apiKey); 
    req.ContentType = "application/x-www-form-urlencoded"; 

    System.Net.ServicePointManager.ServerCertificateValidationCallback += 
    delegate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, 
        System.Security.Cryptography.X509Certificates.X509Chain chain, 
        System.Net.Security.SslPolicyErrors sslPolicyErrors) 
    { 
     return true; 
    }; 

    string result = string.Empty; 

    using (HttpWebResponse resp = req.GetResponse() as HttpWebResponse) 
    { 
     StreamReader reader = new StreamReader(resp.GetResponseStream()); 
     result = reader.ReadToEnd(); 
    } 

    return result; 
}