【问题标题】:Google API -> Create a new Calendar -> Parse ErrorGoogle API -> 创建一个新日历 -> 解析错误
【发布时间】:2012-11-16 02:37:00
【问题描述】:

我正在尝试按照documentation 通过 Google API 创建日历。我试图避免使用客户端库并通过自定义 webrequests 与 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有效且未过期,应用密钥正确。

我做错了什么或错过了什么?

提前致谢,

【问题讨论】:

  • 您好,只是出于兴趣,您为什么反对使用客户端库?
  • 因为它只是为已经相当复杂的项目增加了另一层复杂性,因为我们必须包含不受我们控制的代码,并且当它出现错误时我们可能无法修复自己/ 或中断,因为根据定义,REST 服务应该简单明了。我们的代码也使用相同的严肃方法与 FB 和 Twitter 同步,这一点都不难,除非像这种情况下,文档是错误的。
  • 感谢您的回复:)

标签: c# google-api google-calendar-api


【解决方案1】:

我不确定这是否能解决您的问题,但有几点需要注意 在这种情况下,不要使用 Environment.NewLine,如果您的代码在 Windows、Mac 或 Linux 上运行,您的网络流量不应该改变。 Http 1.1 需要 CRLF

您将帖子的正文编码为 UTF-8 是的,您没有告诉服务器您正在使用哪种编码。您所有的字符都是低位 ASCII,所以这无关紧要,但为了完整性,您的内容类型应该是

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

除此之外我看不到您的代码有问题,最好附加一个透明的回显代理(Charles 或 fiddler),这样您就可以通过网络看到您的请求是什么样的。来自日历examples 他们正在发送

请求

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"
}

希望有所帮助,但可能不会。

【讨论】:

  • 感谢您的建议。这个项目已经暂停了一段时间,但我会在几天后回复它并发布更新。
【解决方案2】:

我想通了,让它工作了!

虽然 David 的建议本身并不能解决问题,但他告诉我使用数据包嗅探器(我最终使用了 Wireshark,但这不是重点),让我走上了正确的道路。

事实证明,我的简化代码中有两个错误。一个明显到让我脸红,一个更狡猾。

首先,

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上找到了如何解决这个问题here

因此,对于任何为此苦苦挣扎的人,这是最终的解决方案。

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);
}

希望这对某人有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-07
    • 2018-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-24
    相关资源
    最近更新 更多