首页 > 解决方案 > (C# .NET 5 REST API)使用转换器添加多态时输入无效

问题描述

我正在尝试使用转换器在我的 REST API 中使用多态性。我浏览了本教程:https ://newbedev.com/deserialising-json-to-derived-types-in-asp-net-web-api并将其调整为我自己的基类和派生类型。

我发送的请求是这样的:

{
  "createdBy": "string",
  "createdAt": "2021-08-23T14:42:21.500Z",
  "modifiedBy": "string",
  "modifiedAt": "2021-08-23T14:42:21.500Z",
  "id": 0,
  "points": 0,
  "text": "test",
  "quizId": 4,
  "quizOptions": [
  ]
}

当我删除“文本”属性时它可以工作,但我当然会收到内部服务器错误,因为它不能被解析为“ImageOptionDto”或“TextOptionDto”。

我的转换器:

public class QuizOptionJsonConverter : JsonCreationConverter<QuizOptionDto>
{
    protected override QuizOptionDto Create(Type objectType, JObject jObject)
    {
        if (jObject == null) throw new ArgumentNullException("jObject");

        if (jObject["text"] != null)
        {
            return jObject.ToObject<TextOptionDto>();
        }
        else if (jObject["imageUrl"] != null)
        {
            return jObject.ToObject<ImageOptionDto>();
        }
        else
        {
            return null;
        }
    }
}

我的基类:

[JsonConverter(typeof(QuizOptionJsonConverter))]
public class QuizOptionDto : IdentifierBaseModelDto
{
    public bool IsCorrect { get; set; }
    public int QuizQuestionId { get; set; }
    public QuizQuestionDto QuizQuestion { get; set; }
}

我的派生类:

public class TextOptionDto : QuizOptionDto
{
    public string Text { get; set; }
}

public class ImageOptionDto : QuizOptionDto
{
    public string ImageUrl { get; set; }
}

经过一些研究,我还将它添加到我的 Startup.cs

options.SerializerSettings.TypeNameHandling = TypeNameHandling.All;
options.SerializerSettings.Converters.Add(new QuizQuestionJsonConverter());
options.SerializerSettings.Converters.Add(new QuizOptionJsonConverter());

我的问题正是当我使用派生属性进行 api 调用时,例如:'text' 它返回“输入无效”,例如 400)。我试图抑制模型状态验证,但是我的 post 方法中的参数只是“null”。显然,这里出了点问题。

我调试了代码并得出结论,我的代码没有通过该CanConvert方法。我检查了“objectType(方法中的参数)”的类型,它说:

在此处输入图像描述

我希望“TextOptionDto”是这里的类型,而不是“AnnotatedProblemDetails”。我知道这里发生了什么,但我不知道如何解决它。

错误:

{
  "$type": "Microsoft.AspNetCore.Mvc.NewtonsoftJson.ValidationProblemDetailsConverter+AnnotatedValidationProblemDetails, Microsoft.AspNetCore.Mvc.NewtonsoftJson",
  "errors": {
    "$type": "System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[System.String[], System.Private.CoreLib]], System.Private.CoreLib",
    "": {
      "$type": "System.String[], System.Private.CoreLib",
      "$values": [
        "The input was not valid."
      ]
    }
  },
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "00-742ca70c9de2454bac8f94422bc49a2b-bd270ab858be3d43-00"
}

你们能帮帮我吗?

谢谢!

编辑

经过一番研究,我发现了问题。它似乎与我来自 OData 的 EDM 有关。当我删除这部分时:

public static IEdmModel GetEdmModel()
    {
        var builder = new ODataConventionModelBuilder();
        builder.EnableLowerCamelCase();
        
        // The name in the string must be the same as the controller classname e.g. Users
        builder.EntitySet<ProductDto>("Products");
        builder.EntitySet<CategoryDto>("Categories");
        builder.EntitySet<TextBlockDto>("TextBlocks");
        builder.EntitySet<MediaDto>("Media");
        builder.EntitySet<QuizDto>("Quizzes");
        builder.EntitySet<QuizResultDto>("QuizResults");
        builder.EntitySet<QuizQuestionDto>("QuizQuestions"); <---
        builder.EntitySet<UserDto>("Users");

        return builder.GetEdmModel();
    }

它工作得很好,但是如果我这样做,这个控制器当然不会使用 OData。

关于如何构建我的模型以使其允许继承的任何建议?

标签: c#.netapipolymorphismodata

解决方案


推荐阅读