【问题标题】:MVC Action with Optional Parameters -- which is better?带有可选参数的 MVC 操作——哪个更好?
【发布时间】:2012-04-11 23:13:02
【问题描述】:

在您的动作签名中使用以下两种替代方案是否有任何优点/缺点:

public ActionResult Action(int? x) // get MVC to bind null when no parameter is provided
{
    if(x.HasValue)
    {
        // do something
    }
}

public ActionResult Action(int? x = null) // C# optional parameter (virtual overload)
{
    if(x.HasValue)
    {
        // do something
    }
}

【问题讨论】:

  • 我认为在第一种情况下你需要参数,而在另一种情况下,如果没有传递参数,它会假定 null,所以它实际上是你真正想要的第二个(只是猜测)。
  • @V4Vendetta no 第一种情况在作为 Web 请求调用时不需要显式参数。

标签: c# .net asp.net-mvc asp.net-mvc-3 c#-4.0


【解决方案1】:

我在实践中从未见过第二个动作签名,也看不出它有什么用处。

第一个通常涵盖所有场景:

  • 如果不发送任何参数 (GET /somecontroller/action),x 参数的值将在操作内为空
  • 如果发送了 x 参数,但它不是有效的整数 (GET /somecontroller/action?x=abc),则 x 参数的值将在操作中为 null,并且模型状态将无效
  • 如果发送了 x 参数并且值表示有效整数 (GET /somecontroller/action?x=123),则将为其分配 x。

在我的示例中,我使用了带有查询字符串参数的 GET 请求,但显然这同样适用于其他 HTTP 动词,如果 x 是一个路由参数。

【讨论】:

  • 很好的答案,但请注意 int? x = null 什么都不做。 null 是默认值
  • 嗨@Darin,我收到了一个没有发送参数的请求,但我的参数值没有设置为null,而是对象的默认值。我更喜欢空值。关于可能导致它的任何想法?我会提出一个新问题,但它可能会被当作骗子关闭!
  • @DoctaJonez 假设您在签名中指定了一个可以为空的类型,例如 int?
  • @ZaidMasud 是的,它是一个可为空的 int。我发现它正在从其他地方获取价值。我不记得确切的细节,但它正在获取碰巧具有相同名称的不同字段(不在模型中)的默认值。抱歉,我不能更具体!
【解决方案2】:

如果它是null以外的任何其他值,您只需要指定可选参数值。

如果在重载或对 Action 的调用中未指定任何内容,MVC3 将自动将 null 设置为您的参数值。

但值得注意的是,如果签名中此参数后有任何非可选参数,则必须在调用中指定null

因此最好将所有可选参数放在签名的末尾。

【讨论】:

  • 请扩展您所说的“仍然为空”是什么意思?确实,当没有提供参数时,MVC 框架会将其绑定到空值,但请注意,它是 MVC 为您执行此操作的。在第二种选择中,我们明确指定了重载。
【解决方案3】:

最佳 Asp.net MVC 解决方案 - 使用操作方法选择器

为什么不通过删除不必要的代码分支来简化控制器操作方法,并拥有如下所示的这种代码:

public ActionResult Index()
{
    // do something when there's no id
}

[RequiresRouteValues("id")]
public ActionResult Index(int id)
{
    // do something when id is present
}

这当然是可能的,只要您提供RequiresRouteValuesAttribute 操作方法选择器的非常简单的代码即可。您可以在 this blog post 中找到执行此操作的代码。

在我看来,这是解决这个问题的最佳方法,因为:

  1. 它通过删除不必要的分支来简化代码
  2. 使代码更易于维护(由于复杂性较低)
  3. 尽可能扩展 Asp.net MVC 框架
  4. 保持参数类型应有的状态,而不需要使它们可以为空

无论如何。有关此技术的所有细节都在链接的帖子中进行了详细说明。

【讨论】:

  • 这只适用于路由定义中定义的id参数吗?如果该参数被称为其他名称,我相信 RequiresRouteValues 属性将不再需要,并且解决方案将类似于我的第二个代码示例,当然分支更少。感谢您的想法,但您可能会在这里回答不同的问题。
  • 不,这适用于任何控制器操作参数。这并不意味着提供的参数名称必须在路由定义中。它们可能也与查询值、发布字段有关......不,它与您的第二个示例完全不同。这个属性是一个动作方法选择器而不是一个动作过滤器......如果特定动作参数不是请求的一部分(作为路由值、查询变量或发布字段的一部分),则根本不会执行此方法。 MVC 不会将此方法解析为请求处理的可能候选者。
  • @zooone9243:当然,我的回答并没有直接回答你提出的问题,但它提供了一个更好、更清晰的解决方案,不会让你回答你的问题首先。
  • 罗伯特 我建议将其发布为this question的答案。
  • @ZaidMasud:这是一个早就应该回答的老问题,已经得到了充分的回答,涵盖了 90% 的此类案例。动作方法选择器是 MVC 中的高级主题。动作重命名不是...
猜你喜欢
  • 1970-01-01
  • 2016-11-17
  • 2014-11-10
  • 1970-01-01
  • 2011-06-30
  • 2014-12-07
  • 1970-01-01
  • 1970-01-01
  • 2020-01-30
相关资源
最近更新 更多