#c# #.net #api #.net-core #interface
Вопрос:
Я получаю эту систему сообщений об ошибках.Исключение NotSupportedException: Десериализация типов интерфейсов не поддерживается.
при вызове API, который принял запрос, как указано ниже.
пример
[HttpPost] public IActionResult AddSomeData(MyClass MyClass) { return Ok(); } public class MyClass : MyInterface { return Ok(); } public interface MyInterface { public string SomeOtherProperties { get; set; } public MyInterface Property { get; set; } //Or reference of any other interface }
Я пробовал примеры, приведенные в Интернете, такие как создание конкретного класса и добавление атрибута поверх свойства. Но это не помогает.
В качестве обходного пути я удалил общедоступное свойство MyInterface { get; set; } и добавил общедоступное свойство MyClass { get; set; }
Есть ли лучшее решение для этого?
Комментарии:
1. Вы используете что-то вроде ASP.NET или ASP.NET Ядро? Я предполагаю, что это так,
[HttpPost]
но, с другой стороны, другие библиотеки могли бы следовать аналогичной схеме.2. На очень наивном уровне десериализатору придется
new()
обновить ваш экземпляр, а затем установить значения для каждого свойства в этом экземпляре, как десериализатор обновит интерфейс?3. Привязка MVC требует, чтобы все типы можно было обнаружить с помощью отражения во время запуска (единственным реальным исключением являются общие коллекции). Хотя вы можете написать свой собственный поставщик привязки для создания подтипов, я бы не рекомендовал этого делать. Можете ли вы использовать универсальные средства для определения типа
Property
?
Ответ №1:
Проблема с десериализацией в интерфейс заключается в том, что вы теряете информацию
public class MyClass : MyInterface { public string SomeOtherProperties { get; set; } public MyInterface Property { get; set; } public string importantString { get; set; } = "Don't lose me please"; } public interface MyInterface { string SomeOtherProperties { get; set; } MyInterface Property { get; set; } }
Возьмем приведенный выше пример, попытка десериализации в интерфейс потребует указания десериализатору знать только о свойствах интерфейса, а любые другие поля, которые предоставляет ваш конечный пользователь, будут полностью удалены. Кроме того, у вас могут быть методы в конкретном классе, которые поддерживают свойства интерфейса, которые должны существовать.
Есть несколько вариантов, связанных с отражением, которые вы могли бы использовать, если вам нужен API для поддержки нескольких реализаций интерфейса, но вопрос в том, зачем вам нужен интерфейс в первую очередь? Предполагается, что API должен четко определять, что должно быть предоставлено пользователем, абстрагирование этого с помощью интерфейса, который должен быть реализован каким-то конкретным классом, кажется плохой идеей.
Редактировать: если все, что вам нужно, — это общая информация, и в ней нет ничего необычного, вы можете просто использовать MyInterface в качестве стандартного класса
public class MyClass : MyInterface { public string nonImportantString { get; set; } = "lose me"; } public class MyInterface { public string SomeOtherProperties { get; set; } public MyInterface Property { get; set; } }
При этом ваш api чист, и вы можете десериализоваться нормально