WCF 배경에서 웹 API를 처음 접하는 동안 새로운 기능을 익히고 준비하기 전에 Shawn Wildermuth의 Pluralsight 과정을 본 후 다이빙을 시작했습니다. 그의 코스 자료는보다 전통적인 라우팅 방식을 중심으로 디자인되었습니다. 코스가 진행하는 과목 중 하나는 HATEOAS이며 기본 API 컨트롤러 및 모델 공장에서이를 달성하는 것이 얼마나 쉬운가입니다.속성 라우팅 및 쿼리 문자열
속성 라우팅을 구현할 때 가장 먼저 수행 한 작업 중 하나는 UrlHelper가 WebApiConfig에 구성된 기존 라우팅에서 상속 된 Link() 메서드의 첫 번째 인수로 경로 이름을 가져야한다는 것입니다. .cs.
내 컨트롤러 경로 속성 중 하나를 Name 속성으로 꾸미면이 작업을 수행했는데 해당 컨트롤러의 모든 메서드가 어떤 메서드를 사용했는지에 관계없이 name 속성에 액세스 할 수있는 것으로 나타납니다 (아래 코드 참조). 이것이 좀 이상하게 느껴지더라도 작동합니다. 이제는 HATEOAS를 구현 했으므로 생성 된 URL이 쿼리 문자열 형식이고 "url"형식이 아닌 것으로 나타났습니다 (이 용어는 잘못되었지만 나와 함께 있습니다.). 대신 .../api/deliverables/1을 얻는 중 .../api/deliverables? id = 1.
"ok"이지만 원하는 출력이 아닙니다. URL의 반환 값의 형식을 조정하는 방법을 아직 알지 못했지만 컨트롤러에 대해 쿼리 문자열을 테스트 한 결과 쿼리 문자열 형식에서 컨트롤러가 작동하지 않지만 "url "포맷.
나는 그 때 이유를 알아 내려고 노력했다. 나는 디폴트 값, 제약 조건을 설정하고 선택적으로 (즉, {id?}) 설정하는 것과 같이 다른 장식 (예 : [FromUri]은 메시지 본문을 기본으로하는 복잡한 객체에만 필요합니다)을 시도했습니다.
다음은 컨트롤러, 기본 API 컨트롤러 및 HATEOAS 구현을 가능하게 만드는 모델 팩터 모두에 해당하는 코드입니다.
3 개 질문 I이 있습니다
1) 어떻게 컨트롤러 (...// 1 산출물 및 .../산출물 쿼리 문자열에하고 URL 형식으로 "ID를"받아 들일 수 있도록? URL을 도우미의 링크 방식이 현재 쿼리 문자열로 반환합니다 (URL 형식으로 값을 반환 만드는 방법 ID = 1.
2). 이름 경로에
3) 적절한 방법으로 WebAPI 2. 내가하고있는 일 (하나의 메소드에 이름을 할당하고 다른 메소드가 그걸 상속받는 것처럼 보임)은 실제로 냄새가 난다. 실제로 구현하기 시작하면 이것이 엉망이 될 것이라고 믿어야한다. 더 복잡한 코드. Shawn의 구현에 어떤 방식으로 결함이 있습니까? 테스트/개발 목적으로 URL을 하드 코딩하지 않아도되지만 UrlHelper가이를 달성하는 가장 좋은 방법은 아닙니다. 그것은 필요하지 않을 수있는 많은 수화물을 가지고 다니는 것 같습니다.
컨트롤러 :
[RoutePrefix("api/deliverables")]
public class DeliverablesController : BaseApiController
{
private readonly IDeliverableService _deliverableService;
private readonly IUnitOfWork _unitOfWork;
public DeliverablesController(IDeliverableService deliverableService, IUnitOfWorkAsync unitOfWork)
{
_deliverableService = deliverableService;
_unitOfWork = unitOfWork;
}
[Route("", Name = "Deliverables")]
public IHttpActionResult Get()
{
return Ok(_deliverableService.Get().Select(TheModelFactory.Create));
}
[Route("{id}")]
public IHttpActionResult Get(int id)
{
return Ok(TheModelFactory.Create(_deliverableService.Find(id)));
}
[Route("")]
public IHttpActionResult Post([FromBody]DeliverableModel model)
{
try
{
var entity = TheModelFactory.Parse(model);
if (entity == null)
{
return BadRequest("Could not parse Deliverable entry in body.");
}
_deliverableService.Insert(entity);
_unitOfWork.SaveChanges();
return Created(Request.RequestUri + "/" + entity.Id.ToString(CultureInfo.InvariantCulture),TheModelFactory.Create(entity));
}
catch (Exception exception)
{
return BadRequest(exception.Message);
}
}
}
자료 API 컨트롤러 :
public abstract class BaseApiController : ApiController
{
private ModelFactory _modelFactory;
protected ModelFactory TheModelFactory
{
get
{
return _modelFactory ?? (_modelFactory = new ModelFactory(Request));
}
}
}
모델 공장 :
public class ModelFactory
{
private readonly UrlHelper _urlHelper;
public ModelFactory(HttpRequestMessage request)
{
_urlHelper = new UrlHelper(request);
}
public DeliverableModel Create(Deliverable deliverable)
{
return new DeliverableModel
{
Url = _urlHelper.Link("deliverables", new { id = deliverable.Id }),
Description = deliverable.Description,
Name = deliverable.Name,
Id = deliverable.Id
};
}
public Deliverable Parse(DeliverableModel model)
{
try
{
if (string.IsNullOrEmpty(model.Name))
return null;
var entity = new Deliverable
{
Name = model.Name,
Description = !string.IsNullOrEmpty(model.Description)
? model.Description
: string.Empty
};
return entity;
}
catch (Exception)
{
return null;
}
}
}
는 p로 설명이 아닌 속성 (전통) 라우팅의 OINT는 URI와 쿼리 문자열 형식 모두 문제없이 작동 : 제 생각에는
config.Routes.MapHttpRoute(
name: "deliverables",
routeTemplate: "api/deliverables/{id}",
defaults: new { controller = "deliverables", id = RouteParameter.Optional }
);
답변 해 주셔서 감사합니다. 크게 감사드립니다. 여러 경로를 시도했지만 여전히 작동하지 못했습니다. 귀하의 조언에 따라, 필자는 경로 표로 돌아가서 필요할 때마다 속성 라우팅에 다시 접근 할 것입니다. –
나는 그것이 다른 방법으로 라운드해야한다고 생각합니다 - AttributeRouting이 당신의 필요를 충족시키지 않을 때마다 RouteTables를 사용하십시오. – Mrchief