【问题标题】:C# - Office API returning 400 "69 {"error":{"code":"RequestBodyRead","message":"Cannot read the value '0' as a quoted JSON string value."}} 0 "C# - Office API 返回 400 "69 {"error":{"code":"RequestBodyRead","message":"Cannot read the value '0' as aquoted JSON string value."}} 0 "
【发布时间】:2016-09-04 20:02:44
【问题描述】:

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

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

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

【问题讨论】:

  • 该错误表明当 API 需要一个字符串值时,您正在发送一个整数值 0。事实上,here 文档表明 Message.Body.ContentType 应该是一个字符串:"ContentType": "Text"
  • 你是绝对正确的@dbc 我只是觉得奇怪的是他们的 API 期望的东西与要发送到 API 的对象所包含的不同。

标签: c# json post office365api


【解决方案1】:

当 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 中所述。

【讨论】:

  • 是的,就是这样。奇怪的是,他们的对象是以这样一种方式构建的,它不能在不恢复枚举的情况下被序列化和发送。
【解决方案2】:

很可能发生指定的错误,因为提供的 JSON 有效负载无效。

问题与这一行有关:

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

Microsoft.OutlookServices.ItemBodyContentType 属性接受字符串 值(不是整数):TextHTML,例如:

email.Body.ContentType = "Text";

【讨论】:

  • 不幸的是,它不接受代码中的字符串:Cannot implicitly convert type 'string' to 'Microsoft.Office365.OutlookServices.BodyType' 但这看起来是正确的轨道,听起来 API 正在寻找一个字符串,而他们的类是用整数/枚举构建的.
【解决方案3】:

感谢其他答案的帮助,我找到了我的解决方案,修改 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");

【讨论】:

    猜你喜欢
    • 2020-06-25
    • 1970-01-01
    • 1970-01-01
    • 2016-02-27
    • 2021-10-02
    • 2021-02-13
    • 1970-01-01
    • 1970-01-01
    • 2018-12-12
    相关资源
    最近更新 更多