在我的API中,我希望有GET /api/v1/widgets/1,2,3
和GET /api/v1/widgets/best-widget,major-widget,bob-the-widget
等路线
public class WidgetsController : MyApiController
{
public ActionResult Show(IEnumerable<int> ids)
{
}
public ActionResult Show(IEnumerable<string> names)
{
}
}
我已设置路线让我接受操作,但我无法弄清楚如何将1,2,3
变为new List<int>(){1, 2, 3}
等等。当然,我可以采取string
并在我的行动中解析它,但我想避免走那条路。
我想到的一件事是在OnActionExecuting
方法中添加一些东西,但后来我不确定该放在那里的东西(我可以在一起破解某些东西,显然,但我正试图写一些可重复使用的东西。)
我遇到的主要问题是如何知道我是否需要做任何事情(有时上游的ValueProviders会解决所有事情),以及如何处理确定要投射的类型(例如,我怎么知道在这种情况下,我需要去一个整数的集合,或一组字符串,然后我该怎么做?)
顺便说一句,我也有实现ValueProvider
的想法,但在类似的问题上迷失了方向。
答案 0 :(得分:2)
我无法弄清楚如何将1,2,3变成新的List(){1,2,3}等等。
为了避免污染需要接收此参数的每个控制器操作,我建议使用自定义模型绑定器:
public class IdsModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var result = base.BindModel(controllerContext, bindingContext);
var ids = bindingContext.ValueProvider.GetValue("ids");
if (ids != null)
{
return ids.AttemptedValue
.Split(',')
.Select(id => int.Parse(id))
.ToList();
}
return result;
}
}
然后在Application_Start
中注册模型绑定器:
ModelBinders.Binders.Add(typeof(IEnumerable<int>), new IdsModelBinder());
最后你的控制器动作可能看起来像这样(从我在你的问题中可以看到它看起来像这样: - )):
public ActionResult Show(IEnumerable<int> ids)
{
...
}
并且自定义模型绑定器会将ids
路由令牌解析为相应的IEnumerable<int>
值。
您可以使用IEnumerable<string>
执行相同操作,只需删除相应模型装订器中的.Select
子句即可。
答案 1 :(得分:1)
如果您的网址是
/api/v1/widgets/Show?names=best-widget&names=major-widget&names=bob-the-widget
这将整齐地绑定:)
在这种情况下无需覆盖模型绑定器。
查询字符串变量names
将绑定到您的Show-method _
public ActionResult Show(IEnumerable<string> names)
希望这有帮助!
答案 2 :(得分:0)
我对ASP.Net MVC比较陌生,因此我不确定是否有更简单的方法可以做到这一点,但我的方法是做类似以下的事情:
public class WidgetsController : MyApiController
{
public ActionResult Show(string ids)
{
List<int> parsedIds = new List<int>();
foreach (var id in ids.Split(','))
{
parsedIds.Add(int.Parse(id));
}
return Show(parsedIds);
}
private ActionResult Show(List<int> ids);
}
您可能还想为无法解析输入ID的情况添加一些更复杂的错误处理,但这就是我将使用的一般方法。