Написание собственного JsonConverter для десериализации JSON из POST на контроллере ASP.NET Core 2 - PullRequest
0 голосов
/ 04 мая 2018

Мне нужно написать собственный JsonConverter в моем проекте ASP.NET MVC Core 2 для десериализации данных JSON в теле jQuery POST, поскольку это привязка модели по умолчанию. Сложная часть здесь заключается в том, что мне нужен TypeNameHandling для входящего объекта, который содержит массив базового типа или массив полиморфных типов. Я мог бы аннотировать объект с помощью

[JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto)]

но проблемы безопасности, связанные с этим, не приемлемы для моего проекта. Я написал собственный конвертер JSON и пометил свой объект взамен ниже, но, похоже, он не использует мой собственный конвертер (точка останова не достигнута).

[JsonConverter(typeof(ApplicationLoggingConverter))]

Полный соответствующий код ниже. Мое приложение LoggingModel:

public class ApplicationLoggingModel
{
    public Guid ApplicationId { get; set; }

    [JsonConverter(typeof(ApplicationLoggingConverter))]
    public ModelActionBase[] Changes { get; set; }
}

Действие контроллера:

[HttpPost("Save/{id}")]
    public async Task<ActionResult> Save(Guid id, [FromBody]ApplicationLoggingModel model)
    {
        model.ApplicationId = id;
        //nothing yet implemented
        return Ok();
    }

Пользовательский конвертер:

public class ApplicationLoggingConverter : JsonConverter
{
    private readonly Type[] _types;

    public ApplicationLoggingConverter(params Type[] types)
    {
        _types = types;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.StartArray)
        {
            return serializer.Deserialize<ApplicationLoggingModel[]>(reader);
        }
        else
        {
            var myObject = serializer.Deserialize<ApplicationLoggingModel>(reader);
            return new ApplicationLoggingModel[] { myObject };
        }
    }

    public override bool CanConvert(Type objectType)
    {
        return _types.Any(t => t == objectType);
    }
}

При запуске:

services.AddMvc().AddJsonOptions(options => { options.SerializerSettings.Converters.Add(new ApplicationLoggingConverter()); });

... и данные JSON, которые я пытаюсь опубликовать:

"$type": "Project.Web.Areas.Admin.Models.ApplicationLoggingModel, Project.Web",
"Changes": [{
    "$type": "Project.Generation.Common.Actions.EntityAction, Project.Services.Generation.Common",
    "Action": 0,
    "ItemName": "Entity",
    "PropertyName": "Name",
    "OldValue": "",
    "NewValue": "newEntity",
    "Scope": {

    }
}]

Я довольно новичок в пользовательской десериализации для связывания моделей ASP Core 2, и документации по ней довольно мало (если я не гуглю / не исследую не то, что нужно), но кажется, что моя точка останова в "публичном объекте переопределения ReadJson" должна по крайней мере, ударил. Я изменил имена проектов в JSON по соображениям безопасности, и когда я устанавливаю TypeNameHandling. Авто работает, что я делаю не так? Дайте мне знать, если вам нужна дополнительная информация / код.

...