Creare un Singleton in OData v4 usando l'API Web 2.2

di Zoe Luo

Tradizionalmente, un'entità può essere accessibile solo se è stata incapsulata all'interno di un set di entità. Ma OData v4 offre due opzioni aggiuntive, Singleton e Contenimento, entrambe supportate da WebAPI 2.2.

Questo articolo illustra come definire un singleton in un endpoint OData nell'API Web 2.2. Per informazioni su cosa è un singleton e su come usarlo, vedere Uso di un singleton per definire l'entità speciale. Per creare un endpoint OData V4 nell'API Web, vedere Creare un endpoint OData v4 Usando API Web ASP.NET 2.2.

Verrà creato un singleton nel progetto API Web usando il modello di dati seguente:

Modello di dati

Un singleton denominato Umbrella verrà definito in base al tipo Companye verrà definito un set di entità denominato Employees in base al tipo Employee.

Definizione del modello di dati

  1. Definire i tipi CLR.

    /// <summary> 
    /// Present the EntityType "Employee" 
    /// </summary> 
    public class Employee 
    {     
        public int ID { get; set; }     
        public string Name { get; set; }  
       
        [Singleton]     
        public Company Company { get; set; } 
    } 
    /// <summary> 
    /// Present company category, which is an enum type 
    /// </summary> 
    public enum CompanyCategory 
    { 
        IT = 0,     
        Communication = 1,     
        Electronics = 2,     
        Others = 3 
    } 
    /// <summary> 
    /// Present the EntityType "Company" 
    /// </summary> 
    public class Company 
    {
         public int ID { get; set; }
         public string Name { get; set; }
         public Int64 Revenue { get; set; }
         public CompanyCategory Category { get; set; }
         public List<Employee> Employees { get; set; } 
    }
    
  2. Generare il modello EDM in base ai tipi CLR.

    public static IEdmModel GetEdmModel() 
    { 
        ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
        builder.EntitySet<Employee>("Employees"); builder.Singleton<Company>("Umbrella");
        builder.Namespace = typeof(Company).Namespace;
        return builder.GetEdmModel(); 
    }
    

    In questo caso, builder.Singleton<Company>("Umbrella") indica al generatore di modelli di creare un singleton denominato Umbrella nel modello EDM.

    I metadati generati avranno un aspetto simile al seguente:

    <EntityContainer Name="Container"> 
      <EntitySet Name="Employees" EntityType="ODataSingletonSample.Employee"> 
        <NavigationPropertyBinding Path="Company" Target="Umbrella"/> 
      </EntitySet> 
      <Singleton Name="Umbrella" Type="ODataSingletonSample.Company"> 
        <NavigationPropertyBinding Path="Employees" Target="Employees"/> 
      </Singleton> 
    </EntityContainer>
    

    Dai metadati è possibile notare che la proprietà Company di spostamento nel Employees set di entità è associata al singleton Umbrella. L'associazione viene eseguita automaticamente da ODataConventionModelBuilder, poiché ha solo Umbrella il Company tipo. Se nel modello è presente un'ambiguità, è possibile usare per associare in modo esplicito una proprietà di spostamento a un singleton; HasSingletonBinding ha lo stesso effetto dell'uso HasSingletonBinding dell'attributo Singleton nella definizione del tipo CLR:

    EntitySetConfiguration<Employee> employeesConfiguration = 
        builder.EntitySet<Employee>("Employees"); 
    employeesConfiguration.HasSingletonBinding(c => c.Company, "Umbrella");
    

Definire il controller singleton

Come il controller EntitySet, il controller singleton eredita da ODataControllere il nome del controller singleton deve essere [singletonName]Controller.

public class UmbrellaController : ODataController 
{
    public static Company Umbrella;
    static UmbrellaController()
    {
        InitData();
    }
    private static void InitData()
    {
        Umbrella = new Company()
        {
            ID = 1,
            Name = "Umbrella",
            Revenue = 1000,
            Category = CompanyCategory.Communication,
            Employees = new List<Employee>()
        };
    } 
}

Per gestire diversi tipi di richieste, è necessario definire le azioni nel controller. Il routing degli attributi è abilitato per impostazione predefinita in WebApi 2.2. Ad esempio, per definire un'azione per gestire la query Revenue dall'uso Company del routing degli attributi, usare quanto segue:

[ODataRoute("Umbrella/Revenue")] 
public IHttpActionResult GetCompanyRevenue() 
{
     return Ok(Umbrella.Revenue); 
}

Se non si è disposti a definire gli attributi per ogni azione, è sufficiente definire le azioni seguenti alle convenzioni di routing OData. Poiché una chiave non è necessaria per eseguire query su un singleton, le azioni definite nel controller singleton sono leggermente diverse dalle azioni definite nel controller entityset.

Per informazioni di riferimento, le firme del metodo per ogni definizione di azione nel controller singleton sono elencate di seguito.

// Get Singleton 
// ~/singleton 
public IHttpActionResult Get() 
public IHttpActionResult GetUmbrella() 

// Get Singleton 
// ~/singleton/cast 
public IHttpActionResult GetFromSubCompany() 
public IHttpActionResult GetUmbrellaFromSubCompany() 

// Get Singleton Property 
// ~/singleton/property  
public IHttpActionResult GetName() 
public IHttpActionResult GetNameFromCompany() 

// Get Singleton Navigation Property 
// ~/singleton/navigation  
public IHttpActionResult GetEmployees() 
public IHttpActionResult GetEmployeesFromCompany() 

// Update singleton by PUT 
// PUT ~/singleton 
public IHttpActionResult Put(Company newCompany) 
public IHttpActionResult PutUmbrella(Company newCompany) 

// Update singleton by Patch 
// PATCH ~/singleton 
public IHttpActionResult Patch(Delta<Company> item) 
public IHttpActionResult PatchUmbrella(Delta<Company> item) 

// Add navigation link to singleton 
// POST ~/singleton/navigation/$ref 
public IHttpActionResult CreateRef(string navigationProperty, [FromBody] Uri link) 

// Delete navigation link from singleton 
// DELETE ~/singleton/navigation/$ref?$id=~/relatedKey 
public IHttpActionResult DeleteRef(string relatedKey, string navigationProperty) 

// Add a new entity to singleton navigation property 
// POST ~/singleton/navigation 
public IHttpActionResult PostToEmployees([FromBody] Employee employee) 

// Call function bounded to singleton 
// GET ~/singleton/function() 
public IHttpActionResult GetEmployeesCount()

Fondamentalmente, tutto ciò che è necessario fare sul lato servizio. Il progetto di esempio contiene tutto il codice per la soluzione e il client OData che illustra come usare il singleton. Il client viene compilato seguendo la procedura descritta in Creare un'app client OData v4.

.

Grazie a Leo Hu per il contenuto originale di questo articolo.