Omezování v OData v4 pomocí webového rozhraní API 2.2
podle Jinfu Tan
Tradičně bylo možné k entitě přistupovat pouze v případě, že byla zapouzdřena v sadě entit. OData v4 ale nabízí dvě další možnosti: Singleton a Containment, které webAPI 2.2 podporuje.
Toto téma ukazuje, jak definovat obsah v koncovém bodu OData ve WebApi 2.2. Další informace o omezování najdete v tématu Věnovaném omezování s OData v4. Informace o vytvoření koncového bodu OData V4 ve webovém rozhraní API najdete v tématu Vytvoření koncového bodu OData v4 pomocí webového rozhraní API ASP.NET 2.2.
Nejprve vytvoříme ve službě OData model domény pro uchovávání obsahu pomocí tohoto datového modelu:
Účet obsahuje mnoho paymentInstruments (PI), ale pro platební nástroj nedefinujeme sadu entit. Místo toho je možné k rozhraním PI přistupovat pouze prostřednictvím účtu.
Definování datového modelu
Definujte typy CLR.
public class Account { public int AccountID { get; set; } public string Name { get; set; } [Contained] public IList<PaymentInstrument> PayinPIs { get; set; } } public class PaymentInstrument { public int PaymentInstrumentID { get; set; } public string FriendlyName { get; set; } }
Atribut
Contained
se používá pro vlastnosti navigace v kontejneru.Vygenerujte model EDM na základě typů CLR.
public static IEdmModel GetModel() { ODataConventionModelBuilder builder = new ODataConventionModelBuilder(); builder.EntitySet<Account>("Accounts"); var paymentInstrumentType = builder.EntityType<PaymentInstrument>(); var functionConfiguration = paymentInstrumentType.Collection.Function("GetCount"); functionConfiguration.Parameter<string>("NameContains"); functionConfiguration.Returns<int>(); builder.Namespace = typeof(Account).Namespace; return builder.GetEdmModel(); }
Bude
ODataConventionModelBuilder
zpracovávat sestavení modelu EDM, pokudContained
je atribut přidán do odpovídající navigační vlastnosti. Pokud je vlastnost typu kolekce,GetCount(string NameContains)
vytvoří se také funkce.Vygenerovaná metadata budou vypadat takto:
<EntityType Name="Account"> <Key> <PropertyRef Name="AccountID" /> </Key> <Property Name="AccountID" Type="Edm.Int32" Nullable="false" /> <Property Name="Name" Type="Edm.String" /> <NavigationProperty Name="PayinPIs" Type="Collection(ODataContrainmentSample.PaymentInstrument)" ContainsTarget="true" /> </EntityType>
Atribut
ContainsTarget
označuje, že vlastnost navigace je obsah.
Definování kontroleru obsahující sady entit
Obsažené entity nemají vlastní kontroler. akce je definována v kontroleru obsahující sady entit. V této ukázce je AccountsController, ale žádný PaymentInstrumentsController.
public class AccountsController : ODataController
{
private static IList<Account> _accounts = null;
public AccountsController()
{
if (_accounts == null)
{
_accounts = InitAccounts();
}
}
// PUT ~/Accounts(100)/PayinPIs
[EnableQuery]
public IHttpActionResult GetPayinPIs(int key)
{
var payinPIs = _accounts.Single(a => a.AccountID == key).PayinPIs;
return Ok(payinPIs);
}
[EnableQuery]
[ODataRoute("Accounts({accountId})/PayinPIs({paymentInstrumentId})")]
public IHttpActionResult GetSinglePayinPI(int accountId, int paymentInstrumentId)
{
var payinPIs = _accounts.Single(a => a.AccountID == accountId).PayinPIs;
var payinPI = payinPIs.Single(pi => pi.PaymentInstrumentID == paymentInstrumentId);
return Ok(payinPI);
}
// PUT ~/Accounts(100)/PayinPIs(101)
[ODataRoute("Accounts({accountId})/PayinPIs({paymentInstrumentId})")]
public IHttpActionResult PutToPayinPI(int accountId, int paymentInstrumentId, [FromBody]PaymentInstrument paymentInstrument)
{
var account = _accounts.Single(a => a.AccountID == accountId);
var originalPi = account.PayinPIs.Single(p => p.PaymentInstrumentID == paymentInstrumentId);
originalPi.FriendlyName = paymentInstrument.FriendlyName;
return Ok(paymentInstrument);
}
// DELETE ~/Accounts(100)/PayinPIs(101)
[ODataRoute("Accounts({accountId})/PayinPIs({paymentInstrumentId})")]
public IHttpActionResult DeletePayinPIFromAccount(int accountId, int paymentInstrumentId)
{
var account = _accounts.Single(a => a.AccountID == accountId);
var originalPi = account.PayinPIs.Single(p => p.PaymentInstrumentID == paymentInstrumentId);
if (account.PayinPIs.Remove(originalPi))
{
return StatusCode(HttpStatusCode.NoContent);
}
else
{
return StatusCode(HttpStatusCode.InternalServerError);
}
}
// GET ~/Accounts(100)/PayinPIs/Namespace.GetCount()
[ODataRoute("Accounts({accountId})/PayinPIs/ODataContrainmentSample.GetCount(NameContains={name})")]
public IHttpActionResult GetPayinPIsCountWhoseNameContainsGivenValue(int accountId, [FromODataUri]string name)
{
var account = _accounts.Single(a => a.AccountID == accountId);
var count = account.PayinPIs.Where(pi => pi.FriendlyName.Contains(name)).Count();
return Ok(count);
}
private static IList<Account> InitAccounts()
{
var accounts = new List<Account>()
{
new Account()
{
AccountID = 100,
Name="Name100",
PayinPIs = new List<PaymentInstrument>()
{
new PaymentInstrument()
{
PaymentInstrumentID = 101,
FriendlyName = "101 first PI",
},
new PaymentInstrument()
{
PaymentInstrumentID = 102,
FriendlyName = "102 second PI",
},
},
},
};
return accounts;
}
}
Pokud je cesta OData 4 nebo více segmentů, funguje pouze směrování atributů, například [ODataRoute("Accounts({accountId})/PayinPIs({paymentInstrumentId})")]
ve výše uvedeném kontroleru. Jinak funguje jak atribut, tak konvenční směrování: například GetPayInPIs(int key)
odpovídá GET ~/Accounts(1)/PayinPIs
.
Děkujeme Leo Hu za původní obsah tohoto článku.
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro