webapi 2.0中的实例引用/链接

本文关键字:引用 链接 实例 webapi | 更新日期: 2023-09-27 18:18:38

如何在webapi 2中实现restful实例引用?

对象通常有对其他对象实例的引用。例如,一个blogpost有一个对创建该post的作者的引用。

public class Blogpost {
   public string Title {get; set;}
   public string Text {get; set;}
   public Author Author {get; set;}
}

根据这个视频@ 45:00,RESTful原则是将引用转换为直接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": []
}

webapi 2.0中的实例引用/链接

我不知道是否有一个内置的方法来完成这个任务,但是你可以使用一个自定义的合约解析器,一个自定义的值提供程序,并在你的实体上使用一个接口或基类来得到你想要的。

实体基类:可能你的实体已经有一个基类定义了公共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
}

现在,在你的web api配置中,设置json格式化器的ContractResolver:

var formatters = GlobalConfiguration.Configuration.Formatters;
formatters.JsonFormatter.SerializerSettings.ContractResolver = new ReferenceLinkContractResolver();

注意:一些帮助和扩展方法,比如"With"方法