gpt4 book ai didi

c# - 基于 Accept header 的 Web API 操作选择

转载 作者:太空狗 更新时间:2023-10-29 21:54:23 24 4
gpt4 key购买 nike

队列长介绍...

我有一个资源定义在

http://my-awesome-product.com/api/widgets/3

代表 id 为 3 的小部件。在 Web API 中,我将定义一个 Controller 来为该资源提供服务,如下所示:

public class WidgetsController : ApiController
{
public Widget Get(int id)
{
return new Widget(...);
}
}

现在,Widget 类可能非常大,并且想要节省从数据库到 Web 服务器以及从 Web 服务器到客户端的带宽,我创建了几个 DTO 类,其中包含整个 Widget 的有限数量的字段。例如:

public class WidgetSummary
{
public int Id { get; set; }
public string Code { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
}

public class FullWidgetForEditing
{
public int Id { get; set; }
public string Code { get; set; }
public string Description { get; set; }
public decimal Weight { get; set; }
public decimal Price { get; set; }
public Color Color { get; set; }
public decimal Width { get; set; }
public decimal Height { get; set; }
public decimal Depth { get; set; }
}

public class WidgetForDropDownList
{
public int Id { get; set; }
public string Code { get; set; }
}

使用这些 Widget 表示,客户端将请求 WidgetSummary 显示在系统中所有 Widget 的摘要网格上,它会在特定 Widget 的编辑页面上请求 FullWidgetForEditing,它会请求 WidgetForDropDownList 用于下拉列表订单。

根据我对 REST 的理解,要访问 Widget 应该有一个 URL,因为它是一个资源,无论其表示如何,客户端应该指定 Accept 带有媒体类型参数的 header 以检索不同形式的 Widget,例如my-awesome-product.type=widgetsummarymy-awesome-product.type=fullwidgetforeditingmy-awesome-product.type=widgetfordropdownlist

我可以通过像这样检查请求的 header 在 Web API 中实现这一点:

public class WidgetsController : ApiController
{
public object Get(int id)
{
if (Request.Headers.Accept.Any(x => x.Parameters.Any(y => y.Name == "my-awesome-product.type" && y.Value == "widgetsummary")))
{
return new WidgetSummary(...);
}
else if (Request.Headers.Accept.Any(x => x.Parameters.Any(y => y.Name == "my-awesome-product.type" && y.Value == "fullwidgetforediting")))
{
return new FullWidgetForEditing(...);
}
else if (Request.Headers.Accept.Any(x => x.Parameters.Any(y => y.Name == "my-awesome-product.type" && y.Value == "widgetfordropdownlist")))
{
return new WidgetForDropDownList(...);
}

throw new HttpResponseException(HttpStatusCode.NotAcceptable);
}
}

但是,随着类型数量的增加,这很快就会变得困惑,并使单元测试变得更加困难。我真正想做的是:

public class WidgetsController : ApiController
{
[HttpGet(MediaType = "my-awesome-product.type", MediaTypeValue = "widgetsummary")]
public WidgetSummary GetWidgetSummary(int id)
{
return new WidgetSummary();
}

[HttpGet(MediaType = "my-awesome-product.type", MediaTypeValue = "fullwidgetforediting")]
public FullWidgetForEditing GetFullWidgetForEditing(int id)
{
return new FullWidgetForEditing();
}

[HttpGet(MediaType = "my-awesome-product.type", MediaTypeValue = "widgetfordropdownlist")]
public WidgetForDropDownList GetWidgetForDropDownList(int id)
{
return new WidgetForDropDownList();
}
}

并且让 Web API 路由到基于媒体类型的特定操作方法。我研究了覆盖 ApiControllerActionSelector,但是,我开始为该属性引入大量现有代码,因为我真的想要默认操作选择,但在操作不明确的情况下,我想过滤基于媒体类型的操作列表。我真的希望它是非侵入式的,这样我就可以在需要的时候在同一个 Controller 中混合约定路由、标准属性路由(在 Web API v2 中)和这个假设的属性路由。

提问时间:目前是否可以按现状用Web API实现这样的路由策略?我是否必须完全重新实现 ApiControllerActionSelector 才能实现此目的(然后确保我的重新实现保持最新)?

最佳答案

所以这是你需要思考的问题。这真的是三种表示,还是三种不同的资源?如果您决定缓存这些表示,URI 是否足以识别缓存的表示,或者您是否还需要改变接受 header ?

如果您接受它们的差异足以成为资源,那么它们应该由不同的 URL 标识。如果您决定在回复中使用超链接,您是否不希望能够独立于“widgeteditform”指向“widgetsummary”?

当您想要支持只能支持特定媒体类型的不同客户端设备时,通常需要多种表示形式。例如设备 A 获得 Rep1,设备 B 获得 Rep2。您很少希望 Device A 同时访问 Device A 和 Rep1 和 Rep2。

只是我的想法...

关于c# - 基于 Accept header 的 Web API 操作选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18439166/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com