C# 谷歌API->;创建新日历->;解析错误

C# 谷歌API->;创建新日历->;解析错误,c#,google-api,google-calendar-api,C#,Google Api,Google Calendar Api,我正试图通过谷歌API创建一个日历。我试图避免使用客户端库,并通过自定义webrequests与API进行所有通信,到目前为止,这一切都很顺利,但在这个特定的库上,我遇到了一个“解析错误” 请不要参考使用客户端库的解决方案(service.calendars().insert(…) 这是我的代码的简化版本(仍然不起作用): var url=string.Format ( "https://www.googleapis.com/calendar/v3/calendars?key={0}", 应用程

我正试图通过谷歌API创建一个日历。我试图避免使用客户端库,并通过自定义webrequests与API进行所有通信,到目前为止,这一切都很顺利,但在这个特定的库上,我遇到了一个“解析错误”

请不要参考使用客户端库的解决方案(service.calendars().insert(…)

这是我的代码的简化版本(仍然不起作用):

var url=string.Format
(
"https://www.googleapis.com/calendar/v3/calendars?key={0}",
应用程序。键
);
var httpWebRequest=httpWebRequest.Create(url)为httpWebRequest;
httpWebRequest.Headers[“授权”]=
格式(“承载{0}”,user.AccessToken.Token);
httpWebRequest.Method=“POST”;
httpWebRequest.ContentType=“应用程序/json”;
httpWebRequest.CookieContainer=新CookieContainer();
//显然,真正的代码将序列化系统中的对象。
//我现在用的是一个假请求,
//只是为了确保问题不在于序列化。
var请求文本=
“{”+Environment.NewLine
+“\“summary\”:\“test123\”+Environment.NewLine
+“}”+Environment.NewLine
;
使用(var stream=httpWebRequest.GetRequestStream())
使用(var streamWriter=new System.IO.streamWriter(流))
{
streamWriter.Write(System.Text.Encoding.UTF8.GetBytes(requestText));
}
//GetSafeResponse()只是一个捕获WebException(如果有)的扩展
//并返回WebException.Response,而不是使程序崩溃。
var httpWebResponse=httpWebRequest.GetSafeResponse();
正如您所看到的,我现在已经放弃发送序列化对象,我只是尝试使用一个非常简单的虚拟请求:

{
"summary": "test123"
}
但答案仍然是:

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "parseError",
    "message": "Parse Error"
   }
  ],
  "code": 400,
  "message": "Parse Error"
 }
}
accessToken有效且未过期,应用程序密钥正确

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


提前感谢,

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

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

 httpWebRequest.ContentType = "application/json ; charset=UTF-8";
除此之外,我看不出你的代码有什么问题,最好附加一个透明的回音代理(Charles或fiddler),这样你就可以通过网络看到你的请求是什么样子。从他们发送的日历中

要求 回应
希望这能有所帮助,意识到它可能不起作用。

我想出来了,并让它工作了

虽然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()。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);
}

希望这对别人有帮助

大家好,我只是出于兴趣,为什么您不喜欢使用客户端库?因为它只会给一个已经相当复杂的项目增加另一层复杂性,因为我们必须包含不在我们控制之下的代码,当它出现错误和/或中断时,我们可能无法自行修复,并且因为REST服务根据定义是,应该简单明了。我们的代码还使用相同的无意义方法与FB和Twitter同步,这一点也不困难,除非像本例一样,文档是错误的。感谢您的回复:)谢谢您的建议。这个项目已经被搁置了一段时间,但我会在几天后回来发布更新。
using (var streamWriter = new StreamWriter(stream, Encoding.UTF8))
{
    streamWriter.Write(requestText);
}
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);
}