我是來自WCF背景的web api的新手,因爲我在潛水之前觀看了Shawn Wildermuth的Pluralsight課程。他的課程材料是圍繞更傳統的路由而設計的。該課程涉及的主題之一是HATEOAS,通過基礎API控制器和模型工廠實現這一點是多麼容易。屬性路由和查詢字符串
我在實現對屬性路由時遇到的第一件事情是需要UrlHelper將路由名稱作爲Link()方法的第一個參數,這是在WebApiConfig中配置的常規路由中繼承的的.cs。
我通過使用Name屬性裝飾我的控制器路由屬性來解決此問題,並且無論我使用哪種方法(請參見下面的代碼),該控制器中的所有方法都可以訪問name屬性。雖然我覺得這有點奇怪,但它的工作原理。現在我已經實現了HATEOAS,我注意到它生成的URL是以查詢字符串格式生成的,而不是「url」格式(我知道該術語是錯誤的,但是忍受着我)。而不是.../api /交付物/ 1我正在.../api /交付物?id = 1。
這是「好」,但不是所需的輸出。雖然我還沒有想出如何調整URL的返回值的格式,我想我會測試查詢字符串對我的控制器,發現在查詢字符串格式我的控制器不起作用,但在「url 「它的格式。
然後我花了一個小時試圖找出原因。我嘗試過不同的裝飾(即[FromUri],從我的閱讀來看,這隻適用於默認爲消息正文的複雜對象)設置默認值,約束並使其成爲可選項(即{id?})。
下面是有問題的代碼,無論是控制器,基本API控制器和模型工廠,使HATEOAS實現成爲可能。
的3個問題我有是:
1)如何使控制器接受查詢字符串並在URL格式(... /交付/ 1 ... /交付的「身份證」? ID = 1。
2)如何使URL幫手的鏈接方法中的URL格式返回值(這是目前恢復它作爲查詢字符串。
3)以適當的方式來命名路線WebAPI 2.我在做什麼(爲單一方法分配一個名稱,其他人似乎繼承了它,只是聞起來有異味,我必須相信這會崩潰,因爲我實際上開始實施更復雜的代碼。肖恩的執行是否以某種方式存在缺陷?我喜歡不必爲測試/開發目的而硬編碼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