Сериализация общей модели С# в xml в .net core 3.0

Я использую .net core 3.0 для создания веб-API. Я хочу сериализовать универсальную модель в XML. Но по умолчанию он сериализует общую модель только в JSON.

Когда я попытался сериализовать простую модель в XML, она правильно сериализуется в XML.

В зависимости от переданных заголовков я хочу сериализовать модель. Вот что я сделал до сих пор:

В файле startup.cs:

services.AddControllers(options =>{
        options.RespectBrowserAcceptHeader = true; // false by default
    }).
    AddXmlSerializerFormatters().

Ниже приведен пример кода:

Моя общая модель:

public class ApiResponseModel<T>
{
    public int ErrorCode { get; set; }
    public string ErrorMessage { get; set; }
    public T Data { get; set; }

    public ApiResponseModel(int errorCode, string errorMessage, T data)
    {
        this.ErrorCode = errorCode;
        this.ErrorMessage = errorMessage;
        this.Data = data;
    }
}

Действие для возврата данных:

[HttpGet]
public async Task<IActionResult> Get()
{
    IEnumerable<RoleDTO> roleList = null;
    roleList = await _repository.RoleRepository.GetAllRolesAsync();
    var data = new ApiResponseModel<IEnumerable<RoleDTO>>(200, "Success", roleList);
    return Ok(data);
}

Этот ответ возвращает JSON, хотя заголовок Accept указан как application/xml.

Но если я просто возвращаю roleList, он дает ответ в формате XML.

[HttpGet]
public async Task<IActionResult> Get()
{
    IEnumerable<RoleDTO> roleList = null;
    roleList = await _repository.RoleRepository.GetAllRolesAsync();
    return Ok(roleList);
} 

Как я могу получить ответ XML и для общих моделей?


person Sunny12    schedule 07.11.2019    source источник


Ответы (1)


Есть две причины:

  1. Ваш ApiResponseModel<T> не имеет конструктора без параметров.
  2. Вы используете XmlSerializer от AddXmlSerializerFormatters() (вместо XML DataContractSerializer), который по умолчанию не будет заботиться о сериализации IEnumerable<T>.

Чтобы решить эту проблему, добавьте конструктор без параметров:

public class ApiResponseModel<T>
{
    public int ErrorCode { get; set; }
    public string ErrorMessage { get; set; }
    public T Data { get; set; }
    public ApiResponseModel() { }       // add a parameterless constructor

    public ApiResponseModel(int errorCode, string errorMessage, T data)
    {
        this.ErrorCode = errorCode;
        this.ErrorMessage = errorMessage;
        this.Data = data;
    }
}

И рассмотрите возможность добавления форматирования XML DataContractSerializer, чтобы позаботиться о IEnumerable<T> сериализации:

services.AddControllersWithViews(opts =>{
    opts.RespectBrowserAcceptHeader = true;
})
.AddXmlDataContractSerializerFormatters()
.AddXmlSerializerFormatters()
person itminus    schedule 08.11.2019
comment
ваше решение сработало как шарм. Большое спасибо. Но как решить эту проблему, включив конструктор без параметров для модели? Можете ли вы вкратце рассказать об этом или как вы указали точные проблемы? Заранее спасибо. - person Sunny12; 08.11.2019
comment
@ Sunny12 Sunny12 Я не такой умный человек, как Джон Скит, который может компилировать и запускать код в мозгу. Поэтому я просто проверяю журнал, и журнал сообщает мне, что должен быть конструктор без параметров :) - person itminus; 11.11.2019
comment
хорошо, тогда было бы плохо не заметить эти журналы. В любом случае, спасибо. @итминус - person Sunny12; 11.11.2019