asp.net-web-api
Asp.net 웹 API를 사용한 OData
수색…
OData 패키지 설치
도구 메뉴에서 NuGet 패키지 관리자> 패키지 관리자 콘솔을 선택하십시오. 패키지 관리자 콘솔 창에서 다음을 입력하십시오.
Install-Package Microsoft.AspNet.Odata
이 명령은 최신 OData NuGet 패키지를 설치합니다.
엔터티 프레임 워크 사용
이 자습서에서는 Entity Framework (EF) 코드 우선을 사용하여 백 엔드 데이터베이스를 만듭니다.
웹 API OData에는 EF가 필요하지 않습니다. 데이터베이스 엔티티를 모델로 변환 할 수있는 데이터 액세스 계층을 사용하십시오.
먼저, EF 용 NuGet 패키지를 설치하십시오. 도구 메뉴에서 NuGet 패키지 관리자 > 패키지 관리자 콘솔을 선택하십시오. 패키지 관리자 콘솔 창에서 다음을 입력하십시오.
Install-Package EntityFramework
Web.config 파일을 열고 configSections 요소 다음에 구성 요소 내부에 다음 섹션을 추가하십시오.
<configuration>
<configSections>
<!-- ... -->
</configSections>
<!-- Add this: -->
<connectionStrings>
<add name="ProductsContext" connectionString="Data Source=(localdb)\v11.0;
Initial Catalog=ProductsContext; Integrated Security=True; MultipleActiveResultSets=True;
AttachDbFilename=|DataDirectory|ProductsContext.mdf"
providerName="System.Data.SqlClient" />
</connectionStrings>
이 설정은 LocalDB 데이터베이스에 대한 연결 문자열을 추가합니다. 이 데이터베이스는 앱을 로컬에서 실행할 때 사용됩니다.
그런 다음 ProductsContext 라는 클래스를 Models 폴더에 추가합니다.
using System.Data.Entity;
namespace ProductService.Models
{
public class ProductsContext : DbContext
{
public ProductsContext()
: base("name=ProductsContext")
{
}
public DbSet<Product> Products { get; set; }
}
}
생성자에서 "name = ProductsContext" 는 연결 문자열의 이름을 제공합니다.
OData 끝점 구성
App_Start / WebApiConfig.cs 파일을 엽니 다. 다음 using 문을 추가하십시오.
using ProductService.Models;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;
그런 다음 Register 메소드에 다음 코드를 추가하십시오.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// New code:
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Product>("Products");
config.MapODataServiceRoute(
routeName: "ODataRoute",
routePrefix: null,
model: builder.GetEdmModel());
}
}
이 코드는 두 가지 작업을 수행합니다.
- Entity Data Model (EDM)을 생성합니다.
- 경로를 추가합니다.
EDM은 데이터의 추상 모델입니다. EDM은 서비스 메타 데이터 문서를 만드는 데 사용됩니다. ODataConventionModelBuilder 클래스는 기본 명명 규칙을 사용하여 EDM을 만듭니다. 이 접근법은 최소한의 코드가 필요합니다. EDM을보다 잘 제어하려는 경우 ODataModelBuilder 클래스를 사용하여 속성, 키 및 탐색 속성을 명시 적으로 추가하여 EDM을 만들 수 있습니다.
라우트는 HTTP 요청을 엔드 포인트로 라우트하는 f}을 웹 API에 알립니다. OData v4 라우트를 작성하려면 MapODataServiceRoute 확장 메소드를 호출하십시오.
애플리케이션에 여러 OData 엔드 포인트가있는 경우 각각에 대해 별도의 경로를 작성하십시오. 각 경로에 고유 한 경로 이름과 접두어를 지정하십시오.
OData 컨트롤러 추가
컨트롤러는 HTTP 요청을 처리하는 클래스입니다. OData 서비스의 각 엔터티 집합에 대해 별도의 컨트롤러를 만듭니다. 이 자습서에서는 Product 엔티티에 대해 하나의 컨트롤러를 만듭니다.
솔루션 탐색기에서 Controllers 폴더를 마우스 오른쪽 단추로 클릭하고 추가 > 클래스를 선택 하십시오 . ProductsController 클래스의 이름을 지정합니다.
OData v3에 대한이 자습서의 버전은 Add Controller 스캐 폴딩을 사용합니다. 현재 OData v4에 대한 스캐 폴딩은 없습니다.
ProductsController.cs의 상용구 코드를 다음으로 대체하십시오.
using ProductService.Models;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.OData;
namespace ProductService.Controllers
{
public class ProductsController : ODataController
{
ProductsContext db = new ProductsContext();
private bool ProductExists(int key)
{
return db.Products.Any(p => p.Id == key);
}
protected override void Dispose(bool disposing)
{
db.Dispose();
base.Dispose(disposing);
}
}
}
컨트롤러는 ProductsContext 클래스를 사용하여 EF를 사용하여 데이터베이스에 액세스합니다. 컨트롤러가 Dispose 메서드를 재정 의하여 ProductsContext 를 처리합니다.
이것은 컨트롤러의 시작점입니다. 다음으로 모든 CRUD 작업에 대한 메소드를 추가합니다.
엔티티 세트에서 CRUD 수행
엔티티 세트 쿼리
ProductsController에 다음 메소드를 추가하십시오.
[EnableQuery]
public IQueryable<Product> Get()
{
return db.Products;
}
[EnableQuery]
public SingleResult<Product> Get([FromODataUri] int key)
{
IQueryable<Product> result = db.Products.Where(p => p.Id == key);
return SingleResult.Create(result);
}
매개 변수없는 버전의 Get 메서드는 전체 Products 컬렉션을 반환합니다. 키 매개 변수가있는 Get 메서드는 해당 키 (이 경우 Id 속성)별로 제품을 조회합니다.
[EnableQuery] 특성을 사용하면 클라이언트가 $ filter, $ sort 및 $ page와 같은 쿼리 옵션을 사용하여 쿼리를 수정할 수 있습니다. 자세한 내용은 OData 쿼리 옵션 지원을 참조하십시오.
엔티티 집합에 엔티티 추가
클라이언트가 데이터베이스에 새 제품을 추가 할 수있게하려면 다음 메소드를 ProductsController에 추가하십시오.
public async Task<IHttpActionResult> Post(Product product)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Products.Add(product);
await db.SaveChangesAsync();
return Created(product);
}
엔티티 업데이트
OData는 엔터티, PATCH 및 PUT을 업데이트하는 두 가지 의미를 지원합니다.
- PATCH가 부분 업데이트를 수행합니다. 클라이언트는 업데이트 할 속성 만 지정합니다.
- PUT은 엔티티 전체를 대체합니다.
PUT의 단점은 클라이언트가 변경되지 않는 값을 포함하여 엔티티의 모든 속성에 대한 값을 보내야한다는 것입니다. OData 사양 에서는 PATCH가 선호됩니다.
어쨌든 다음은 PATCH 및 PUT 메서드에 대한 코드입니다.
public async Task<IHttpActionResult> Patch([FromODataUri] int key, Delta<Product> product)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var entity = await db.Products.FindAsync(key);
if (entity == null)
{
return NotFound();
}
product.Patch(entity);
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ProductExists(key))
{
return NotFound();
}
else
{
throw;
}
}
return Updated(entity);
}
public async Task<IHttpActionResult> Put([FromODataUri] int key, Product update)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (key != update.Id)
{
return BadRequest();
}
db.Entry(update).State = EntityState.Modified;
try
{
await db.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ProductExists(key))
{
return NotFound();
}
else
{
throw;
}
}
return Updated(update);
}
PATCH의 경우 컨트롤러는 Delta <T> 유형을 사용하여 변경 사항을 추적합니다.
엔티티 삭제
클라이언트가 데이터베이스에서 제품을 삭제할 수있게하려면 다음 메소드를 ProductsController에 추가하십시오.
public async Task<IHttpActionResult> Delete([FromODataUri] int key)
{
var product = await db.Products.FindAsync(key);
if (product == null)
{
return NotFound();
}
db.Products.Remove(product);
await db.SaveChangesAsync();
return StatusCode(HttpStatusCode.NoContent);
}