Highrise Api, Тема данных не публикуется с RestSharp

Я пытаюсь использовать Highrise Api с оболочкой.NET 4.5 от scottschluer, чтобы публиковать новых людей в нашей учетной записи Highrise вместе с любыми пользовательскими данными, которые они вводят.

Проблема, с которой я сталкиваюсь, связана с пользовательскими данными. Объект person публикуется просто отлично, но поля данных субъекта не включаются в публикацию.

Я наткнулся на этот пост: Highrise Custom Fields. Похоже, что то, чего не хватало, было type="array" атрибут из subject_datas поле. Я проверил эту гипотезу, вручную создав запрос, используя сериализованное значение объекта, который я пытался опубликовать. Результатом этого теста стала успешная публикация на сервер со всеми заполненными пользовательскими полями данных.

Я попытался расширить классы из сборки-оболочки, чтобы добавить этот отсутствующий атрибут в список, но это все равно не сработало. У объекта Person есть свойство для объектов List of SubjectData. Я переписал это свойство в дочернем классе, чтобы вместо него использовать собственный класс. Таким образом, я мог бы добавить свойство для использования в качестве атрибута. Этот пользовательский класс все еще не работал.

После просмотра кода для XmlSerializer от RestSharp выясняется, что он добавит список элементов только тогда, когда этот объект реализует IList. Это не было проблемой, я смог заставить это работать, но код, кажется, не позволяет добавлять атрибуты к элементу списка. Он только смотрит на потомков класса списка и игнорирует любые другие свойства объекта.

Итак, мой вопрос заключается в следующем:

Можно ли применить атрибуты к свойству списка в RestSharp, или есть другой способ добавить type="array" приписать data_subjects xml узел перед отправкой запроса?

1 ответ

Решение

В конце концов я решил проблему самостоятельно, создав новый класс запросов, который бы создавал RestRequest с использованием пользовательского XmlSerializer.

Затем я расширил класс Person и спрятал свойство за свойством объекта списка

До:

[SerializeAs(Name = "subject_datas")]
public List<SubjectData> SubjectDatas { get; set; }

После:

[SerializeAs(Name = "subject_datas")]
public new SubjectDataList SubjectDatas { get; set; }

SubjectDataList класс это просто оболочка для List<SubjectData>,

SubjectDataList реализует интерфейс под названием ISerializeList<SubjectData>который определяется как:

interface ISerializeList : IEnumerable {}
interface ISerializeList<T> :IEnumerable<T>, ISerializeList {}

SubjectDataList также имеет свойство type для отображения атрибута type на узле subjectdatas запроса rest.

[SerializeAs(Name = "type", Attribute = true)]
public string Type { get; set; } = "array";

Затем я сделал класс под названием XmlListSerializer который реализует ISerializer, Я скопировал реализацию XmlSerializer, но сделал несколько модификаций. в Map метод, есть часть, которая проверяет, является ли переменная rawValue является IList, Я немного изменил эту часть, и добавил пункт для моего XmlListSerializer учебный класс.

Итак, теперь это выглядит так:

if (propType.IsPrimitive || propType.IsValueType || propType == typeof(string)) {
    //...
} else if (rawValue is IList) {
    ProcessIList((IList) rawValue, element);
} else if (rawValue is ISerializeList) {
    ProcessISerializeList((ISerializeList) rawValue, element);
} else {
    Map(element, rawValue);
}

куда ProcessIList а также ProcessISerializeList определяются как:

private void ProcessIList(IList list, XElement element) {
    ProcessIEnumerable(list, element);
}
private void ProcessISerializeList(ISerializeList list, XElement element) {
    ProcessIEnumerable(list, element);
    Map(element, list);
}
private void ProcessIEnumerable(IEnumerable list, XElement element) {
    var itemTypeName = "";
    foreach (var item in list) {
        if (itemTypeName == "") {
            var type = item.GetType();
            var setting = type.GetAttribute<SerializeAsAttribute>();

            itemTypeName = setting != null && setting.Name.HasValue() ? setting.Name : type.Name;
        }

        var instance = new XElement(itemTypeName.AsNamespaced(Namespace));

        Map(instance, item);
        element.Add(instance);
    }
}

Я надеюсь, что этот ответ сможет помочь кому-либо еще, имеющему проблемы с этой проблемой.

Другие вопросы по тегам