1

ドキュメントに従って、Google API を使用してカレンダーを作成しようとしています。クライアント ライブラリの使用を避け、カスタム Web リクエストを介して API とのすべての通信を行うようにしていますが、これまでのところうまく機能していますが、この特定のライブラリでは「解析エラー」に苦しんでいます。

クライアント ライブラリ ( service.calendars().insert(...) )を使用するソリューションを参照しないでください。

これは私のコードの単純化されたバージョンです (まだ動作していません):

var url = string.Format
(
    "https://www.googleapis.com/calendar/v3/calendars?key={0}",
    application.Key
);

var httpWebRequest = HttpWebRequest.Create(url) as HttpWebRequest;
httpWebRequest.Headers["Authorization"] = 
    string.Format("Bearer {0}", user.AccessToken.Token);                    
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "application/json";
httpWebRequest.CookieContainer = new CookieContainer();

// Obviously the real code will serialize an object in our system.
// I'm using a dummy request for now,
// just to make sure that the problem is not the serialization.
var requestText =
      "{" + Environment.NewLine
    + "\"summary\": \"test123\"" + Environment.NewLine
    + "}" + Environment.NewLine
    ;

using (var stream = httpWebRequest.GetRequestStream())
using (var streamWriter = new System.IO.StreamWriter(stream))
{
    streamWriter.Write(System.Text.Encoding.UTF8.GetBytes(requestText));
}

// GetSafeResponse() is just an extension that catches the WebException (if any)
// and returns the WebException.Response instead of crashing the program.
var httpWebResponse = httpWebRequest.GetSafeResponse();

ご覧のとおり、シリアル化されたオブジェクトを送信することは今のところあきらめており、非常に単純なダミーのリクエストで動作させようとしています。

{
"summary": "test123"
}

それでも、応答はまだ次のとおりです。

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "parseError",
    "message": "Parse Error"
   }
  ],
  "code": 400,
  "message": "Parse Error"
 }
}

accessToken は有効で期限切れではありません。アプリケーション キーは正しいです。

私は何が間違っているか、欠けていますか?

前もって感謝します、

4

2 に答える 2

2

これで問題が解決するかどうかはわかりませんが、注意すべき点がいくつかあります。この場合、Environment.NewLineを使用しないでください。コードがWindows、Mac、またはLinuxで実行されている場合、ネットワークトラフィックは変更されません。Http1.1にはCRLFが必要です

投稿の本文をUTF-8としてエンコードしています。はい、使用しているエンコードをサーバーに通知していません。すべての文字は低ビットASCIIであるため、これは重要ではありませんが、完全を期すために、コンテンツタイプは次のようになります。

 httpWebRequest.ContentType = "application/json ; charset=UTF-8";

コードに問題がないことを除けば、透過的なエコープロキシ(Charlesまたはfiddler)を接続して、要求がネットワーク上でどのように見えるかを確認できるようにすることをお勧めします。彼らが送っているカレンダーの例から

リクエスト

POST https://www.googleapis.com/calendar/v3/calendars?key={YOUR_API_KEY}

Content-Type:  application/json
Authorization:  Bearer ya29.AHES6ZR3F6ByTg1eKVkjegKyWIukodK8KGSzY-ea1miGKpc
X-JavaScript-User-Agent:  Google APIs Explorer

{
 "summary": "Test Calendar"
}

応答

200 OK

- Show headers -

{

 "kind": "calendar#calendar",
 "etag": "\"NybCyMgjkLQM6Il-p8A5652MtaE/ldoGyKD2MdBs__AsDbQ2rHLfMpk\"",
 "id": "google.com_gqua79l34qk8v30bot94celnq8@group.calendar.google.com",
 "summary": "Test Calendar"
}

それが役に立たないかもしれないことに注意して、それが役立つことを願っています。

于 2012-12-10T12:55:26.630 に答える
1

私はそれを理解し、それを機能させました!

David の提案はそれ自体では解決策にはなりませんでしたが、彼はパケット スニファーを使用するように指示してくれました (最終的に Wireshark を使用しましたが、それは重要ではありません)。

結局のところ、私の馬鹿げたコードには 2 つのエラーがありました。それは私を赤面させるほど明白で、もう1つは少しよこしまです。

初めに、

using (var streamWriter = new StreamWriter(stream))
{
    streamWriter.Write(Encoding.UTF8.GetBytes(requestText));
}

もちろんあるべき

using (var streamWriter = new StreamWriter(stream, Encoding.UTF8))
{
    streamWriter.Write(requestText);
}

streamWriter.Write はパラメーターに対して ToString() を実行し、Byte[].ToString() は「System.Byte[]」を返すだけです。恥ずかしい!

次に、デフォルトの UTF8 エンコーディングでは、バイト オーダー マーク \357\273\277 が追加されます。これにより、Google に関する限り、コンテンツが無効になります。この問題を解決する方法は、stackoverflowで見つけました。

したがって、これに苦労している人にとって、これが最終的な解決策です。

var url = string.Format
(
    "https://www.googleapis.com/calendar/v3/calendars?key={0}",
    application.Key
);

var httpWebRequest = HttpWebRequest.Create(url) as HttpWebRequest;
httpWebRequest.Headers["Authorization"] = 
    string.Format("Bearer {0}", user.AccessToken.Token);                    
httpWebRequest.Method = "POST";
// added the character set to the content-type as per David's suggestion
httpWebRequest.ContentType = "application/json; charset=UTF-8";
httpWebRequest.CookieContainer = new CookieContainer();

// replaced Environment.Newline by CRLF as per David's suggestion
var requestText = string.Join
(
    "\r\n",
    "{",
    " \"summary\": \"Test Calendar 123\"",
    "}"
);

using (var stream = httpWebRequest.GetRequestStream())
// replaced Encoding.UTF8 by new UTF8Encoding(false) to avoid the byte order mark
using (var streamWriter = new StreamWriter(stream, new UTF8Encoding(false)))
{
    streamWriter.Write(requestText);
}

これが誰かを助けることを願っています!

于 2013-01-07T12:38:50.153 に答える