На моем сервере у меня есть следующие настройки:
EntitySet<Contact>("Contacts");
EntityType<ContactDto>();
Вот действия контроллера:
[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
StackTrace:
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 .
Я создал еще одну ветвь репро , которая использует другой подход, так что он использует общий базовый класс, зарегистрированный в модели EDM, вместоинтерфейс. Тем не менее, Simple.OData.Client не может обойти это. Пожалуйста, проверьте также мои комментарии по этой проблеме.
Как мне заставить DTO работать с OData?
Обновление
Возможное решение: использование действий /функции. Попытался поэкспериментировать с ним, но не смог заставить его работать между клиентом и сервером, см. этот ответ для получения дополнительной информации.