Как динамически удалить объект по умолчанию из «IEnumerable» на контроллере RESTC#

Место общения программистов C#
Ответить
Anonymous
 Как динамически удалить объект по умолчанию из «IEnumerable» на контроллере REST

Сообщение Anonymous »

У меня есть конечная точка REST, которая получает класс EntityInsertRequest

Код: Выделить всё

public class EntityInsertRequest
{
public string Description { get; set; }
public IEnumerable Fields { get; set; }
}

public class EntityFieldInsertRequest
{
public string DatabaseField { get; set; }
public string Description { get; set; }
}
Как создать фильтр или переопределить инициализацию объекта для удаления объекта по умолчанию из списка, в этом случае объектом списка по умолчанию будет:

Код: Выделить всё

{
"databaseField": "",
"description": ""
}
И я бы отправил:

Код: Выделить всё

{
"description": "FooBar",
"fields": [
{
"databaseField": "",
"description": ""
},
{
"databaseField": "Foo",
"description": "Bar"
}
]
}
Я бы хотел, чтобы его экземпляр создавался с пустым списком и динамически реплицировался для других конечных точек.
Я не могу изменить способ отправки и удалите объект на стороне отправителя, он должен находиться на серверной стороне.
Я пытался создать JsonConverter:

Код: Выделить всё

public class NullableIEnumerableOverride : JsonConverter where T : class
{
public override bool CanConvert(Type typeToConvert)
{
return typeof(System.Collections.IEnumerable).IsAssignableFrom(typeToConvert) && typeToConvert != typeof(string) && typeToConvert.GenericTypeArguments[0].IsClass;
}

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

var list = JsonSerializer.Deserialize(ref reader);

if (list == null || !list.Any())
{
return  (IEnumerable)CreateEmptyInstance(typeToConvert);
}

// can't get properties of generic object with typeof(T).GetProperties()
//bool allFieldsAreDefault = list.All(item =>
//{
//   var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
//    return properties.All(prop =>
//    {
//        var value = prop.GetValue(item);
//        var defaultValue = GetDefault(prop.PropertyType);
//        return Equals(value, defaultValue);
//    });
//});
//return allFieldsAreDefault ? (IEnumerable)CreateEmptyInstance(typeToConvert) : list;

return list;
}

private static object CreateEmptyInstance(Type typeToConvert)
{
if (typeToConvert.IsGenericType &&  typeof(IEnumerable).IsAssignableFrom(typeToConvert.GetGenericTypeDefinition()))
{
Type elementType = typeToConvert.GetGenericArguments()[0];
Type listType = typeof(List).MakeGenericType(elementType);
return Activator.CreateInstance(listType) ?? throw new InvalidOperationException($"Unable to create instance of type {listType}.");
}

throw new InvalidOperationException($"Type {typeToConvert} is not supported.");
}

public override void Write(Utf8JsonWriter writer, IEnumerable? value, JsonSerializerOptions options)
{
if (value == null)
{
writer.WriteNullValue();
return;
}

JsonSerializerOptions jsonOptions = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
};

JsonSerializer.Serialize(writer, value, jsonOptions);
}

private object? GetDefault(Type type)
{
return type.IsValueType ? Activator.CreateInstance(type) : null;
}
}
А в program.cs у меня есть:

Код: Выделить всё

builder.Services.AddControllers().AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new NullableIEnumerableOverride());
});
Поскольку я хочу использовать его на других конечных точках и установить как общий объект в program.cs, я получаю следующую ошибку приведения:

System.InvalidCastException: невозможно привести объект типа «System.Collections.Generic.List»

Код: Выделить всё

1[System.Object]' to type 'System.Collections.Generic.IEnumerable
1[Logic.Request.Entity.EntityFieldInsertRequest]'.
at System.Text.Json.ThrowHelper.ThrowInvalidCastException_DeserializeUnableToAssignValue(Type typeOfValue, Type объявленныйтип)

at System.Text.Json.JsonSerializer.g__ThrowUnableToCastValue|50_0[T](значение объекта)

at System.Text.Json.JsonSerializer.UnboxOnRead[T](значение объекта)

в System.Text.Json.Serialization.JsonConverter

Код: Выделить всё

1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)   at System.Text.Json.Serialization.Metadata.JsonPropertyInfo
1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& Reader)

в System.Text.Json.Serialization.Converters.ObjectDefaultConverter

Код: Выделить всё

1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)   at System.Text.Json.Serialization.JsonConverter
1.TryRead(Utf8JsonReader& Reader, Type typeToConvert, параметры JsonSerializerOptions, ReadStack& state, T& value, Boolean& isPopulatedValue)

в System.Text.Json.Serialization.JsonConverter

Код: Выделить всё

1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)   at System.Text.Json.Serialization.Metadata.JsonTypeInfo
1.ContinueDeserialize(ReadBufferState&ufferState, JsonReaderState& jsonReaderState, ReadStack& readStack)

at System.Text.Json.Serialization.Metadata.JsonTypeInfo

Код: Выделить всё

1.DeserializeAsync(Stream utf8Json, CancellationToken cancellationToken)   at System.Text.Json.Serialization.Metadata.JsonTypeInfo
1.DeserializeAsObjectAsync(Stream utf8Json, CancellationToken cancelToken)

в Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(контекст InputFormatterContext, кодировка кодировки)

at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(контекст InputFormatterContext, кодировка кодирования)

в Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContextbindingContext)

в Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, параметр ParameterDescriptor, метаданные ModelMetadata, значение объекта, контейнер объекта)

в Microsoft.AspNetCore.Mvc .Controllers.ControllerBinderDelegateProvider.c__DisplayClass0_0.d.MoveNext()

--- Конец трассировки стека из предыдущего местоположения ---

в Microsoft .AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|13_0(вызов ControllerActionInvoker, Task LastTask, Следующее состояние, Область области, Состояние объекта, Логическое значение isCompleted)

в Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker. g__Awaited|20_0(вызов ResourceInvoker, задача LastTask, состояние следующее, область области, состояние объекта, логическое значение isCompleted)

в Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(вызов ResourceInvoker, задача задачи , область IDisposable)

в Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(вызов ResourceInvoker, задача Task, область IDisposable)

в Microsoft.AspNetCore.Authorization .AuthorizationMiddleware.Invoke(контекст HttpContext)

в Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(контекст HttpContext)

в Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext) httpContext)

в Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)

в Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)< /p>


Подробнее здесь: https://stackoverflow.com/questions/790 ... rest-contr
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»