[英]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);
}
Contact
和ContactDto
實現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.