9

我很难从 WCF 数据服务迁移到 web api odata v4。我被困在以下问题上:

odata web api 似乎不支持@odata.bind。

我找到了以下链接: https ://github.com/OData/WebApi/issues/158 有人建议ODataEntityDeserializer像这样实现自己的派生类:

public class ExtendedODataEntityDeserializer : ODataEntityDeserializer
{
    public ExtendedODataEntityDeserializer(ODataDeserializerProvider deserializerProvider) : base(deserializerProvider)
    {
    }

    public override void ApplyNavigationProperty(
        object entityResource, 
        ODataNavigationLinkWithItems navigationLinkWrapper, 
        IEdmEntityTypeReference entityType, 
        ODataDeserializerContext readContext)
    {
        base.ApplyNavigationProperty(entityResource, navigationLinkWrapper, entityType, readContext);

        foreach (var childItem in navigationLinkWrapper.NestedItems)
        {
            var entityReferenceLink = childItem as ODataEntityReferenceLinkBase;

            if (entityReferenceLink != null)
            {
                var navigationPropertyName = navigationLinkWrapper.NavigationLink.Name;
                Uri referencedEntityUrl = entityReferenceLink.EntityReferenceLink.Url;

                if (!referencedEntityUrl.IsAbsoluteUri)
                {
                    referencedEntityUrl = new Uri(readContext.Request.RequestUri, referencedEntityUrl);
                }

                var linkedEntities = (Model.LinkedEntityCollection)entityResource;
                linkedEntities.Add(navigationPropertyName, referencedEntityUrl);
            }
        }
    }
}

LinkedEntityCollection 是我的实体类的基类,用作字典(MyEntity : LinkedEntityCollection实现很简单)。

public class ExtendedODataDeserializerProvider : ODataDeserializerProvider
{
    private static ExtendedODataDeserializerProvider _instance = null;

    private ExtendedODataDeserializerProvider()
    {
        _instance = this;
    }

    public static ExtendedODataDeserializerProvider Instance
    {
        get { return _instance ?? new ExtendedODataDeserializerProvider(); }
    }

    public override ODataEdmTypeDeserializer GetEdmTypeDeserializer(Microsoft.OData.Edm.IEdmTypeReference edmType)
    {
        return DefaultODataDeserializerProvider.Instance.GetEdmTypeDeserializer(edmType);
    }

    public override ODataDeserializer GetODataDeserializer(Microsoft.OData.Edm.IEdmModel model, Type type, System.Net.Http.HttpRequestMessage request)
    {
        return new ExtendedODataEntityDeserializer(DefaultODataDeserializerProvider.Instance);
    }
}

在 http 配置中注册:

public static void Register(HttpConfiguration config)
{
    ODataModelBuilder builder = new ODataConventionModelBuilder();

    // registering entities: builder.EntitySet<T>("EntityName") ...

    ODataBatchHandler batchHandler = new DefaultODataBatchHandler(new HttpServer(config));
    batchHandler.MessageQuotas.MaxOperationsPerChangeset = 10;
    batchHandler.MessageQuotas.MaxPartsPerBatch = 10;

    var odataFormatters = ODataMediaTypeFormatters.Create(DefaultODataSerializerProvider.Instance, ExtendedODataDeserializerProvider.Instance);

    config.Formatters.Clear();
    config.Formatters.AddRange(odataFormatters);

    config.MapODataServiceRoute(routeName: "Central", routePrefix: "Odata", model: builder.GetEdmModel(), batchHandler: batchHandler);
}

但是,如果您确实使用此 hack,您将失去在实体之间创建链接的能力,如本文所述:http ://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/ odata-v4/实体关系-in-odata-v4

“@odata.id”没有被解析,假设它是函数中的一个实体ODataEntityDeserializer.Read。也许我在这里基本上遗漏了一些东西,因为我对 web api 相当陌生(config.Formatters.Clear()似乎有点苛刻)。或者是否有任何其他解决方法来支持@odata.bind?

这个功能有没有可能在不久的将来实现?

更新

我得到了我的黑客工作。问题是我应该派生ExtendedODataDeserializerProviderDefaultODataDeserializerProvider不是相应地ODataDeserializerProvider返回反序列化器:

public override ODataDeserializer GetODataDeserializer(
     Microsoft.OData.Edm.IEdmModel model, 
     Type type,     
     System.Net.Http.HttpRequestMessage request)
{
    if (type == typeof(ODataActionParameters) || 
        type == typeof(ODataUntypedActionParameters) || 
        type == typeof(Uri))
    {
        return base.GetODataDeserializer(model, type, request);
    }

    return new ExtendedODataEntityDeserializer(DefaultODataDeserializerProvider.Instance);
 }

所以剩下的问题是:我们什么时候在 asp.net webapi odata 中获得@odata.bind 支持?

4

1 回答 1

1

试图回答

所以剩下的问题是:我们什么时候在 asp.net webapi odata 中获得@odata.bind 支持?

vnext repo 中似乎有一个与此相关的功能。但是,该问题被标记为影响较小。 https://github.com/OData/WebApi/milestones/vNext,因此无法知道何时实现此功能。

于 2015-06-28T20:35:56.243 回答