Как различить нулевые и несуществующие данные в JSON в привязке модели Asp.Net Core? - PullRequest
4 голосов
/ 31 октября 2019

Я хочу провести различие между этими двумя входами json в действии в Asp.Net Core:

{
  "field1": null,
  "field2": null
}

и

{
  "field1": null,
}

У меня есть обычный класс в C #:

public class MyData
{
   public string Field1 { get; set;}
   public string Field2 { get; set;}
}

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

Ответы [ 3 ]

0 голосов
/ 31 октября 2019

Введение: Ядро Asp.net получает ваше тело запроса и затем десериализуется в объект типа MyData, а затем вызывает метод в вашем контроллере, передавая объект в качестве параметра. Из объекта myData вы не можете знать, было ли field2 нулевым или не переданным. В обоих случаях свойство будет иметь нулевое значение. Информация, которую вы пытаетесь найти, теряется при десериализации.

Решение: Чтобы выяснить это, вам нужно прочитать тело запроса и проверить тело запроса, если поле было передано илине. В ядре asp.net есть некоторая сложность - чтение тела запроса, как только оно будет прочитано (основной структурой asp.net для создания объекта MyData). Нам нужно перемотать поток запросов и затем прочитать его. Код для этого ниже.

[HttpPost]
public void Post([FromBody] MyData myData)
{
    HttpContext.Request.Body.Seek(0, System.IO.SeekOrigin.Begin);
    System.IO.StreamReader sr = new System.IO.StreamReader(HttpContext.Request.Body);
    var requestBody = sr.ReadToEnd();
    //Now check the requestBody if the field was passed using JSON parsing or string manipulation
    Console.WriteLine(requestBody);
}

Предупреждение: Хотя это будет работать. То, что вы пытаетесь сделать, снизит читабельность и затруднит работу других разработчиков. Дифференцирование, если значение поля равно нулю или отсутствует в теле запроса, не является обычной практикой.

0 голосов
/ 07 ноября 2019

Это то, что я в итоге сделал, так как все остальные опции кажутся слишком сложными (например, jsonpatch, привязка модели) или не дают желаемой гибкости.

Это решение означает, что есть немногошаблон для каждого свойства, но не слишком много:

public class UpdateRequest : PatchRequest
{
    [MaxLength(80)]
    [NotNullOrWhiteSpaceIfSet]
    public string Name
    {
       get => _name;
       set { _name = value; SetHasProperty(nameof(Name)); }
    }  
}

public abstract class PatchRequest
{
    private readonly HashSet<string> _properties = new HashSet<string>();

    public bool HasProperty(string propertyName) => _properties.Contains(propertyName);

    protected void SetHasProperty(string propertyName) => _properties.Add(propertyName);
}

Значение может быть прочитано следующим образом:

if (request.HasProperty(nameof(request.Name)) { /* do something with request.Name */ }

, и это можно проверить с помощьюнастраиваемый атрибут:

var patchRequest = (PatchRequest) validationContext.ObjectInstance;
if (patchRequest.HasProperty(validationContext.MemberName) {/* do validation*/}
0 голосов
/ 31 октября 2019

Низкий ключ будет выглядеть так:

public class MyData
{
  public string Field1 { get; set; }
  public string Field2 { get; set; }

  // this can be extension method also.
  public bool HasProperty(string propertyName)
  {
    return GetType().GetProperty(propertyName) != null;
  }
}

На основном:

  string json = "{  \"field1\": null,  \"field2\": null }";
  MyData jsonObject = null;

  jsonObject = JsonConvert.DeserializeObject<MyData>(json);

  MyData source= null; // this will contain values  

  if (jsonObject.HasProperty("Field1"))
    source.Field1 = jsonObject.Field1;

Ссылка: Проверьте, существует ли свойство в классе

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