【发布时间】:2019-06-25 02:56:14
【问题描述】:
是否有一种简单的方法可以重用路由“段”以及用于验证和使用段中参数的控制器逻辑?
例如,我想像这样表示我的资源:
- 房屋
- {住宅地址}
- 架构
- 屋顶
- 壁板
- 房间
- 生活
- 门
- 窗户
- 餐饮
- 门
- 窗户
- 厨房
- 门
- 窗户
- 卧室
- [0]
- 门
- 窗户
- [1]
- 门
- 窗户
- [0]
- 生活
- 架构
- {住宅地址}
以下是一种可行的方法。 有什么更好的方法?
[Route("[controller]")]
[ApiController]
class HousesController : ControllerBase
{
[HttpGet]
public IEnumerable<House> Get() => _housesRepo.GetAll();
[HttpGet("{houseId}")]
public ActionResult<House> Get(string houseId)
{
if (!_housesRepo.TryGetHouse(houseId, out var house))
return NotFound("Bad house ID");
}
}
class RoomsController : ControllerBase
{
[HttpGet("~houses/{houseId}/rooms/bedrooms/{bedroomId}")]
public ActionResult<Room> GetBedroom(string houseId, int bedroomId)
{
if (!_housesRepo.TryGetHouse(houseId, out var house))
return NotFound("Bad house ID");
var bedrooms = house.Bedrooms;
if (bedroomId < 0 || bedroomId >= bedrooms.Length)
return NotFound("Bad bedroom ID");
return bedrooms[bedroomId];
}
[HttpGet("~houses/{houseId}/rooms/{roomClass}")]
public ActionResult<Room> GetRoom(string houseId, string roomClass)
{
if (!_housesRepo.TryGetHouse(houseId, out var house))
return NotFound("Bad house ID");
var roomsByClass = house.RoomsByClass;
if (!roomsByClass.TryGetValue(roomClass, out var room))
return NotFound("Bad room class");
return room;
}
}
class ArchitectureController : ControllerBase
{
[HttpGet("~houses/{houseId}/architecture")]
public ActionResult<string[]> Get(string houseId)
{
if (!_housesRepo.TryGetHouse(houseId, out _))
return NotFound("Bad house ID");
return new [] { "roof", "siding" };
}
[HttpGet("~houses/{houseId}/architecture/roof")]
public ActionResult<Roof> GetRoof(string houseId)
{
if (!_housesRepo.TryGetHouse(houseId, out var house))
return NotFound("Bad house ID");
return house.Architecture.Roof;
}
[HttpGet("~houses/{houseId}/architecture/siding")]
public ActionResult<Siding> GetSiding(string houseId)
{
if (!_housesRepo.TryGetHouse(houseId, out var house))
return NotFound("Bad house ID");
return house.Architecture.Siding;
}
}
但请注意有多少重复:
-
~houses/{houseId}路段 - 验证
houseId并检索关联的House
随着资源变得越来越复杂,重复只会变得更糟。
微软似乎在推动人们拥有一个非常扁平的层次结构。例如:
~houses/{houseId}~architecture/{architectureId}~rooms/{roomId}
但这只会隐藏问题。例如,Room 仅作为House 的组成部分才有意义,因此{roomId} 还必须包含有关房屋ID 的信息。然后我需要解析roomId 以提取houseId 以验证和提取关联的House 资源。
如果我能有这个就好了:
[Segment("HOUSE")]
[HttpGet("houses/{houseId}")]
public ActionResult<House> GetHouse(string houseId) => _housesRepo
.TryGetValue(houseId, out var house)
? new ActionResult<House>(house)
: NotFound("Bad house ID");
[HttpGet("[HOUSE]/architecture")]
public string[] GetArchitectureCategories(House house) => new [] { "roof", "siding" };
[HttpGet("[HOUSE]/architecture/roof")]
public Roof GetRoof(House house) => house.Architecture.Roof;
[HttpGet("[HOUSE]/architecture/siding")]
public Siding GetSiding(House house) => house.Architecture.Siding;
[Segment("BEDROOM")]
[HttpGet("[HOUSE]/rooms/bedrooms/{bedroomId}")]
public Room GetBedroom(House house, int bedroomId) => house.Bedrooms[bedroomId];
[Segment("ROOM")]
[HttpGet("[HOUSE]/rooms/{roomClass}")]
public ActionResult<Room> GetRoom(House house, string roomClass) => house
.RoomsByClass
.TryGetValue(roomClass, out var room)
? new ActionResult<Room>(room)
: NotFound("Bad room class");
这将很容易建立。例如,我可以快速添加门窗控制器:
[HttpGet("[ROOM|BEDROOM]/doors")]
public Door[] GetDoors(Room room) => room.Doors;
[HttpGet("[ROOM|BEDROOM]/windows")]
public Window[] GetWindows(Room room) => room.Windows;
【问题讨论】:
标签: rest asp.net-core asp.net-core-webapi