Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions AspNetCoreOData.sln
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ODataAlternateKeySample", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BenchmarkServer", "sample\BenchmarkServer\BenchmarkServer.csproj", "{8346AD1B-00E3-462D-B6B1-9AA3C2FB2850}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ODataMiniApi", "sample\ODataMiniApi\ODataMiniApi.csproj", "{53645862-60E1-403A-B9BB-911D3801010F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -75,6 +77,10 @@ Global
{8346AD1B-00E3-462D-B6B1-9AA3C2FB2850}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8346AD1B-00E3-462D-B6B1-9AA3C2FB2850}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8346AD1B-00E3-462D-B6B1-9AA3C2FB2850}.Release|Any CPU.Build.0 = Release|Any CPU
{53645862-60E1-403A-B9BB-911D3801010F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{53645862-60E1-403A-B9BB-911D3801010F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{53645862-60E1-403A-B9BB-911D3801010F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{53645862-60E1-403A-B9BB-911D3801010F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -90,6 +96,7 @@ Global
{647EFCFA-55A7-4F0A-AD40-4B6EB1BFCFFA} = {B1F86961-6958-4617-ACA4-C231F95AE099}
{7B153669-A42F-4511-8BDB-587B3B27B2F3} = {B1F86961-6958-4617-ACA4-C231F95AE099}
{8346AD1B-00E3-462D-B6B1-9AA3C2FB2850} = {B1F86961-6958-4617-ACA4-C231F95AE099}
{53645862-60E1-403A-B9BB-911D3801010F} = {B1F86961-6958-4617-ACA4-C231F95AE099}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {540C9752-AAC0-49EA-BA60-78490C90FF86}
Expand Down
180 changes: 180 additions & 0 deletions sample/ODataMiniApi/AppDb.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
//-----------------------------------------------------------------------------
// <copyright file="AppDb.cs" company=".NET Foundation">
// Copyright (c) .NET Foundation and Contributors. All rights reserved.
// See License.txt in the project root for license information.
// </copyright>
//------------------------------------------------------------------------------

using Microsoft.EntityFrameworkCore;

namespace ODataMiniApi;

public class AppDb : DbContext
{
public AppDb(DbContextOptions<AppDb> options) : base(options) { }

public DbSet<School> Schools => Set<School>();

public DbSet<Student> Students => Set<Student>();

public DbSet<Customer> Customers => Set<Customer>();

public DbSet<Order> Orders => Set<Order>();

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<School>().HasKey(x => x.SchoolId);
modelBuilder.Entity<Student>().HasKey(x => x.StudentId);
modelBuilder.Entity<School>().OwnsOne(x => x.MailAddress);

modelBuilder.Entity<Customer>().HasKey(x => x.Id);
modelBuilder.Entity<Order>().HasKey(x => x.Id);
modelBuilder.Entity<Customer>().OwnsOne(x => x.Info);
}
}

static class AppDbExtension
{
public static void MakeSureDbCreated(this WebApplication app)
{
using (var scope = app.Services.CreateScope())
{
var services = scope.ServiceProvider;
var context = services.GetRequiredService<AppDb>();

if (context.Schools.Count() == 0)
{
#region Students
var students = new List<Student>
{
// Mercury school
new Student { SchoolId = 1, StudentId = 10, FirstName = "Spens", LastName = "Alex", FavoriteSport = "Soccer", Grade = 87, BirthDay = new DateOnly(2009, 11, 15) },
new Student { SchoolId = 1, StudentId = 11, FirstName = "Jasial", LastName = "Eaine", FavoriteSport = "Basketball", Grade = 45, BirthDay = new DateOnly(1989, 8, 3) },
new Student { SchoolId = 1, StudentId = 12, FirstName = "Niko", LastName = "Rorigo", FavoriteSport = "Soccer", Grade = 78, BirthDay = new DateOnly(2019, 5, 5) },
new Student { SchoolId = 1, StudentId = 13, FirstName = "Roy", LastName = "Rorigo", FavoriteSport = "Tennis", Grade = 67, BirthDay = new DateOnly(1975, 11, 4) },
new Student { SchoolId = 1, StudentId = 14, FirstName = "Zaral", LastName = "Clak", FavoriteSport = "Basketball", Grade = 54, BirthDay = new DateOnly(2008, 1, 4) },

// Venus school
new Student { SchoolId = 2, StudentId = 20, FirstName = "Hugh", LastName = "Briana", FavoriteSport = "Basketball", Grade = 78, BirthDay = new DateOnly(1959, 5, 6) },
new Student { SchoolId = 2, StudentId = 21, FirstName = "Reece", LastName = "Len", FavoriteSport = "Basketball", Grade = 45, BirthDay = new DateOnly(2004, 2, 5) },
new Student { SchoolId = 2, StudentId = 22, FirstName = "Javanny", LastName = "Jay", FavoriteSport = "Soccer", Grade = 87, BirthDay = new DateOnly(2003, 6, 5) },
new Student { SchoolId = 2, StudentId = 23, FirstName = "Ketty", LastName = "Oak", FavoriteSport = "Tennis", Grade = 99, BirthDay = new DateOnly(1998, 7, 25) },

// Earth School
new Student { SchoolId = 3, StudentId = 30, FirstName = "Mike", LastName = "Wat", FavoriteSport = "Tennis", Grade = 93, BirthDay = new DateOnly(1999, 5, 15) },
new Student { SchoolId = 3, StudentId = 31, FirstName = "Sam", LastName = "Joshi", FavoriteSport = "Soccer", Grade = 78, BirthDay = new DateOnly(2000, 6, 23) },
new Student { SchoolId = 3, StudentId = 32, FirstName = "Kerry", LastName = "Travade", FavoriteSport = "Basketball", Grade = 89, BirthDay = new DateOnly(2001, 2, 6) },
new Student { SchoolId = 3, StudentId = 33, FirstName = "Pett", LastName = "Jay", FavoriteSport = "Tennis", Grade = 63, BirthDay = new DateOnly(1998, 11, 7) },

// Mars School
new Student { SchoolId = 4, StudentId = 40, FirstName = "Mike", LastName = "Wat", FavoriteSport = "Soccer", Grade = 64, BirthDay = new DateOnly(2011, 11, 15) },
new Student { SchoolId = 4, StudentId = 41, FirstName = "Sam", LastName = "Joshi", FavoriteSport = "Basketball", Grade = 98, BirthDay = new DateOnly(2005, 6, 6) },
new Student { SchoolId = 4, StudentId = 42, FirstName = "Kerry", LastName = "Travade", FavoriteSport = "Soccer", Grade = 88, BirthDay = new DateOnly(2011, 5, 13) },

// Jupiter School
new Student { SchoolId = 5, StudentId = 50, FirstName = "David", LastName = "Padron", FavoriteSport = "Tennis", Grade = 77, BirthDay = new DateOnly(2015, 12, 3) },
new Student { SchoolId = 5, StudentId = 53, FirstName = "Jeh", LastName = "Brook", FavoriteSport = "Basketball", Grade = 69, BirthDay = new DateOnly(2014, 10, 15) },
new Student { SchoolId = 5, StudentId = 54, FirstName = "Steve", LastName = "Johnson", FavoriteSport = "Soccer", Grade = 100, BirthDay = new DateOnly(1995, 3, 2) },

// Saturn School
new Student { SchoolId = 6, StudentId = 60, FirstName = "John", LastName = "Haney", FavoriteSport = "Soccer", Grade = 99, BirthDay = new DateOnly(2008, 12, 1) },
new Student { SchoolId = 6, StudentId = 61, FirstName = "Morgan", LastName = "Frost", FavoriteSport = "Tennis", Grade = 17, BirthDay = new DateOnly(2009, 11, 4) },
new Student { SchoolId = 6, StudentId = 62, FirstName = "Jennifer", LastName = "Viles", FavoriteSport = "Basketball", Grade = 54, BirthDay = new DateOnly(1989, 3, 15) },

// Uranus School
new Student { SchoolId = 7, StudentId = 72, FirstName = "Matt", LastName = "Dally", FavoriteSport = "Basketball", Grade = 77, BirthDay = new DateOnly(2011, 11, 4) },
new Student { SchoolId = 7, StudentId = 73, FirstName = "Kevin", LastName = "Vax", FavoriteSport = "Basketball", Grade = 93, BirthDay = new DateOnly(2012, 5, 12) },
new Student { SchoolId = 7, StudentId = 76, FirstName = "John", LastName = "Clarey", FavoriteSport = "Soccer", Grade = 95, BirthDay = new DateOnly(2008, 8, 8) },

// Neptune School
new Student { SchoolId = 8, StudentId = 81, FirstName = "Adam", LastName = "Singh", FavoriteSport = "Tennis", Grade = 92, BirthDay = new DateOnly(2006, 6, 23) },
new Student { SchoolId = 8, StudentId = 82, FirstName = "Bob", LastName = "Joe", FavoriteSport = "Soccer", Grade = 88, BirthDay = new DateOnly(1978, 11, 15) },
new Student { SchoolId = 8, StudentId = 84, FirstName = "Martin", LastName = "Dalton", FavoriteSport = "Tennis", Grade = 77, BirthDay = new DateOnly(2017, 5, 14) },

// Pluto School
new Student { SchoolId = 9, StudentId = 91, FirstName = "Michael", LastName = "Wu", FavoriteSport = "Soccer", Grade = 97, BirthDay = new DateOnly(2022, 9, 22) },
new Student { SchoolId = 9, StudentId = 93, FirstName = "Rachel", LastName = "Wottle", FavoriteSport = "Soccer", Grade = 81, BirthDay = new DateOnly(2022, 10, 5) },
new Student { SchoolId = 9, StudentId = 97, FirstName = "Aakash", LastName = "Aarav", FavoriteSport = "Soccer", Grade = 98, BirthDay = new DateOnly(2003, 3, 15) },

// Shyline high School
new Student { SchoolId = 10, StudentId = 101, FirstName = "Steve", LastName = "Chu", FavoriteSport = "Soccer", Grade = 77, BirthDay = new DateOnly(2002, 11, 12) },
new Student { SchoolId = 10, StudentId = 123, FirstName = "Wash", LastName = "Dish", FavoriteSport = "Tennis", Grade = 81, BirthDay = new DateOnly(2002, 12, 5) },
new Student { SchoolId = 10, StudentId = 106, FirstName = "Ren", LastName = "Wu", FavoriteSport = "Soccer", Grade = 88, BirthDay = new DateOnly(2003, 3, 15) }
};

foreach (var s in students)
{
context.Students.Add(s);
}
#endregion

#region Schools
var schools = new List<School>
{
new School { SchoolId = 1, SchoolName = "Mercury Middle School", MailAddress = new Address { ApartNum = 241, City = "Kirk", Street = "156TH AVE", ZipCode = "98051" } },
new HighSchool { SchoolId = 2, SchoolName = "Venus High School", MailAddress = new Address { ApartNum = 543, City = "AR", Street = "51TH AVE PL", ZipCode = "98043" }, NumberOfStudents = 1187, PrincipalName = "Venus TT" },
new School { SchoolId = 3, SchoolName = "Earth University", MailAddress = new Address { ApartNum = 101, City = "Belly", Street = "24TH ST", ZipCode = "98029" } },
new School { SchoolId = 4, SchoolName = "Mars Elementary School ", MailAddress = new Address { ApartNum = 123, City = "Issaca", Street = "Mars Rd", ZipCode = "98023" } },
new School { SchoolId = 5, SchoolName = "Jupiter College", MailAddress = new Address { ApartNum = 443, City = "Redmond", Street = "Sky Freeway", ZipCode = "78123" } },
new School { SchoolId = 6, SchoolName = "Saturn Middle School", MailAddress = new Address { ApartNum = 11, City = "Moon", Street = "187TH ST", ZipCode = "68133" } },
new HighSchool { SchoolId = 7, SchoolName = "Uranus High School", MailAddress = new Address { ApartNum = 123, City = "Greenland", Street = "Sun Street", ZipCode = "88155" }, NumberOfStudents = 886, PrincipalName = "Uranus Sun" },
new School { SchoolId = 8, SchoolName = "Neptune Elementary School", MailAddress = new Address { ApartNum = 77, City = "BadCity", Street = "Moon way", ZipCode = "89155" } },
new School { SchoolId = 9, SchoolName = "Pluto University", MailAddress = new Address { ApartNum = 12004, City = "Sahamish", Street = "Universals ST", ZipCode = "10293" } },
new HighSchool { SchoolId =10, SchoolName = "Shyline High School", MailAddress = new Address { ApartNum = 4004, City = "Sammamish", Street = "8TH ST", ZipCode = "98029"}, NumberOfStudents = 976, PrincipalName = "Laly Fort" }
};

foreach (var s in schools)
{
s.Students = students.Where(std => std.SchoolId == s.SchoolId).ToList();

context.Schools.Add(s);
}
#endregion

context.SaveChanges();
}

if (context.Customers.Count() == 0)
{
#region Customers and Orders

var customers = new List<Customer>
{
new Customer { Id = 1, Name = "Alice", Info = new Info { Email = "[email protected]", Phone = "123-456-7819" },
Orders = [
new Order { Id = 11, Amount = 9},
new Order { Id = 12, Amount = 19},
] },
new Customer { Id = 2, Name = "Johnson", Info = new Info { Email = "[email protected]", Phone = "233-468-7289" },
Orders = [
new Order { Id = 21, Amount =8},
new Order { Id = 22, Amount = 76},
] },
new Customer { Id = 3, Name = "Peter", Info = new Info { Email = "[email protected]", Phone = "223-656-7889" },
Orders = [
new Order { Id = 32, Amount = 7 }
] },

new Customer { Id = 4, Name = "Sam", Info = new Info { Email = "[email protected]", Phone = "245-876-0989" },
Orders = [
new Order { Id = 41, Amount = 5 },
new Order { Id = 42, Amount = 32}
] }
};

foreach (var s in customers)
{
context.Customers.Add(s);
foreach (var o in s.Orders)
{
context.Orders.Add(o);
}
}
#endregion

context.SaveChanges();
}
}
}
}
101 changes: 101 additions & 0 deletions sample/ODataMiniApi/AppModels.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
//-----------------------------------------------------------------------------
// <copyright file="AppModels.cs" company=".NET Foundation">
// Copyright (c) .NET Foundation and Contributors. All rights reserved.
// See License.txt in the project root for license information.
// </copyright>
//------------------------------------------------------------------------------

using Microsoft.OData.Edm;
using Microsoft.OData.ModelBuilder;
using System.ComponentModel.DataAnnotations.Schema;

namespace ODataMiniApi;

public class EdmModelBuilder
{
public static IEdmModel GetEdmModel()
{
var builder = new ODataConventionModelBuilder();
builder.EntitySet<School>("Schools");
builder.ComplexType<Address>();
builder.ComplexType<Student>();

builder.EntitySet<Customer>("Customers");
builder.EntitySet<Order>("Orders");
builder.ComplexType<Info>();
return builder.GetEdmModel();
}
}

public class School
{
public int SchoolId { get; set; }

public string SchoolName { get; set; }

public Address MailAddress { get; set; }

public virtual IList<Student> Students { get; set; }
}

public class HighSchool : School
{
// Additional properties specific to HighSchool
public int NumberOfStudents { get; set; }
public string PrincipalName { get; set; }
}

public class Student
{
public int StudentId { get; set; }

public string FirstName { get; set; }

public string LastName { get; set; }

public string FavoriteSport { get; set; }

public int Grade { get; set; }

public int SchoolId { get; set; }

public DateOnly BirthDay { get; set; }
}

[ComplexType]
public class Address
{
public int ApartNum { get; set; }

public string City { get; set; }

public string Street { get; set; }

public string ZipCode { get; set; }
}


public class Customer
{
public int Id { get; set; }

public string Name { get; set; }

public Info Info { get; set; }

//[AutoExpand]
public List<Order> Orders { get; set; }
}

public class Order
{
public int Id { get; set; }

public int Amount { get; set; }
}

public class Info
{
public string Email { get; set; }
public string Phone { get; set; }
}
64 changes: 64 additions & 0 deletions sample/ODataMiniApi/CustomersAndOrders.http
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
@ODataMiniApi_HostAddress = http://localhost:5177

###

GET {{ODataMiniApi_HostAddress}}/customers

### [AutoExpand]
### 4.01 Delta Payload Get "odata." prefix even in 4.01?
###

###

GET {{ODataMiniApi_HostAddress}}/v0/customers

###

GET {{ODataMiniApi_HostAddress}}/v00/customers?$select=name&$expand=info&$top=2&$orderby=id
###

GET {{ODataMiniApi_HostAddress}}/v1/customers?$select=name,info&$top=2&$orderby=id

###
GET {{ODataMiniApi_HostAddress}}/v1/customers?$select=name&$top=2&$orderby=id&$expand=info
###
GET {{ODataMiniApi_HostAddress}}/v1/customers?$select=name,info&$top=2&$orderby=id%20desc

###

GET {{ODataMiniApi_HostAddress}}/v2/customers?$select=name&$top=2&$orderby=id

###
GET {{ODataMiniApi_HostAddress}}/v2/customers?$select=name&$top=2&$orderby=id&$expand=orders($select=amount)
###
GET {{ODataMiniApi_HostAddress}}/v2/customers?$select=name,info&$top=2&$orderby=id%20desc

###
# GET {{ODataMiniApi_HostAddress}}/v11/customers?$select=name&$expand=info // throw exception because 'info' is not navigation property
GET {{ODataMiniApi_HostAddress}}/v11/customers?$select=name,info

###
GET {{ODataMiniApi_HostAddress}}/v3/customers

###
GET {{ODataMiniApi_HostAddress}}/v5/customers
// throw exception since the delegate needs parameters, but we cannot easily provide the parameters.


### $filter=amount gt 15
GET {{ODataMiniApi_HostAddress}}/v0/?$filter=amount%20gt%2015

###
GET {{ODataMiniApi_HostAddress}}/v1/orders?$filter=amount%20gt%2015
###
GET {{ODataMiniApi_HostAddress}}/v2/orders?$filter=amount%20gt%2015


###

PATCH {{ODataMiniApi_HostAddress}}/v1/customers/1
Content-Type: application/json

{
"name": "kerry"
}
Loading