Каков наилучший способ преобразования int (1 и 0) в bool (true и false) для привязки модели свойств сложного типа? - PullRequest
2 голосов
/ 09 июля 2019

Я интегрирую некоторые службы в свой сервер. Но провайдер api заставляет некоторые поля использовать 1 и 0, чтобы указать bool true и false. Поэтому я хочу сделать пользовательское преобразование при привязке модели.

Запрос отправлен на мой сервер:

{
    ...
    "prefix_success": "1" // or "0"
    ...
}

Моя модель:

public class RequestForm {
    ...

    public bool Success { get; set; }

    ...
}

Ответы [ 3 ]

1 голос
/ 10 июля 2019

Если запрос представляет собой POST с полезной нагрузкой JSON, а значение передается в виде строки, вы можете сделать следующее:

Создать пользовательский JsonConverter

using Newtonsoft.Json;
using System;

namespace AppNamespace.JsonConverters
{
    public class NumericStringToBooleanConverter : JsonConverter
    {
        public override bool CanRead => true;
        public override bool CanWrite => false;

        public override bool CanConvert(Type objectType) => objectType == typeof(string);

        public override object ReadJson(JsonReader reader, Type objectType,
            object existingValue, JsonSerializer serializer)
        {
            return reader.Value.ToString().Equals("1");
        }

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

Затем использовать атрибут модели JsonConverter

using AppNamespace.JsonConverters;
using Newtonsoft.Json;
using System;
--
[JsonProperty("prefix_success")]
[JsonConverter(typeof(NumericStringToBooleanConverter))]
public bool Success { get; set; }
0 голосов
/ 10 июля 2019

Я думаю, что это самое простое. Спасибо всем.

Связующее:

public class IntToBoolModelBinder : IModelBinder {
    public Task BindModelAsync(ModelBindingContext bindingContext) {
        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        var value = valueProviderResult.FirstValue;

        if (int.TryParse(value, out var intValue)) {
            bindingContext.Result = ModelBindingResult.Success(intValue == 0 ? false : true);

        } else if (bool.TryParse(value, out var boolValue)) {
            bindingContext.Result = ModelBindingResult.Success(boolValue);

        } else if (string.IsNullOrWhiteSpace(value)) {
            bindingContext.Result = ModelBindingResult.Success(false);

        } else {
            bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, 
                $"{bindingContext.ModelName} should be a int, bool or empty string.");
        }

        return Task.CompletedTask;
    }
}

использование:

public class Model {
    ...

    [BindProperty(BinderType = typeof(IntToBoolModelBinder))]
    public bool MarketingConsent { get; set; }

    ...
}
0 голосов
/ 10 июля 2019

Для этого вам нужно создать пользовательский механизм связывания моделей.

1.Создать StringToBoolBinder

public class StringToBoolBinder: ComplexTypeModelBinder
{
    IDictionary<ModelMetadata, IModelBinder> _propertyBinders;
    public StringToBoolBinder(IDictionary<ModelMetadata, IModelBinder> propertyBinders) : base(propertyBinders)
    {
        _propertyBinders = propertyBinders;
    }
    protected override Task BindProperty(ModelBindingContext bindingContext)
    {

        if (bindingContext == null)
            throw new ArgumentNullException(nameof(bindingContext));

        string valueFromBody = string.Empty;

        using (var sr = new StreamReader(bindingContext.HttpContext.Request.Body))
        {
            valueFromBody = sr.ReadToEnd();
        }

        if (string.IsNullOrEmpty(valueFromBody))
        {
            return Task.CompletedTask;
        }

        if (bindingContext.FieldName == "Success")
        {
            var json = JObject.Parse(valueFromBody);
            string values = Convert.ToString(((JValue)JObject.Parse(valueFromBody)["prefix_success"]).Value);
            if (values == "1")
            {
                bindingContext.Result = ModelBindingResult.Success(true);
            }
            else
            {
                bindingContext.Result = ModelBindingResult.Success(false);
            }

        }else
        {
            return base.BindProperty(bindingContext);
        }
        return Task.CompletedTask;

    }

}

2.Создать StringToBoolBinderProvider

public class StringToBoolBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }
        if (context.Metadata.IsComplexType && context.Metadata.ModelType == typeof(RequestForm))
        {
            var propertyBinders = new Dictionary<ModelMetadata, IModelBinder>();
            for (var i = 0; i < context.Metadata.Properties.Count; i++)
            {
                var property = context.Metadata.Properties[i];
                propertyBinders.Add(property, context.CreateBinder(property));
            }
            return new StringToBoolBinder(propertyBinders);
        }

        return null;
    }
}

3. Зарегистрировать провайдера при запуске

services.AddMvc(options =>
            {
                // add custom binder to beginning of collection
                options.ModelBinderProviders.Insert(0, new StringToBoolBinderProvider());
            });

4.Action

[HttpPost]
public void Post([FromBody] RequestForm form)

5.Model

public class RequestForm {
   ... 
   public bool Success { get; set; }
   ...
}

6.Json Полезная нагрузка

{
  ...
  "prefix_success":"1",
  ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...