Documentation

OData Integration

    Introduction

    OData is defined as "An open protocol to allow the creation and consumption of queryable and interoperable RESTful APIs in a simple and standard way" in odata.org. You can use OData with ASP.NET Boilerplate. Abp.Web.Api.OData nuget package simplifies it's usage.

    Setup

    Install Nuget Package

    We should first install Abp.Web.Api.OData nuget package to our WebApi project:

    Install-Package Abp.Web.Api.OData

    Set Module Dependency

    We should set dependency to AbpWebApiODataModule from our module. Example:

    [DependsOn(typeof(AbpWebApiODataModule))]
    public class MyProjectWebApiModule : AbpModule
    {
        ...
    }

    See module system to understand module dependencies.

    Configure Your Entities

    OData requires to declare entities which can be used as OData resources. We should do this in PreInitialize method of our module, as shown below:

    [DependsOn(typeof(AbpWebApiODataModule))]
    public class MyProjectWebApiModule : AbpModule
    {
        public override void PreInitialize()
        {
            var builder = Configuration.Modules.AbpWebApiOData().ODataModelBuilder;
    
            //Configure your entities here...
            builder.EntitySet<Person>("Persons");
        }
    
        ...
    }

    Here, we got the ODataModelBuilder reference and set the Person entity. You can use EntitySet to add other entities as similar. See OData documentation for more information on builder.

    Create Controllers

    Abp.Web.Api.OData nuget package includes AbpODataEntityController base class (which extends standard ODataController) to create your controllers easier. An example to create an OData endpoint for Person entity:

    public class PersonsController : AbpODataEntityController<Person>
    {
        public PersonsController(IRepository<Person> repository)
            : base(repository)
        {
        }
    }

    It's that easy. All methods of AbpODataEntityController is virtual. That means you can override Get, Post, Put, Patch, Delete and other actions and add your own logic.

    Configuration

    Abp.Web.Api.OData automatically calls HttpConfiguration.MapODataServiceRoute method with conventional configuration. If you need, you can set Configuration.Modules.AbpWebApiOData().MapAction to map OData routes yourself.

    Examples

    Here, some example requests to the controller defined above. Assume that the application works on http://localhost:61842. We will show some basics. Since OData is a standard protocol, you can easily find more advanced examples on the web.

    Getting List of Entities

    Getting all people.

    Request
    GET http://localhost:61842/odata/Persons
    Response
    {
      "@odata.context":"http://localhost:61842/odata/$metadata#Persons","value":[
        {
          "Name":"Douglas Adams","IsDeleted":false,"DeleterUserId":null,"DeletionTime":null,"LastModificationTime":null,"LastModifierUserId":null,"CreationTime":"2015-11-07T20:12:39.363+03:00","CreatorUserId":null,"Id":1
        },{
          "Name":"John Nash","IsDeleted":false,"DeleterUserId":null,"DeletionTime":null,"LastModificationTime":null,"LastModifierUserId":null,"CreationTime":"2015-11-07T20:12:39.363+03:00","CreatorUserId":null,"Id":2
        }
      ]
    }

    Getting a Single Entity

    Getting the person with Id = 2.

    Request
    GET http://localhost:61842/odata/Persons(2)
    Response
    {
      "@odata.context":"http://localhost:61842/odata/$metadata#Persons/$entity","Name":"John Nash","IsDeleted":false,"DeleterUserId":null,"DeletionTime":null,"LastModificationTime":null,"LastModifierUserId":null,"CreationTime":"2015-11-07T20:12:39.363+03:00","CreatorUserId":null,"Id":2
    }

    Getting a Single Entity With Navigation Properties

    Getting the person with Id = 1 including his phone numbers.

    Request
    GET http://localhost:61842/odata/Persons(1)?$expand=Phones
    Response
    {
      "@odata.context":"http://localhost:61842/odata/$metadata#Persons/$entity","Name":"Douglas Adams","IsDeleted":false,"DeleterUserId":null,"DeletionTime":null,"LastModificationTime":null,"LastModifierUserId":null,"CreationTime":"2015-11-07T20:12:39.363+03:00","CreatorUserId":null,"Id":1,"Phones":[
        {
          "PersonId":1,"Type":"Mobile","Number":"4242424242","CreationTime":"2015-11-07T20:12:39.363+03:00","CreatorUserId":null,"Id":1
        },{
          "PersonId":1,"Type":"Mobile","Number":"2424242424","CreationTime":"2015-11-07T20:12:39.363+03:00","CreatorUserId":null,"Id":2
        }
      ]
    }

    Querying

    Here, a more advanced query includes filtering, sorting and getting top 2 results.

    Request
    GET http://localhost:61842/odata/Persons?$filter=Name eq 'Douglas Adams'&$orderby=CreationTime&$top=2
    Response
    {
      "@odata.context":"http://localhost:61842/odata/$metadata#Persons","value":[
        {
          "Name":"Douglas Adams","IsDeleted":false,"DeleterUserId":null,"DeletionTime":null,"LastModificationTime":null,"LastModifierUserId":null,"CreationTime":"2015-11-07T20:12:39.363+03:00","CreatorUserId":null,"Id":1
        },{
          "Name":"Douglas Adams","IsDeleted":false,"DeleterUserId":null,"DeletionTime":null,"LastModificationTime":null,"LastModifierUserId":null,"CreationTime":"2016-01-12T20:29:03+02:00","CreatorUserId":null,"Id":3
        }
      ]
    }

    OData supports paging, sorting, filtering, projections and much more. See it's own documentation for more information.

    Creating a New Entity

    In this example, we're creating a new person.

    Request
    POST http://localhost:61842/odata/Persons
    
    {
        Name: "Galileo Galilei"
    }

    Here, "Content-Type" header is "application/json".

    Response
    {
      "@odata.context": "http://localhost:61842/odata/$metadata#Persons/$entity",
      "Name": "Galileo Galilei",
      "IsDeleted": false,
      "DeleterUserId": null,
      "DeletionTime": null,
      "LastModificationTime": null,
      "LastModifierUserId": null,
      "CreationTime": "2016-01-12T20:36:04.1628263+02:00",
      "CreatorUserId": null,
      "Id": 4
    }

    If we get the list again, we can see the new person. We can also update or delete an existing entity as OData supports it.

    Getting MetaData

    We can get metadata of entities, as shown in this example.

    Request
    GET http://localhost:61842/odata/$metadata
    Response
    <?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="AbpODataDemo.People" xmlns="http://docs.oasis-open.org/odata/ns/edm">
    
                <EntityType Name="Person">
    
                    <Key>
    
                        <PropertyRef Name="Id" />
    
                    </Key>
    
                    <Property Name="Name" Type="Edm.String" Nullable="false" />
    
                    <Property Name="IsDeleted" Type="Edm.Boolean" Nullable="false" />
    
                    <Property Name="DeleterUserId" Type="Edm.Int64" />
    
                    <Property Name="DeletionTime" Type="Edm.DateTimeOffset" />
    
                    <Property Name="LastModificationTime" Type="Edm.DateTimeOffset" />
    
                    <Property Name="LastModifierUserId" Type="Edm.Int64" />
    
                    <Property Name="CreationTime" Type="Edm.DateTimeOffset" Nullable="false" />
    
                    <Property Name="CreatorUserId" Type="Edm.Int64" />
    
                    <Property Name="Id" Type="Edm.Int32" Nullable="false" />
    
                    <NavigationProperty Name="Phones" Type="Collection(AbpODataDemo.People.Phone)" />
    
                </EntityType>
    
                <EntityType Name="Phone">
    
                    <Key>
    
                        <PropertyRef Name="Id" />
    
                    </Key>
    
                    <Property Name="PersonId" Type="Edm.Int32" />
    
                    <Property Name="Type" Type="AbpODataDemo.People.PhoneType" Nullable="false" />
    
                    <Property Name="Number" Type="Edm.String" Nullable="false" />
    
                    <Property Name="CreationTime" Type="Edm.DateTimeOffset" Nullable="false" />
    
                    <Property Name="CreatorUserId" Type="Edm.Int64" />
    
                    <Property Name="Id" Type="Edm.Int32" Nullable="false" />
    
                    <NavigationProperty Name="Person" Type="AbpODataDemo.People.Person">
    
                        <ReferentialConstraint Property="PersonId" ReferencedProperty="Id" />
    
                    </NavigationProperty>
    
                </EntityType>
    
                <EnumType Name="PhoneType">
    
                    <Member Name="Unknown" Value="0" />
    
                    <Member Name="Mobile" Value="1" />
    
                    <Member Name="Home" Value="2" />
    
                    <Member Name="Office" Value="3" />
    
                </EnumType>
    
            </Schema>
    
            <Schema Namespace="Default" xmlns="http://docs.oasis-open.org/odata/ns/edm">
    
                <EntityContainer Name="Container">
    
                    <EntitySet Name="Persons" EntityType="AbpODataDemo.People.Person" />
    
                </EntityContainer>
    
            </Schema>
    
        </edmx:DataServices>
    
    </edmx:Edmx>

    Metadata is used to investigate the service.

    Sample Project

    You get source code of the sample project here: https://github.com/aspnetboilerplate/sample-odata