Friday, January 4, 2019

OData $expand and $select

How to implement OData $expand and $select in Web API

You can download the full code from my GitHub repository 

And follow my YouTube channel for detailed description
Step 1:

Create a new Web API project in visual studio and add below nuget packages to enable odata
"Microsoft.AspNet.OData"

Step 2:

Create below model class Product, Supplier, Category and ProductList
-----------------------------------------------------------------------------
using System.ComponentModel.DataAnnotations.Schema;

namespace ODataExpandAndSelect.Models
{
    public class Product
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }

        [ForeignKey("Category")]
        public int CategoryId { get; set; }
        public virtual Category Category { get; set; }

        [ForeignKey("Supplier")]
        public string SupplierId { get; set; }
        public virtual Supplier Supplier { get; set; }
    }
}
----------------------------------------------------------------------------------------
using System.ComponentModel.DataAnnotations;

namespace ODataExpandAndSelect.Models
{
    public class Supplier
    {
        [Key]
        public string Key { get; set; }
        public string Name { get; set; }
    }

}
----------------------------------------------------------------------------------------------------
using System.Collections.Generic;
using System.Linq;

namespace ODataExpandAndSelect.Models
{
    public class Category
    {
        public Category()
        {
            Products = new HashSet();
        }
        public int ID { get; set; }
        public string Name { get; set; }
        public virtual ICollection Products { get; set; }
    }
------------------------------------------------------------------------------------------
    public class ProductList
    {
        public IQueryable getProducts()
        {
            List products = new List();

            Category c1 = new Category() { ID = 1, Name = "Category1", Products = products };
            Category c2 = new Category() { ID = 2, Name = "Category2", Products = products };
            Supplier s1 = new Supplier() { Key = "s1", Name = "Supplier1" };
            Supplier s2 = new Supplier() { Key = "s2", Name = "Supplier2" };

            Product p1 = new Product() { ID = 1, Category = c1, CategoryId = 1, Name = "product1", Price = 100.50M , Supplier = s1, SupplierId = "SupplierS1" };
            Product p2 = new Product() { ID = 2, Category = c2, CategoryId = 2, Name = "product2", Price = 200.50M , Supplier = s2, SupplierId = "SupplierS2" };

            products.Add(p1);
            products.Add(p2);
           
            return products.AsQueryable();
        }
    }
}
------------------------------------------------------------------------------------

Since I am not using any database in this example, So I have created ProductList class and returning some dummy data, You may use any database or entity framework as per your requirement.

Step 3:  
In WebApi.Config Please add below changes

using System.Linq;
using System.Web.Http;
using Microsoft.AspNet.OData.Batch;
using Microsoft.AspNet.OData.Builder;
using Microsoft.AspNet.OData.Extensions;
using Microsoft.OData.Edm;
using ODataExpandAndSelect.Models;

namespace ODataExpandAndSelect
{
    public static class WebApiConfig
    {
        private static IEdmModel GetEdmModel()
        {
            ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
            builder.Namespace = "WebAPITest";
            builder.ContainerName = "DefaultContainer";
            builder.EntitySet("Product");
            builder.EntitySet("Category");
            builder.EntitySet("Supplier");
            var edmModel = builder.GetEdmModel();
            return edmModel;
        }
        public static void Register(HttpConfiguration config)
        {
            config.Count().Filter().OrderBy().Expand().Select().MaxTop(null); 
            config.MapODataServiceRoute("odata", null, GetEdmModel(), new DefaultODataBatchHandler(GlobalConfiguration.DefaultServer));
            config.EnsureInitialized();
        }
    }

}

Step 4:
Create a ProductController in controller folder like below

using System.Linq;
using Microsoft.AspNet.OData;
using ODataExpandAndSelect.Models;

namespace ODataExpandAndSelect.Controllers
{
    public class ProductController : ODataController
    {
        [EnableQuery]
        public IQueryable Get()
        {
            ProductList list = new ProductList();
            var data = list.getProducts();
            return data;
        }
    }
}

Step 5:
In Global.asax.cs add below changes

using System.Web.Http;

namespace ODataExpandAndSelect
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);
        }
    }
}

Step 6:
Run your application on IIS express and use query like below

http://localhost:5197/Product?$expand=Category





You can expand to next level through comma separated like below query
http://localhost:5197/Product?$expand=Category,Supplier


For $select you can you below query
http://localhost:5197/Product?$select=Price





Thank you
Happy coding

No comments:

Post a Comment