簡體   English   中英

帶有 Simple.OData.Client 的 DTO

[英]DTOs with Simple.OData.Client

在我的服務器中,我有以下設置:

EntitySet<Contact>("Contacts");
EntityType<ContactDto>();

這是 controller 操作:

[EnableQuery]
public ActionResult<IQueryable<ContactDto>> Get()
{
  return Ok(_DbContext.Contacts.Select(c => new ContactDto(c)));
}

[EnableQuery]
public async Task<ActionResult<Contact>> Get(int key)
{
  return await _DbContext.Contacts.FindAsync(key);
}

ContactContactDto實現IContact ,此外它們彼此不知道。

查詢服務器時(使用Contacts路由),我得到了預期的結果,但在客戶端我試圖做:

var settings = new ODataClientSettings(new Uri(
    $"https://localhost:{Constants.Port}/{Constants.Api}"));
var client = new ODataClient(settings);

var result = await client
    .For<Contact>()
    .FindEntriesAsync();

我遇到了一個例外:

Microsoft.OData.ODataException: 'The context URL 'https://localhost:54687/api/$metadata#Contacts/ODataDtoRepro.Models.ContactDto' is invalid

堆棧跟蹤:

at Microsoft.OData.JsonLight.ODataJsonLightContextUriParser.ParseContextUriFragment(String fragment, Func`3 clientCustomTypeResolver, Boolean throwIfMetadataConflict, Boolean& isUndeclared)
   at Microsoft.OData.JsonLight.ODataJsonLightContextUriParser.ParseContextUri(ODataPayloadKind expectedPayloadKind, Func`3 clientCustomTypeResolver, Boolean throwIfMetadataConflict)
   at Microsoft.OData.JsonLight.ODataJsonLightContextUriParser.Parse(IEdmModel model, String contextUriFromPayload, ODataPayloadKind payloadKind, Func`3 clientCustomTypeResolver, Boolean needParseFragment, Boolean throwIfMetadataConflict)
   at Microsoft.OData.JsonLight.ODataJsonLightDeserializer.ReadPayloadStart(ODataPayloadKind payloadKind, PropertyAndAnnotationCollector propertyAndAnnotationCollector, Boolean isReadingNestedPayload, Boolean allowEmptyPayload)
   at Microsoft.OData.JsonLight.ODataJsonLightReader.ReadAtStartImplementation()
   at Microsoft.OData.ODataReaderCore.ReadImplementation()
   at Microsoft.OData.ODataReaderCore.ReadSynchronously()
   at Microsoft.OData.ODataReaderCore.InterceptException[T](Func`1 action)
   at Microsoft.OData.ODataReaderCore.Read()
   at Simple.OData.Client.V4.Adapter.ResponseReader.ReadResponse(ODataReader odataReader, IODataResponseMessageAsync responseMessage)
   at Simple.OData.Client.V4.Adapter.ResponseReader.<GetResponseAsync>d__3.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Simple.OData.Client.ODataClient.<ExecuteRequestWithResultAsync>d__147`1.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Simple.OData.Client.ODataClient.<FindAnnotatedEntriesAsync>d__88.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Simple.OData.Client.ODataClient.<FindEntriesAsync>d__89.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Simple.OData.Client.FluentClientBase`2.<FilterAndTypeColumnsAsync>d__91.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Client.Program.<Main>d__0.MoveNext() in D:\Users\Shimmy\Documents\Visual Studio 2019\Projects\ODataDtoRepro\Client\Program.cs:line 16

我在GitHub上做了一個重現項目。

我創建了另一個repro 分支,它嘗試了不同的方法,因此它使用在 EDM model 中注冊的共享基類,而不是接口。 盡管如此,Simple.OData.Client 還是無法繞過它。 另請查看我對這個問題的評論。

如何讓 DTO 與 OData 一起使用?

更新

可能的解決方案:使用動作/功能。 嘗試對其進行試驗,但無法使其在客戶端和服務器之間工作,請參閱答案了解更多信息。

我認為問題在於這兩個對象之間沒有關系。 我刪除了您的代碼並通過刪除實體集使其正常工作

var edmModel = new ODataConventionModelBuilder();
edmModel.EntitySet<ContactDto>("Contacts");
routeBuilder.MapODataServiceRoute("API Route", Constants.Api, edmModel.GetEdmModel());

並通過讓 ContactD 擴展聯系人

public class ContactDto : Contact

由於contact 是contact dto 的子集,因此它按預期返回,沒有錯誤。 如果您希望我將代碼提交給您的 github,請告訴我。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM