我有一个具有 OData 后端的 Blazor WASM 应用程序。我正在尝试配置我的一个模型的 NavigationProperty,以便我可以使用$expand=
查询参数返回更多数据,但是在尝试发出PATCH
请求时我不断收到以下错误(GET
工作得很好):
Microsoft.OData.ODataException: The property 'JobId' does not exist on type 'Coin.ODataOrderHeader'. Make sure to only use property names that are defined by the type or mark the type as open type.
但它确实存在!不只是在模型中:
public partial class ODataOrderHeader
{
[Key]
public int OrderId { get; set; }
[Column("JobID")]
[ForeignKey("Job")]
public int JobId { get; set; }
...
[System.Text.Json.Serialization.JsonPropertyName("Job")]
public virtual Jobs Job { get; set; }
}
但在$metadata
文档中也是如此:
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
<edmx:DataServices>
<Schema Namespace="Coin" xmlns="http://docs.oasis-open.org/odata/ns/edm">
...
<EntityType Name="ODataOrderHeader">
<Key>
<PropertyRef Name="OrderId" />
</Key>
<Property Name="OrderId" Type="Edm.Int32" Nullable="false" />
<Property Name="JobId" Type="Edm.Int32" />
...
<NavigationProperty Name="Job" Type="Coin.Jobs">
<ReferentialConstraint Property="JobId" ReferencedProperty="JobId" />
</NavigationProperty>
</EntityType>
...
</Schema>
</edmx:DataServices>
</edmx:Edmx>
下面是创建模型的代码:
private IEdmModel GetEdmModel()
{
var builder = new ODataConventionModelBuilder();
builder.Namespace = "Coin";
builder.ContainerName = "CoinContainer";
...
var orders = builder.EntitySet<ODataOrderHeader>("Orders");
return builder.GetEdmModel();
}
我可能应该指出,ODataOrderHeader
更多的是 DTO 类型,而Jobs
EF 脚手架类型。
下面是Simple.OData.Client
调用 API 的代码:
private async void UpdateItem()
{
ODataClient client = new ODataClient(new ODataClientSettings(HttpClient, new Uri("odata", UriKind.Relative)));
await client.For<ODataOrderHeader>("Orders")
.Key(currentOrder.OrderId)
.Set(currentOrder)
.UpdateEntryAsync();
}
这是上面代码调用的控制器操作:
[ODataRoute("/orders({key})")]
public async Task<IActionResult> Patch([FromODataUri] int key, Delta<ODataOrderHeader> order)
{
if (!ModelState.IsValid)
return BadRequest();
...
}
最后,完整的错误消息:
Unhandled Exception:
Microsoft.OData.ODataException: The property 'JobId' does not exist on type 'Coin.ODataOrderHeader'. Make sure to only use property names that are defined by the type or mark the type as open type.
at Microsoft.OData.WriterValidationUtils.ValidatePropertyDefined (Microsoft.OData.PropertySerializationInfo propertyInfo, System.Boolean throwOnUndeclaredProperty) <0x61a9028 + 0x00098> in <filename unknown>:0
at Microsoft.OData.JsonLight.ODataJsonLightPropertySerializer.WritePropertyInfo (Microsoft.OData.ODataPropertyInfo propertyInfo, Microsoft.OData.Edm.IEdmStructuredType owningType, System.Boolean isTopLevel, Microsoft.OData.IDuplicatePropertyNameChecker duplicatePropertyNameChecker, Microsoft.OData.Evaluation.ODataResourceMetadataBuilder metadataBuilder) <0x6120d78 + 0x000f8> in <filename unknown>:0
at Microsoft.OData.JsonLight.ODataJsonLightPropertySerializer.WriteProperty (Microsoft.OData.ODataProperty property, Microsoft.OData.Edm.IEdmStructuredType owningType, System.Boolean isTopLevel, Microsoft.OData.IDuplicatePropertyNameChecker duplicatePropertyNameChecker, Microsoft.OData.Evaluation.ODataResourceMetadataBuilder metadataBuilder) <0x61203e8 + 0x00018> in <filename unknown>:0
at Microsoft.OData.JsonLight.ODataJsonLightPropertySerializer.WriteProperties (Microsoft.OData.Edm.IEdmStructuredType owningType, System.Collections.Generic.IEnumerable`1[T] properties, System.Boolean isComplexValue, Microsoft.OData.IDuplicatePropertyNameChecker duplicatePropertyNameChecker, Microsoft.OData.Evaluation.ODataResourceMetadataBuilder metadataBuilder) <0x6011c28 + 0x00048> in <filename unknown>:0
at Microsoft.OData.JsonLight.ODataJsonLightWriter.StartResource (Microsoft.OData.ODataResource resource) <0x5ef5478 + 0x003d6> in <filename unknown>:0
at Microsoft.OData.ODataWriterCore+<>c__DisplayClass121_0.<WriteStartResourceImplementation>b__0 () <0x5ed80f0 + 0x00082> in <filename unknown>:0
at Microsoft.OData.ODataWriterCore.InterceptException (System.Action action) <0x5ed3f20 + 0x00042> in <filename unknown>:0
at Microsoft.OData.ODataWriterCore.WriteStartResourceImplementation (Microsoft.OData.ODataResource resource) <0x5ed3a78 + 0x00076> in <filename unknown>:0
at Microsoft.OData.ODataWriterCore+<>c__DisplayClass49_0.<WriteStartAsync>b__0 () <0x5ed3628 + 0x0000c> in <filename unknown>:0
at Microsoft.OData.TaskUtils.GetTaskForSynchronousOperation (System.Action synchronousOperation) <0x5ed34e0 + 0x0000a> in <filename unknown>:0
--- End of stack trace from previous location where exception was thrown ---
at Simple.OData.Client.V4.Adapter.RequestWriter.WriteEntryPropertiesAsync (Microsoft.OData.ODataWriter entryWriter, Microsoft.OData.ODataResource entry, System.Collections.Generic.IDictionary`2[TKey,TValue] links) <0x5ed2260 + 0x000f2> in <filename unknown>:0
at Simple.OData.Client.V4.Adapter.RequestWriter.WriteEntryContentAsync (System.String method, System.String collection, System.String commandText, System.Collections.Generic.IDictionary`2[TKey,TValue] entryData, System.Boolean resultRequired) <0x5477750 + 0x0049c> in <filename unknown>:0
at Simple.OData.Client.RequestWriterBase.CreateUpdateRequestAsync (System.String collection, System.String entryIdent, System.Collections.Generic.IDictionary`2[TKey,TValue] entryKey, System.Collections.Generic.IDictionary`2[TKey,TValue] entryData, System.Boolean resultRequired) <0x5814b98 + 0x0020c> in <filename unknown>:0
at Simple.OData.Client.RequestBuilder.UpdateRequestAsync (System.Boolean resultRequired, System.Threading.CancellationToken cancellationToken) <0x577cd28 + 0x00386> in <filename unknown>:0
at Simple.OData.Client.ODataClient.UpdateEntryAsync (Simple.OData.Client.FluentCommand command, System.Boolean resultRequired, System.Threading.CancellationToken cancellationToken) <0x577bcc8 + 0x00162> in <filename unknown>:0
at Simple.OData.Client.BoundClient`1[T].UpdateEntryAsync (System.Boolean resultRequired, System.Threading.CancellationToken cancellationToken) <0x576d9a0 + 0x00230> in <filename unknown>:0
at Coin.Client.Pages.OrderEdit.UpdateItem () [0x000ac] in C:\Users\trichardson\source\Workspaces\Corsi\COIN2\Client\Pages\OrderEdit.razor:393
at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__7_1 (System.Object state) <0x6547930 + 0x0000c> in <filename unknown>:0
at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context (System.Object state) <0x65478e0 + 0x00022> in <filename unknown>:0
at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) <0x3112fc8 + 0x00100> in <filename unknown>:0
at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) <0x310b7d8 + 0x00010> in <filename unknown>:0
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem () <0x5743290 + 0x00038> in <filename unknown>:0
at System.Threading.ThreadPoolWorkQueue.Dispatch () <0x39a89b8 + 0x00102> in <filename unknown>:0
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback () <0x39a4578 + 0x00000> in <filename unknown>:0
[ERROR] FATAL UNHANDLED EXCEPTION: Microsoft.OData.ODataException: The property 'JobId' does not exist on type 'Coin.ODataOrderHeader'. Make sure to only use property names that are defined by the type or mark the type as open type.
at Microsoft.OData.WriterValidationUtils.ValidatePropertyDefined (Microsoft.OData.PropertySerializationInfo propertyInfo, System.Boolean throwOnUndeclaredProperty) <0x61a9028 + 0x00098> in <filename unknown>:0
at Microsoft.OData.JsonLight.ODataJsonLightPropertySerializer.WritePropertyInfo (Microsoft.OData.ODataPropertyInfo propertyInfo, Microsoft.OData.Edm.IEdmStructuredType owningType, System.Boolean isTopLevel, Microsoft.OData.IDuplicatePropertyNameChecker duplicatePropertyNameChecker, Microsoft.OData.Evaluation.ODataResourceMetadataBuilder metadataBuilder) <0x6120d78 + 0x000f8> in <filename unknown>:0
at Microsoft.OData.JsonLight.ODataJsonLightPropertySerializer.WriteProperty (Microsoft.OData.ODataProperty property, Microsoft.OData.Edm.IEdmStructuredType owningType, System.Boolean isTopLevel, Microsoft.OData.IDuplicatePropertyNameChecker duplicatePropertyNameChecker, Microsoft.OData.Evaluation.ODataResourceMetadataBuilder metadataBuilder) <0x61203e8 + 0x00018> in <filename unknown>:0
at Microsoft.OData.JsonLight.ODataJsonLightPropertySerializer.WriteProperties (Microsoft.OData.Edm.IEdmStructuredType owningType, System.Collections.Generic.IEnumerable`1[T] properties, System.Boolean isComplexValue, Microsoft.OData.IDuplicatePropertyNameChecker duplicatePropertyNameChecker, Microsoft.OData.Evaluation.ODataResourceMetadataBuilder metadataBuilder) <0x6011c28 + 0x00048> in <filename unknown>:0
at Microsoft.OData.JsonLight.ODataJsonLightWriter.StartResource (Microsoft.OData.ODataResource resource) <0x5ef5478 + 0x003d6> in <filename unknown>:0
at Microsoft.OData.ODataWriterCore+<>c__DisplayClass121_0.<WriteStartResourceImplementation>b__0 () <0x5ed80f0 + 0x00082> in <filename unknown>:0
at Microsoft.OData.ODataWriterCore.InterceptException (System.Action action) <0x5ed3f20 + 0x00042> in <filename unknown>:0
at Microsoft.OData.ODataWriterCore.WriteStartResourceImplementation (Microsoft.OData.ODataResource resource) <0x5ed3a78 + 0x00076> in <filename unknown>:0
at Microsoft.OData.ODataWriterCore+<>c__DisplayClass49_0.<WriteStartAsync>b__0 () <0x5ed3628 + 0x0000c> in <filename unknown>:0
at Microsoft.OData.TaskUtils.GetTaskForSynchronousOperation (System.Action synchronousOperation) <0x5ed34e0 + 0x0000a> in <filename unknown>:0
--- End of stack trace from previous location where exception was thrown ---
at Simple.OData.Client.V4.Adapter.RequestWriter.WriteEntryPropertiesAsync (Microsoft.OData.ODataWriter entryWriter, Microsoft.OData.ODataResource entry, System.Collections.Generic.IDictionary`2[TKey,TValue] links) <0x5ed2260 + 0x000f2> in <filename unknown>:0
at Simple.OData.Client.V4.Adapter.RequestWriter.WriteEntryContentAsync (System.String method, System.String collection, System.String commandText, System.Collections.Generic.IDictionary`2[TKey,TValue] entryData, System.Boolean resultRequired) <0x5477750 + 0x0049c> in <filename unknown>:0
at Simple.OData.Client.RequestWriterBase.CreateUpdateRequestAsync (System.String collection, System.String entryIdent, System.Collections.Generic.IDictionary`2[TKey,TValue] entryKey, System.Collections.Generic.IDictionary`2[TKey,TValue] entryData, System.Boolean resultRequired) <0x5814b98 + 0x0020c> in <filename unknown>:0
at Simple.OData.Client.RequestBuilder.UpdateRequestAsync (System.Boolean resultRequired, System.Threading.CancellationToken cancellationToken) <0x577cd28 + 0x00386> in <filename unknown>:0
at Simple.OData.Client.ODataClient.UpdateEntryAsync (Simple.OData.Client.FluentCommand command, System.Boolean resultRequired, System.Threading.CancellationToken cancellationToken) <0x577bcc8 + 0x00162> in <filename unknown>:0
at Simple.OData.Client.BoundClient`1[T].UpdateEntryAsync (System.Boolean resultRequired, System.Threading.CancellationToken cancellationToken) <0x576d9a0 + 0x00230> in <filename unknown>:0
at Coin.Client.Pages.OrderEdit.UpdateItem () [0x000ac] in C:\Users\trichardson\source\Workspaces\Corsi\COIN2\Client\Pages\OrderEdit.razor:393
at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__7_1 (System.Object state) <0x6547930 + 0x0000c> in <filename unknown>:0
at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context (System.Object state) <0x65478e0 + 0x00022> in <filename unknown>:0
at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) <0x3112fc8 + 0x00100> in <filename unknown>:0
at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) <0x310b7d8 + 0x00010> in <filename unknown>:0
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem () <0x5743290 + 0x00038> in <filename unknown>:0
at System.Threading.ThreadPoolWorkQueue.Dispatch () <0x39a89b8 + 0x00102> in <filename unknown>:0
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback () <0x39a4578 + 0x00000> in <filename unknown>:0
Uncaught ExitStatusThe program '' has exited with code -1 (0xffffffff).
是否有我遗漏的配置错误或控制器操作有问题?