Как вы делаете спокойный экземпляр ссылок в webapi 2?
Объект часто ссылается на экземпляры других объектов. Например, blogpost имеет ссылку на автора, создавшего сообщение.
public class Blogpost {
public string Title {get; set;}
public string Text {get; set;}
public Author Author {get; set;}
}
Принцип RESTful, согласно этому видео @45:00, преобразуется в ссылку на прямой URI. Что-то вроде этого:
{
"Id": 1,
"Title": "My first blogpost",
"Text": "Hello World",
"Author": [ "href" : "http://app.com/api/authors/4"]
}
Как это должно быть сделано в webapi 2? По умолчанию, если вы отключите ленивую загрузку, ссылки просто возвращаются как пустой массив:
{
"Id": 1,
"Title": "My first blogpost",
"Text": "Hello World",
"Author": []
}
Я не знаю, есть ли встроенный способ выполнения этой задачи, но вы можете получить то, что хотите, с помощью настраиваемого адаптера контракта, поставщика настраиваемых значений и использования интерфейса или базового класса для ваших объектов.
Базовый класс Entity: Вероятно, у ваших сущностей уже есть базовый класс, определяющий общее свойство Id, если нет, просто создайте базовый класс и измените класс объектов наследования с DomainEntityBase.
public abstract class DomainEntityBase
{
public int Id { get; set; }
}
Пользовательский разрешитель контрактов. Мы будем использовать настраиваемый разрешающий механизм для изменения поставщика стоимости ссылочных объектов.
public class ReferenceLinkContractResolver : CamelCasePropertyNamesContractResolver
{
#region Methods
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var properties = base.CreateProperties(type, memberSerialization);
var childProperties = properties.Where(p => typeof(DomainEntityBase).IsAssignableFrom(p.PropertyType));
foreach (var c in childProperties)
{
c.ValueProvider = new ReferenceLinkingValueProvider(ReflectionHelper.GetProperty(type, c.PropertyName));
}
return properties;
}
#endregion
}
Поставщик настраиваемого значения. С помощью этого поставщика настраиваемых значений мы меняем сериализацию ссылочной сущности на свойство href.
public class ReferenceLinkingValueProvider : IValueProvider
{
#region Fields
private PropertyInfo m_property;
#endregion
#region Constructors
public ReferenceLinkingValueProvider(PropertyInfo property)
{
m_property = property;
}
#endregion
#region Methods
public object GetValue(object target)
{
if (target == null)
{
return null;
}
var value = m_property.GetValue(target);
var entity = value as DomainEntityBase;
if (entity == null)
{
return value;
}
// If your resources are in plural, you will need some helper method
// to put in right plural (remember the resources with 'y' ends).
var resourceName = entity.GetType().Name;
// Here is where the real work happens. You change the entire entity
// serialization to just the href property.
return new
{
href = "http://app.com/api/{0}/{1}".With(resourceName, entity.Id)
};
}
public void SetValue(object target, object value)
{
m_property.SetValue(target, value);
}
#endregion
}
Теперь, в вашем веб-конфигураторе api, установите ContractResolver вашего json-форматирования:
var formatters = GlobalConfiguration.Configuration.Formatters;
formatters.JsonFormatter.SerializerSettings.ContractResolver = new ReferenceLinkContractResolver();
Примечание. Некоторые методы помощника и расширения, такие как "С", поступают из библиотеки HelperSharp.