C# - Office API 返回 400 "69 {"error":{"code":"RequestBodyRead","message":"Cannot read the value '0' as a quoted JSON string value."}} 0 "

C# - Office API returning 400 "69 {"error":{"code":"RequestBodyRead","message":"Cannot read the value '0' as a quoted JSON string value."}} 0 "

我正在尝试使用 Office 365 发送电子邮件 API,我无法使用 Microsoft.Office365 包进行发送,因为它们目前不支持我们的身份验证,但我有一个访问 API 的有效令牌,获取请求工作正常,但是当我尝试从 post 到“https://outlook.office.com/api/v2.0/me/sendmail”时,出现上述错误。虽然我不能使用 Microsoft.Office365 中提供的发送功能,但我正在使用消息对象创建我的电子邮件,然后序列化和 posting.

public void SendMail(string Subject, string Body) {
    HttpClient client = new HttpClient();
    string accessToken = userCache.UserAccessToken;
    Uri uri = new Uri("https://outlook.office.com/api/v2.0/me/sendmail");
    client.DefaultRequestHeaders.Add("User-Agent", agent);
    client.DefaultRequestHeaders.Add("client-request-id", requestGuid);
    client.DefaultRequestHeaders.Add("return-client-request-id", "true");
    client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
    List<string> recipients = new List<string>();
    recipients.Add(userCache.Email);

    #region Create Email Message
    Message email = new Message();
    email.Body = new ItemBody();
    email.Body.Content = Body;
    email.Body.ContentType = 0;//0=text, 1=html
    email.From = new Recipient();
    email.From.EmailAddress = new EmailAddress();
    email.From.EmailAddress.Address = userCache.Email;//set from email to email of current logged in user

    email.Importance = Importance.Normal;
    email.Sender = email.From;
    email.Subject = Subject;
    email.ToRecipients = recipients;
    #endregion
    try {
        dynamic mailObject = new ExpandoObject();
        mailObject.Message = email;
        mailObject.SaveToSentItems = "true";
        HttpResponseMessage hrm = client.PostAsJsonAsync<Object>(uri, mailObject as ExpandoObject).Result;
    } catch (Exception e) { }
}

这会将下面的 json 提交给 API:

{
    "Message": {
        "Subject": "Products",
        "Body": {
            "ContentType": 0,
            "Content": "Products"
        },
        "BodyPreview": null,
        "Importance": 0,
        "HasAttachments": null,
        "ParentFolderId": null,
        "From": {
            "EmailAddress": {
                "Name": null,
                "Address":"andrew.branoff@paretobiz.com"
            }
        },
        "Sender": {
            "EmailAddress": {
                "Name": null,
                "Address": "andrew.branoff@paretobiz.com"
            }
        },
        "ToRecipients": [
            {
                "EmailAddress": {
                    "Name": null,
                    "Address": "andrew.branoff@paretobiz.com"
                }
            }
        ],
        "CcRecipients": [],
        "BccRecipients": [],
        "ReplyTo": [],
        "ConversationId": null,
        "UniqueBody": null,
        "DateTimeReceived": null,
        "DateTimeSent": null,
        "IsDeliveryReceiptRequested": null,
        "IsReadReceiptRequested": null,
        "IsDraft": null,
        "IsRead": null,
        "WebLink": null,
        "Attachments": [],
        "ChangeKey": null,
        "Categories": [],
        "DateTimeCreated": null,
        "DateTimeLastModified": null,
        "Id": null
    },
    "SaveToSentItems": "true"
}

据我所知,这就是 API 正在寻找的东西,因为我使用了他们自己的对象来构建它,但无论我做什么,它似乎都拒绝我发送的内容。我尝试先使用

进行序列化
JsonConvert.SerializeObject(mailObject, Newtonsoft.Json.Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });

不发送空值,认为它可能不接受值,即使是空值,对于它计算的东西,如正文预览,但没有变化。

指定的错误很可能是因为提供的 JSON 负载无效。

问题与此行有关:

email.Body.ContentType = 0;//0=text, 1=html

ContentType 属性 of Microsoft.OutlookServices.ItemBody 接受 string 值(不是 integer):TextHTML,例如:

email.Body.ContentType = "Text";

该错误表明您在 API 需要字符串值时发送整数值 0。事实上,文档 here 表明 Message.Body.ContentType 以及 Message.Importance 应该是字符串,例如:

  "Body": {
    "ContentType": "Text",
    "Content": "Products"
  },

您可能会为这些属性发送整数值,因为在您的 c# 类 中,它们是枚举。如果要按名称将枚举序列化为字符串,则需要使用 StringEnumConverter.

可以直接在属性上设置为属性,例如:

public class Body
{ 
    [JsonConverter(typeof(StringEnumConverter))]
    public ContentType ContentType { get; set; }

    public string Content { get; set; }
}

您还可以配置 HttpClient 以将此转换器用于所有枚举,如 this answer 中所述。

感谢其他答案的帮助,我找到了解决方案,修改 Json.net 序列化对象的方式。我将发布确切的解决方案,以帮助其他人稍后解决此问题。

var settings = new JsonSerializerSettings();
settings.Converters.Add(new StringEnumConverter());
settings.NullValueHandling = NullValueHandling.Ignore;
string json = JsonConvert.SerializeObject(emailObject, Newtonsoft.Json.Formatting.None, settings);
StringContent content = new StringContent(json, Encoding.UTF8, "application/json");