Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在asp net内核中处理自定义JSONConverter中的错误?_C#_Asp.net Core Webapi_.net Core 3.1_System.text.json - Fatal编程技术网

C# 如何在asp net内核中处理自定义JSONConverter中的错误?

C# 如何在asp net内核中处理自定义JSONConverter中的错误?,c#,asp.net-core-webapi,.net-core-3.1,system.text.json,C#,Asp.net Core Webapi,.net Core 3.1,System.text.json,我在我的WebAPI项目中使用了NetCore3.1。为了从JSON请求主体中的用户处接受dd-MM-yyyy格式的日期,我创建了一个DateTime转换器,它将所有传入日期和传出日期转换为指定的格式 下面是我的日期时间转换器: public class DateTimeConverter : JsonConverter<DateTime> { public override DateTime Read(ref Utf8JsonReader reader, Type type

我在我的WebAPI项目中使用了NetCore3.1。为了从JSON请求主体中的用户处接受dd-MM-yyyy格式的日期,我创建了一个DateTime转换器,它将所有传入日期和传出日期转换为指定的格式

下面是我的日期时间转换器:

public class DateTimeConverter : JsonConverter<DateTime>
{
    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        Debug.Assert(typeToConvert == typeof(DateTime));
        return DateTime.Parse(reader.GetString());
    }

    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString("dd-MM-yyyy hh:mm tt"));
    }
}
现在我在DateTime转换器中面临一些问题。我创建了一个用于检查ModelState错误的操作过滤器,在DateTime转换器抛出异常后调用该过滤器。以下是ModelState错误筛选器:

    public override void OnActionExecuting(ActionExecutingContext context)
    {

        if (!context.ModelState.IsValid)
        {

            ApiResponseModel<IEnumerable<ValidationErrorModel>> apiResponseModel = new ApiResponseModel<IEnumerable<ValidationErrorModel>>();

            apiResponseModel.ResponseCode = (int)HttpStatusCode.BadRequest;
            apiResponseModel.ResponseMessage = string.Join(" ",
                context.ModelState.Values.Where(E => E.Errors.Count > 0)
                .SelectMany(E => E.Errors)
                .Select(E => E.ErrorMessage)
                .ToArray());
            apiResponseModel.ResponseData = null;
            context.Result = new OkObjectResult(apiResponseModel);
        }
    }
public override void OnActionExecuting(ActionExecutingContext上下文)
{
如果(!context.ModelState.IsValid)
{
ApiResponseModel ApiResponseModel=新的ApiResponseModel();
apiResponseModel.ResponseCode=(int)HttpStatusCode.BadRequest;
apiResponseModel.ResponseMessage=string.Join(“,
context.ModelState.Values.Where(E=>E.Errors.Count>0)
.SelectMany(E=>E.Errors)
.选择(E=>E.ErrorMessage)
.ToArray());
apiResponseModel.ResponseData=null;
context.Result=新的OkObjectResult(apiResponseModel);
}
}

如果日期的格式不正确,例如MM dd YYYY格式,则会生成ModelState错误,并给出内置错误消息“提供的值无效”。我想显示一条不同的消息,而不是这个内置消息,比如“{nameofdatetimefield}的格式不正确”。那么我如何在这个DateTimeConverter中实现同样的功能呢?

在转换器中,而不是使用像
DateTime.Parse这样的API,它会对无效格式的输入引发异常,您可以使用
TryParse
TryParseExact
方法,自己抛出异常并显示不同的错误消息。我假设您仍然希望保持异常的类型相同(即
FormatException

如果您希望在转换器中访问属性名称本身(放入异常消息或出于任何其他原因),这是不容易做到的。如果确实需要,实现这一点的一种方法是为正在序列化的父类型创建一个具有
DateTime
属性的转换器,并以这种方式访问它。这种方法并不理想,尤其是当您碰巧在许多不同的父类型中有这样的
DateTime
属性时(因为它需要您为所有这些属性创建自定义转换器)。无论如何,这里有一个片段作为示例,它使用典型的
WeatherForecast
父类型,其中包含
DateTime
,它与
dotnet新webapi
模板一起提供:

// The "Read" side of a JsonConverter<WeatherForecast> implementation

public override WeatherForecast Read(
    ref Utf8JsonReader reader,
    Type typeToConvert,
    JsonSerializerOptions options)
{
    var forecast = new WeatherForecast();

    while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
    {
        if (reader.ValueTextEquals(nameof(forecast.Date)))
        {
            if (!reader.Read())
            {
                throw new JsonException();
            }

            if (DateTime.TryParseExact(
                        reader.GetString(),
                        "dd-MM-yyyy hh:mm tt",
                        CultureInfo.InvariantCulture,
                        DateTimeStyles.None, 
                        out DateTime date))
            {
                forecast.Date = date;
            }
            else
            {
                throw new FormatException(
                    $"The {nameof(forecast.Date)} is not in a proper format.");
            }
        }

        // Add logic for creating the rest of the object properties from the JSON.
    }

    return forecast;
}
//JsonConverter实现的“读取”端
公共天气预报已读(
参考Utf8JsonReader读取器,
类型转换,
JsonSerializerOptions(可选)
{
var forecast=新天气预报();
while(reader.Read()&&reader.TokenType!=JsonTokenType.EndObject)
{
if(reader.ValueTextEquals(name of(forecast.Date)))
{
如果(!reader.Read())
{
抛出新的JsonException();
}
如果(DateTime.TryParseExact)(
reader.GetString(),
“dd-MM-yyyy hh:MM-tt”,
CultureInfo.InvariantCulture,
DateTimeStyles。无,
过期时间(日期)
{
预测。日期=日期;
}
其他的
{
抛出新的格式化异常(
$“{nameof(forecast.Date)}的格式不正确。”);
}
}
//添加用于从JSON创建其余对象属性的逻辑。
}
收益预测;
}

要解决Sunny向ovveride发出的“提供的值无效”消息的问题,您必须使用throwJsonException而不是FormatException

public override DateTime Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options)
{
    if (DateTime.TryParseExact(
    reader.GetString(),
    "dd-MM-yyyy hh:mm tt",
    CultureInfo.InvariantCulture,
    DateTimeStyles.None, 
    out DateTime date))
{
    return date;
}
    throw new JsonException("Property is not in a proper date format.");
}

谢谢你的回复。我尝试了使用DateTime.TryParseExact()并引发format exception的第一个解决方案,但由于我有一个用于检查模型状态错误的操作筛选器,它给出了相同的消息。“提供的值无效”。我编辑了我的问题,以便更清楚地说明您是在尝试使用
Newtonsoft.Json
还是
System.Text.Json
?为什么要调用
AddNewtonsoftJson
以及与
System.Text.Json
一起工作的转换器?我会尽量避免混合JSON库。你的
DateTimeConverter
有人打电话给你吗?@ahsonkhan。我之所以使用Newtonsoft.Json,是因为System.Text.Json中仍然不支持某些功能。是的,DateTimeConverter正在被调用。
// The "Read" side of a JsonConverter<WeatherForecast> implementation

public override WeatherForecast Read(
    ref Utf8JsonReader reader,
    Type typeToConvert,
    JsonSerializerOptions options)
{
    var forecast = new WeatherForecast();

    while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
    {
        if (reader.ValueTextEquals(nameof(forecast.Date)))
        {
            if (!reader.Read())
            {
                throw new JsonException();
            }

            if (DateTime.TryParseExact(
                        reader.GetString(),
                        "dd-MM-yyyy hh:mm tt",
                        CultureInfo.InvariantCulture,
                        DateTimeStyles.None, 
                        out DateTime date))
            {
                forecast.Date = date;
            }
            else
            {
                throw new FormatException(
                    $"The {nameof(forecast.Date)} is not in a proper format.");
            }
        }

        // Add logic for creating the rest of the object properties from the JSON.
    }

    return forecast;
}
public override DateTime Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options)
{
    if (DateTime.TryParseExact(
    reader.GetString(),
    "dd-MM-yyyy hh:mm tt",
    CultureInfo.InvariantCulture,
    DateTimeStyles.None, 
    out DateTime date))
{
    return date;
}
    throw new JsonException("Property is not in a proper date format.");
}