Microsoft.AspNetCore.Odata v7.4.0 NuGet を使用している ASP.NET Core 3.1x API を使用しており、Simple.OData.V4.Client v5 を使用している ASP.NET Core 3.1v Web クライアントを使用しています。 .12.0
Simple.Odata クライアントから、関連する LineItem オブジェクト (マスター/詳細) を含む Order オブジェクトを投稿しようとしています。Order オブジェクトは API に正しく渡されていますが、関連する LineItem コレクションは渡されていません。
これが私の Order クラスです。
public class Order
{
public Guid Id { get; set; }
public DateTimeOffset DateOfOrder { get; set; }
public string PurchaseOrderNumber { get; set; }
public decimal Subtotal { get; set; }
public decimal Discount { get; set; }
public decimal Shipping { get; set; }
public decimal SalesTax { get; set; }
public decimal Total { get; set; }
public List<OrderLineItem> OrderLineItems { get; set; } = new List<OrderLineItem>();
}
これが私の OrderLineItem クラスです。
public class OrderLineItem : BaseModel
{
public Guid Id { get; set; }
public Guid OrderId { get; set; }
public Order Order { get; set; }
public Guid ProductId { get; set; }
public string ProductName { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
public decimal Discount { get; set; }
public decimal Total { get; set; }
}
クライアント Web サイト アプリケーションの ODataService のメソッドを次に示します。
public async Task<Result<Order>> CreateOrderAsync(Order req, CancellationToken cancellationToken)
{
try
{
var baseUrl = cdUtilities.GetBaseApiUrl();
var accessToken = await GetAccessToken();
var client = new ODataClient(SetODataToken(baseUrl, accessToken));
var response = await client.For<Order>()
.Set(req).InsertEntryAsync(cancellationToken);
return Result.Ok(response);
}
catch (WebRequestException badRequest)
{
var odataErrorResponse = JsonConvert.DeserializeObject<ExceptionResponse>(badRequest.Response);
var errorMessage = $"Bad Request: The API returned an HTTP Status Code 400.{Environment.NewLine}";
if (odataErrorResponse.Error != null)
{
foreach (var errorDetail in odataErrorResponse.Error.Details)
{
errorMessage = $"{errorMessage} {errorDetail.Message}{Environment.NewLine}";
}
}
logger.LogError(badRequest, errorMessage);
return Result.Fail<Order>(errorMessage);
}
catch (Exception ex)
{
logger.LogError(ex, ex.Message);
return Result.Fail<Order>(ex.Message);
}
}
これは、API で正しく動作する Postman で使用している Order オブジェクトと関連する OrderLineItem オブジェクトの json です。
{
"@odata.context": "https://localhost:44367/v1/$metadata#Orders",
"DateOfOrder": "2020-05-14T08:00:43.511Z",
"PurchaseOrderNumber": "P051420200001",
"Subtotal": 450.00,
"Discount": 0.00,
"Shipping": 3.45,
"SalesTax": 28.00,
"Total": 495.89,
"OrderLineItems": [
{
"ProductId": "BF43F1C7-6796-4C92-B4DD-08D7DBE4BBCC",
"ProductName": "Test Product 2",
"Quantity": 6,
"UnitPrice": 53.00,
"Discount": 0.00,
"Total": 318.00,
"Length": 10.0,
"Width": 4.0,
"Height": 7.0,
"Weight": 0.302,
"DimUnit": "Inch",
"WeightUnit": "Pound",
"Status": "Active",
"DeleteFlag": false
}
]
}
Postman を使用して関連する OrderLineItems を持つ新しい注文を投稿すると、My API は注文と関連する OrderLineItem レコードを正常に作成します。ただし、Simple.OData.V4.Client を使用して投稿すると、Order レコードは作成されますが、関連する OrderLineItem レコードは作成されません。
Postman 経由でレコードを送信するときに OData API コントローラーを見ると、含まれている OrderLineItems と共に Order オブジェクトが渡されていることがわかります。
しかし、Web アプリケーションから Simple.OData.V4.Client を使用しているときに OData API コントローラーを見ると、OrderLineItems のカウントが 0 であるため、Simple OData クライアントは関連する OrderLineItem レコードを送信していないことがわかります。ただし、Web アプリケーションの OData サービスの CreatreOrderAsync メソッドに渡される Order オブジェクトで確認できます。
そのため、単純な OData クライアントが関連レコードを含めるために必要なものが不足していると想定する必要がありますが、単純な OData クライアントのドキュメントを確認した後、マスター/詳細タイプのクライアントの Post メソッドの例を見つけることができません。
ここで何が欠けていますか?
***** 2020 年 5 月 14 日更新 *****
Simple.Odata.Client は、ディープ リンク (1 回の操作でデータが関連付けられたモデル) をサポートしていません。Microsoft には、積極的に更新されている OData クライアントがあり、関連データをサポートしています。これはより複雑ですが、より柔軟でもあるようです (つまり、ODataClientFactory と DI のサポート)。ここにドキュメントへのリンクがあります。
Microsoft クライアントは、Connected Services を使用してプロキシをセットアップし、Visual Studio の API メタデータにリンクするという点で、WCF で行う必要があったことを思い出させます。LINQ クエリをサポートしている点と、実際のネットワーク呼び出しなしで単体テストできる IOdataClientFactory が気に入っています。