【问题标题】:"Bad request" error when passing DateTime to REST API将 DateTime 传递给 REST API 时出现“错误请求”错误
【发布时间】:2021-04-26 16:28:20
【问题描述】:

我正在向 HTTP post API 发送数据。但每次我尝试调用 API 时,都会收到错误代码:400,错误请求消息。

这是我的 API 代码:

  [Route("InsUpPlayer")]
    [HttpPost]
    public async Task<object> InsUpPlayer([FromForm] Players player)
    {
        try
        {

            //Some code here

        }
        catch (Exception e)
        {
            throw new Exception(e.Message);
        }
    }

还有我的存储库代码:

public async Task<string> PlayerInsUpPost(Player player1)
    {
        var SendResponse = "false";
        try
        {
            var RequestUrl = baseUrl + "Master/InsUpPlayer";
            var httpClient = new HttpClient();
            httpClient.BaseAddress = new Uri(RequestUrl);

            using (var player = new MultipartFormDataContent())
            {
                if (player1.ProfileImageFile != null)
                {
                    string objimgFileBase64 = "";
                    ByteArrayContent fileContent;
                    using (var ms = new MemoryStream())
                    {
                        player1.ProfileImageFile.CopyTo(ms);
                        var fileBytes = ms.ToArray();
                        objimgFileBase64 = Convert.ToBase64String(fileBytes);
                    }
                    byte[] bytes = Convert.FromBase64String(objimgFileBase64);
                    fileContent = new ByteArrayContent(bytes);
                    player.Add(fileContent, "ProfileImageFile", string.Format("{0}", player1.ProfileImageFile.FileName));
                }
                if (player1.DetailImageFile != null)
                {
                    string objimgFileBase64 = "";
                    ByteArrayContent fileContent;
                    using (var ms = new MemoryStream())
                    {
                        player1.DetailImageFile.CopyTo(ms);
                        var fileBytes = ms.ToArray();
                        objimgFileBase64 = Convert.ToBase64String(fileBytes);
                    }
                    byte[] bytes = Convert.FromBase64String(objimgFileBase64);
                    fileContent = new ByteArrayContent(bytes);
                    player.Add(fileContent, "DetailImageFile", string.Format("{0}", player1.DetailImageFile.FileName));
                }
                player.Add(new StringContent(player1.playerId.ToString()), "playerId");
                player.Add(new StringContent(player1.FirstName), "FirstName");
                player.Add(new StringContent(player1.LastName), "LastName");
                player.Add(new StringContent(player1.DOB.ToString()), "DOB");
                player.Add(new StringContent(player1.Nationality.ToString()), "Nationality");
                player.Add(new StringContent(player1.BirthState.ToString()), "BirthState");
                player.Add(new StringContent(player1.JerseyNo.ToString()), "JerseyNo");
                player.Add(new StringContent(player1.Postion.ToString()), "Postion");
                player.Add(new StringContent(player1.Biography), "Biography");
                player.Add(new StringContent(player1.isActive.ToString()), "isActive");                    
                player.Add(new StringContent(player1.isPublish.ToString()), "isPublish");
                player.Add(new StringContent(player1.UserType.ToString()), "UserType");

                HttpResponseMessage objResponse = await httpClient.PostAsync(RequestUrl, player);
                if (objResponse.IsSuccessStatusCode && (int)objResponse.StatusCode == 200)
                {
                    var serResponse = objResponse.ContentAsType<ResultModel>();
                    //SendResponse = serResponse.result;
                    SendResponse = "true";
                }
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Exception Occured");
            throw;
        }
        return SendResponse;
    }

Player 类是这样的:

public class Player
{
    public long playerId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DOB { get; set; }
    public int Nationality { get; set; }
    public int BirthState { get; set; }
    public int JerseyNo { get; set; }
    public int Postion { get; set; }
    public string Biography { get; set; }
    public bool isActive { get; set; }
    public bool isPublish { get; set; }
    public int UserType { get; set; }
    public IFormFile ProfileImageFile { get; set; }
    public IFormFile DetailImageFile { get; set; }

    public string ProfileImage { get; set; }
    public string DetailImage { get; set; }
}

更新:这是我的 JQuery 代码:这里的 DOB 是正确的,但我刚刚意识到它没有正确传递给控制器​​。

$("#PublishPlayer").click(function () {
debugger;
var value = $('#CreatePlayerForm').valid();
var url = '/Admin/PlayerInsUpPost';

var day = $('#Day').val();
var month = $('#Month').val();
var year = $('#Year').val();

var DOB = new Date(year, month, day);

var fdata = new FormData();
fdata.append("playerId", $('#playerId').val());
fdata.append("FirstName", $('#FirstName').val());
fdata.append("LastName", $('#LastName').val());
fdata.append("DOB", DOB);
fdata.append("Nationality", $('#Nationality').val());
fdata.append("BirthState", $('#BirthState').val());
fdata.append("JerseyNo", $('#JerseyNo').val());
fdata.append("Position", $('#Position').val());
fdata.append("Biography", $('#Biography').val());


fdata.append('ProfileImageFile', $('#ProfileImageFile')[0].files[0]);

fdata.append('DetailImageFile', $('#ProfileImageFile')[0].files[0]);

if (value == true) {
    $.ajax({
        url: url,
        datatype: "json",
        accept: {
            javascript: 'application/javascript'
        },
        type: "POST",
        cache: false,
        processData: false,
        contentType: false,
        data: fdata,
        success: function (result) {
            if (result == "true") {
                alert('Player added successfully.');
                window.location.href = "/Admin/PlayerList";

            } else if (result == "false") {
                alert('Failed to update, please try later.');
            }
        },
        error: function () {
            alert('Something went wrong');
        }
    });
}
else {
    //$('.playeradd').removeClass('show');
    //$('.playeradd').addClass('hide');
    return false;
}
//event.stopPropagation();

});

调用 Ajax 之前 JQuery 中的 DOB 为:Wed Sep 12 2001 00:00:00 GMT+0530(印度标准时间){}

当传递给控制器​​时,它是:{01-01-0001 12:00:AM}

如果我在 API 和前端评论 DOB,一切正常。但我需要将 DOB 发送到 API,我无法在 API 中更改 DOB 的数据类型。如何解决此错误?

【问题讨论】:

  • 如果不了解更多细节,我们无能为力。你在向 API 发布什么? 400 错误的实际响应是什么?您是否尝试过逐行调试?哪一行导致了问题?
  • 是的,我试过调试,API中的调试器从来没有被调用过,这就是我没有发布API代码的原因。但是,如果我注释掉存储库中的 DOB.ToString() 行,就会调用 API。用正确的错误更新问题。
  • 我建议您也发布一个您要发布到 API 的 JSON 示例。如果在包含 datetime 字段时调试器根本没有触发该方法,这听起来像是模型绑定问题。
  • 好的,让我上传我发布的值的示例。我猜我不会发送 JSON。我不会在任何地方将其转换为 JSON。
  • 你用的是什么版本的net core?

标签: c# asp.net-core asp.net-web-api


【解决方案1】:

将数据传递到 ajax 请求时将其转换为 ISO 字符串。 Dotnet 明白这一点。所以做这样的事情:

fdata.append("DOB", DOB.toISOString());

【讨论】:

  • 谢谢!我现在可以将 DOB 传递给控制器​​,但床请求错误仍然存​​在。
  • 将 dob 作为字符串传递,因为当您以日期格式传递时,它包含空格字符,这会使请求数据无效。
  • @RahulShukla,我将 DOB 作为字符串传递,但问题仍然存在。
  • hmm.. 你能从 api 中添加日志,看看究竟是什么导致了 400 错误请求
  • 功能不适合我
【解决方案2】:

.net core > 3.0 中的新序列化程序在解析日期格式时非常严格(注意默认值已从 newtonsoft json 更改)。它们必须采用 ISO8601 格式,即 YYYY-MM-DD。如果您传递的内容不在 ISO8601 表单中,则必须编写自定义格式化程序。

public class DateTimeJsonConverter : JsonConverter<DateTime>
{
    public override DateTime Read(
        ref Utf8JsonReader reader,
        Type typeToConvert,
        JsonSerializerOptions options) =>
            DateTime.ParseExact(reader.GetString(),
                "<YOUR FORMAT HERE>", CultureInfo.InvariantCulture);

    public override void Write(
        Utf8JsonWriter writer,
        DateTime dateTimeValue,
        JsonSerializerOptions options) =>
            writer.WriteStringValue(dateTimeValue.ToString(
                "<YOUR FORMAT HERE>", CultureInfo.InvariantCulture));
}

上面的代码是自定义格式化程序的示例。

在此处阅读更多详细信息 (https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to#sample-basic-converter),了解如何为您的输入创建自定义格式化程序。

【讨论】:

    【解决方案3】:

    我想这是 ASP.NET 反序列化 DateTime 的一些问题(我不确定)。我之前遇到过类似的发送日期问题,我的解决方案不是发送 DateTime 结构,而是发送滴答数(您可以从 DateTime 对象中获取)作为 long 变量。

    DateTime BOD = DateTime.Now; // You may fill your DateTime object with your own data
    long BODticks = BOD.Ticks;
    

    然后在服务器端,您可以像这样轻松地重新创建日期时间:

    DateTime myDate = new DateTime(BODticks);
    

    然后为了使用它,您可以如下修改您的播放器类:

    public class Player
    {
        public long playerId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public long DOBTicks { get; set; }
        public DateTime DOB { get => new DateTime(DOBTicks); set => DOBTicks = value.Ticks; }
        public int Nationality { get; set; }
        public int BirthState { get; set; }
        public int JerseyNo { get; set; }
        public int Postion { get; set; }
        public string Biography { get; set; }
        public bool isActive { get; set; }
        public bool isPublish { get; set; }
        public int UserType { get; set; }
        public IFormFile ProfileImageFile { get; set; }
        public IFormFile DetailImageFile { get; set; }
    
        public string ProfileImage { get; set; }
        public string DetailImage { get; set; }
    }
    

    我确信有人可以找到更好的解决方案,并且假设这个解决方案确实有效并且我正确理解了您的问题。

    【讨论】:

    • 问题是我无法更改 API 中的任何内容,并且 API 接受 DateTime 格式的 DOB,我正在将 DateTime 转换为字符串并发送它。即使我将 DOB 转换为刻度,我仍然以字符串格式发送所有内容。我更改了 API 中的 Player 只是为了进行测试,并且 API 正在接受输入。那么有什么方法可以将日期时间发送到 API 吗?
    猜你喜欢
    • 2023-03-07
    • 2012-12-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多