ASP.NET Core: Xây dựng API web với hỗ trợ OData bằng ASP.NET Core
Trong bài viết mẫu này:
- Trình bày cách thêm hỗ trợ tùy chọn truy vấn OData trong ứng dụng ASP.NET Core Web API.
- Sử dụng API Web việc cần làm đã hoàn thành làm điểm bắt đầu.
- Không sử dụng Mô hình dữ liệu thực thể (EDM).
Cảnh báo
Một máy khách độc hại hoặc ngây thơ có thể tạo một truy vấn tiêu tốn quá nhiều tài nguyên. Truy vấn như vậy có thể làm gián đoạn quyền truy cập vào dịch vụ của bạn. Xem lại Hướng dẫn bảo mật cho ASP.NET Core Web API OData trước khi bắt đầu hướng dẫn này.
Đăng ký OData
Thêm gói NuGet Microsoft.AspNetCore.OData vào dự án.
Cập nhật phương thức ConfigureServices
trong Startup.cs với phần code được đánh dấu sau:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
// requires using Microsoft.AspNet.OData.Extensions;
services.AddOData();
}
Mã trước đăng ký dịch vụ OData trong bộ chứa nội xạ phụ thuộc (DI) .
Định cấu hình middleware
OData có thể thực hiện sắp xếp, lọc, truy vấn dữ liệu liên quan, v.v. Mỗi khả năng này có thể được bật hoặc tắt bằng middleware.
Cập nhật Configure
với phần code được đánh dấu sau:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
// The default HSTS value is 30 days. You may want to change this for
// production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseHttpsRedirection();
app.UseMvc(routeBuilder =>
{
routeBuilder.EnableDependencyInjection();
routeBuilder.Select().OrderBy().Filter();
});
}
Trong đoạn code trên:
- Cho phép ghi đè lên các điểm cuối hiện có thông qua DI để tạo route, thay vì hiển thị điểm cuối OData truyền thống.
- Cho phép chọn, sắp xếp theo thứ tự và lọc đối với trình tạo route.
Cập nhật controller
Thêm [EnableQuery()]
vào phương thức public ActionResult<IQueryable<TodoItem>> GetTodoItems()
trong TodoController
:
// GET: api/Todo
[EnableQuery()] // requires using Microsoft.AspNet.OData;
[HttpGet]
public ActionResult<IQueryable<TodoItem>> GetTodoItems()
{
return _context.TodoItems;
}
Trả về System.Linq.IQueryable
hoặc ActionResult<IQueryable>
cho phép OData dịch truy vấn sang truy vấn SQL bằng các khả năng của ef core. Trả về các kiểu khác, chẳng hạn như IEnumerable
khiến OData thực hiện các truy vấn trong ứng dụng.
Truy vấn tài nguyên bằng OData
Đăng một số dữ liệu lên ứng dụng API web, sử dụng công cụ như HTTP REPL hoặc Postman.
Gửi 5 Post request tới https://localhost:5001/api/todo
với 5 mục bên dưới trong phần yêu cầu.
{
"name": "test OData",
"isComplete": false,
"Type": "work",
"priority": 1,
"DueDate": "2019-04-18 00:00:01"
}
{
"name": "test 2",
"isComplete": true,
"Type": "shopping",
"priority": 2,
"DueDate": "2019-04-18 08:00:01"
}
{
"name": "test 3",
"isComplete": true,
"Type": "work",
"priority": 1,
"DueDate": "2019-04-18 09:00:01"
}
{
"name": "test 4",
"isComplete": false,
"Type": "shopping",
"priority": 3,
"DueDate": "2019-04-18 12:00:01"
}
{
"name": "test 5",
"isComplete": false,
"Type": "work",
"priority": 2,
"DueDate": "2019-04-18 15:00:01"
}
Gửi một Get request để xác minh dữ liệu trước đó đã được lưu. Ví dụ, http://localhost:5001/api/todo?$select=name,isComplete
.
$select
Tùy chọn $select
chỉ định một tập hợp con các property để đưa vào nội dung phản hồi. Ví dụ: để chỉ nhận name và isComplete của từng mục, hãy thêm ?$select=name,isComplete
vào cuối đường dẫn yêu cầu.
Yêu cầu trên trả về dữ liệu sau:
[
{
"Name": "Item1",
"IsComplete": false
},
{
"Name": "test 5",
"IsComplete": false
},
{
"Name": "test OData",
"IsComplete": false
},
{
"Name": "test 2",
"IsComplete": true
},
{
"Name": "test 3",
"IsComplete": true
},
{
"Name": "test 4",
"IsComplete": false
}
]
$orderBy
Tùy chọn $orderBy
có thể tiêu tốn quá nhiều tài nguyên. Cân nhắc sử dụng [Queryable(AllowedQueryOptions=AllowedQueryOptions.{Option})]
để vô hiệu hóa $orderBy
. Xem Hướng dẫn bảo mật cho ASP.NET Core Web API OData để biết thêm thông tin.
$orderBy
sắp xếp dữ liệu dựa trên một hoặc nhiều property. Ví dụ: để sắp xếp dữ liệu dựa trên mức độ ưu tiên của từng mục, hãy thêm ?$orderBy=priority
vào yêu cầu. Ví dụ, http://localhost:5001/api/todo?$orderBy=priority
.
Yêu cầu trên trả về dữ liệu sau:
[
{
"id": 1,
"name": "Item1",
"isComplete": false,
"type": null,
"priority": 0,
"dueDate": "0001-01-01T00:00:00"
},
{
"id": 3,
"name": "test OData",
"isComplete": false,
"type": "work",
"priority": 1,
"dueDate": "2019-04-18T00:00:01"
},
{
"id": 5,
"name": "test 3",
"isComplete": true,
"type": "work",
"priority": 1,
"dueDate": "2019-04-18T09:00:01"
},
{
"id": 2,
"name": "test 5",
"isComplete": false,
"type": "work",
"priority": 2,
"dueDate": "2019-04-18T15:00:01"
},
{
"id": 4,
"name": "test 2",
"isComplete": true,
"type": "shopping",
"priority": 2,
"dueDate": "2019-04-18T08:00:01"
},
{
"id": 6,
"name": "test 4",
"isComplete": false,
"type": "shopping",
"priority": 3,
"dueDate": "2019-04-18T12:00:01"
}
]
Dữ liệu có thể được sắp xếp dữ liệu dựa trên nhiều property. Ví dụ: ?$orderBy=type,priority desc
" sắp xếp các mục dựa trên type
và sau đó priority
theo thứ tự giảm dần.
$filter
Tùy chọn $filter
có thể tiêu tốn quá nhiều tài nguyên. Cân nhắc sử dụng [Queryable(AllowedQueryOptions=AllowedQueryOptions.{Option})]
để vô hiệu hóa $filter
. Xem Hướng dẫn bảo mật cho ASP.NET Core Web API OData để biết thêm thông tin.
$filter
lọc dữ liệu dựa trên điều kiện boolean. Ví dụ: để chỉ nhận các mục có giá trị priority
lớn hơn 1, hãy thêm ?$filter=priority gt 1
vào đường dẫn yêu cầu.
Yêu cầu trên trả về dữ liệu sau:
[
{
"id": 2,
"name": "test 5",
"isComplete": false,
"type": "work",
"priority": 2,
"dueDate": "2019-04-18T15:00:01"
},
{
"id": 4,
"name": "test 2",
"isComplete": true,
"type": "shopping",
"priority": 2,
"dueDate": "2019-04-18T08:00:01"
},
{
"id": 6,
"name": "test 4",
"isComplete": false,
"type": "shopping",
"priority": 3,
"dueDate": "2019-04-18T12:00:01"
}
]
Các điều kiện Boolean sau đây có thể được sử dụng với OData $filter
:
Condition | Mô t | Ví dụ |
---|---|---|
eq | Tương đương với | $filter=priority eq 1 |
ne | không bằng | $filter=priority ne 1 |
gt | Lớn hơn | $filter=priority gt 1 |
ge | Lớn hơn hoặc bằng | $filter=priority ge 1 |
lt | Ít hơn | $filter=priority lt 1 |
le | Nhỏ hơn hoặc bằng | $filter=priority le 1 |
and | logic and | $filter=priority gt 1 and priority lt 10 |
or | logic or | $filter=priority gt 1 or priority lt 10 |
not | logic not | $filter=not endswith(name,'task') |
Các hàm chuỗi có thể được sử dụng với OData $filter. Để biết thêm thông tin, hãy xem phần Quy ước URI OData' $filter
.
$skip
$skip
bỏ qua các bản ghi được chỉ định. Ví dụ: để bỏ qua 4 mục đầu tiên, hãy thêm ?$skip=4
vào yêu cầu.
Yêu cầu trên trả về dữ liệu sau:
[
{
"id": 5,
"name": "test 3",
"isComplete": true,
"type": "work",
"priority": 1,
"dueDate": "2019-04-18T09:00:01"
},
{
"id": 6,
"name": "test 4",
"isComplete": false,
"type": "shopping",
"priority": 3,
"dueDate": "2019-04-18T12:00:01"
}
]
Truy vấn theo chuỗi
Các truy vấn theo chuỗi có thể tiêu tốn quá nhiều tài nguyên. Cân nhắc sử dụng [Queryable(AllowedQueryOptions=AllowedQueryOptions.{Option})]
để vô hiệu hóa các hoạt động tốn kém. Cân nhắc giới hạn $orderby
các property trong chỉ mục nhóm. Xem Hướng dẫn bảo mật cho ASP.NET Core Web API OData để biết thêm thông tin.
Các truy vấn OData có thể được xâu chuỗi để tạo một truy vấn phức tạp. Ví dụ: nối thêm ?$skip=2&$select=name,priority&$orderBy=priority desc&filter=priority gt 1
sẽ trả về dữ liệu sau:
[
{
"Name": "test 2",
"priority": 2
},
{
"Name": "test OData",
"priority": 1
},
{
"Name": "test 3",
"priority": 1
},
{
"Name": "Item1",
"priority": 0
}
]