2011-07-09 51 views
3

如果您運行此代碼,它將引發WebException。內部異常是「無法爲不寫入數據的操作設置Content-Length或Chunked Encoding」。我不明白問題的本質。任何人都可以將光投射到這個黑暗的角落?爲什麼此例外聲明代碼不寫入數據?

using System.Diagnostics; 
using System.Net; 
using System.Text; 

namespace sandpit 
{ 
    static class Program 
    { 
    static void Main() 
    { 
     string INITIAL_URI = "http://docs.live.net/SkyDocsService.svc"; 
     string SOAP = "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body><GetWebAccountInfoRequest xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"http://schemas.microsoft.com/clouddocuments\"><BaseRequest><ClientAppId>SkyDrive Service Client</ClientAppId><Market>en-US</Market><SkyDocsServiceVersion>v1.0</SkyDocsServiceVersion></BaseRequest><GetReadWriteLibrariesOnly>false</GetReadWriteLibrariesOnly></GetWebAccountInfoRequest></s:Body></s:Envelope>"; 
     using (WebClient wc = new WebClient()) 
     { 
     wc.Encoding = Encoding.UTF8; 
     wc.Headers["SOAPAction"] = "GetWebAccountInfo"; 
     wc.Headers["Accept-Language"] = "en-US"; 
     wc.Headers["Accept"] = "text/xml"; 
     wc.Headers["Content-Type"] = "text/xml; charset=utf-8"; 
     string response = wc.UploadString(INITIAL_URI, SOAP); 
     Debug.WriteLine(response); 
     } 
    } 
    } 
} 
+0

在這種情況下, false是什麼意思? – ChrisF

+0

GetReadWriteLibraries是本質上是查詢的過濾器值。這不相關;如果live.com不喜歡我的查詢,我會收到回覆說,所以不是發送barf。漢斯,我會嘗試一下魔法重啓的咒語,看看它是否會讓我的量子位回到更理智的世界。 –

+0

我注意到我只能使用,因爲我真的只在響應頭之後。 –

回答

5

問題是由網絡服務器重定向。

不幸的是,你必須繼承WebClient的子類來解決這個問題。這比看起來更難,因爲Silverlight(任何味道)不喜歡這個,並拋出繼承相關的異常,直到你猜你需要重寫ctor並將它歸類爲SecurityCritical。

public class WebClient2 : WebClient 
{ 
    [SecurityCritical] 
    public WebClient2() : base() { } 
    protected override WebRequest GetWebRequest(System.Uri address) 
    { 
    var wr = base.GetWebRequest(address); 
    if (wr is HttpWebRequest) 
     (wr as HttpWebRequest).AllowAutoRedirect = false; 
    return wr; 
    } 
} 

如果您想進一步探索,可以在WebClient2上展示AllowAutoRedirect屬性並將其掛鉤。

+0

謝謝 - 這是完美的。 –

2

如何使用這個SkyDrive client,而不是手工編寫的SOAP請求:

var client = new SkyDriveServiceClient(); 
client.LogOn("user", "pwd"); 
var info = client.GetWebAccountInfo(); 
Console.WriteLine(info.Title); 

似乎更容易我。但是如果你真的堅持使用WebClient並手動處理協議,你可以看到Fiddler使用.NET客戶端通過線路交換什麼並複製它。我認爲在使用WebClient進行身份驗證時,您可能會錯過爲您的請求提供憑據。

如果你看看在網絡級別的跟蹤,你會看到SyDrive服務器需要Passport身份驗證,你將不得不手動處理,如果你決定去與WebClient路線可能是相當大量的工作:

Location: https://login.live.com/login.srf?wa=wsignin1.0&rpsnv=11&ct=1310230173&rver=6.1.6206.0&wp=MBI&wreply=http:%2F%2Fdocs.live.net:101%2FSkyDocsService.svc&lc=1033&id=250206 
WWW-Authenticate: Passport1.4 ct=1310230292,rver=6.1.6206.0,wp=MBI,lc=1033,id=250206 
+0

因爲SkyDriveApiClient甚至不能與VS2010一起使用,遠不如WP7。 –

+0

出於興趣,我從* SkyDriveApiClient中解除了肥皂*。 –

+0

@Peter Wone,當你說它不適用於VS2010時,這很奇怪,因爲當我測試它時,我的答案中的例子工作得很好。對於WP7我同意。移植它可能需要一些修改。另外,如果您從客戶端提取了此SOAP請求,您還應該*提取執行Passport身份驗證的部分。 SkyDrive沒有官方API,因此作爲開發者,我們應該做我們所擁有的:-) –

1

在我的情況的問題由同一個IIS服務器6重定向所做的,因爲會話狀態模式設置爲「自動檢測」,而不是「使用Cookie」。每個URL請求都被重定向爲'AspxAutoDetectCookieSupport = 1'。