【问题标题】:Understanding ASP.NET MVC 5 Routing了解 ASP.NET MVC 5 路由
【发布时间】:2015-04-06 01:36:30
【问题描述】:

我知道这里有很多关于 MVC 路由的问答。不幸的是,我仍然遇到一些我不理解的路由问题。

首先 - 我可以在我的控制器中加载 ActionResults 吗?

例如,我用不同的参数向同一个控制器/动作发出 3 个请求。

  • “/MyController/DoSomething”
  • "/MyController/DoSomething/[Guid 字符串]
  • "/MyController/DoSomething/[Guid String]/TypeA

...在控制器中我有这些方法

public ActionResult DoSomething()
{
    ViewBag.Title = "Do Something By Default";
    return View();
}

public ActionResult DoSomething(String id)
{
    ViewBag.Title = "Do Something By id";
    return View();
}

public ActionResult DoSomething(String id, String type)
{
    ViewBag.Title = "Do Something By id and type";
    return View();
}

我希望每个重载的方法都能做到这一点——但事实并非如此。无论我输入什么参数,唯一调用的 ActionMethod 是 DoSomething()。总之,DoSomething(String id) 和 DoSomething(String id, String type) 完全被忽略了。

即使我尝试过这个......

public ActionResult DoSomething(String? id)
{
     ViewBag.Title = "Do Something Conditionally";
     return View();
}

...只是看看会发生什么。抛出编译错误

错误 4 类型 'string' 必须是不可为空的值类型才能按顺序 将其用作泛型类型或方法中的参数“T” 'System.Nullable'

注意:我的参数是字符串(技术上是 GUID)——不是整数。

我想也许我需要在 /App_Start/RouteConfig 类中映射这些路由并尝试这样做只是为了看看我是否可以让一个重载方法工作

routes.MapRoute(
   "MyController",
   "MyController/DoSomething/{id}",
   new { controller = "MyController", action = "DoSomething", id = "" }
);

...仍然没有调用 DoSomething(String id) ActionResult。没有错误,没有例外。如果我什至没有指定 MapRoute。

我在这里缺少什么吗?您能提供的任何见解、指导和指导将不胜感激。

【问题讨论】:

  • 不,路由不能以这种方式工作。您可以实现您想要的,但它涉及更多,并且需要使用路由约束和其他因素。我现在没有时间解释这一点,但希望其他人会。对于任何给定的方法,MVC 只允许每个 HTTP 动词(get、post 等)使用一种操作方法。所以你可以有 Index() 和 Index(string x) 但它们必须是不同的动词。这是模型绑定机制的限制。 MVC 不知道选择哪个重载,因为没有与 HTTP 表单字段或查询字符串关联的类型。
  • 嗯 - 我想这解决了。谢谢埃里克 - 我很欣赏你的洞察力。我将研究路由约束,看看我是否可以解决这个问题。
  • 好的,我能够让这其中的某些方面发挥作用,这肯定会有所帮助。事实证明,我有一个带有参数的 ActionResult,例如:DoSomething(String id) 而我没有 DoSomething() ActionResult 方法——我可以有条件地使用这个方法,带或不带参数。我只用字符串测试过它,但它确实有效。对于插入的新表单和更新的预填充表单使用相同的操作和视图,这当然就足够了。
  • 另外,String? 无效的原因是因为String 是一个引用类型——它已经可以为空。您只能将值类型包装在 Nullable<> 对象中,因为它们不能自己保存 null

标签: asp.net-mvc asp.net-mvc-5 asp.net-mvc-routing maproute


【解决方案1】:

要有效地实现这一点 - 所需要做的就是确定您正在使用的参数并在参数为空的情况下应用默认值。最终这将导致一个单一的动作。在上述示例的情况下 - 删除 DoSomething() 和 DoSomething(String id) 并仅在 DoSomething(String id, String type) 的范围内工作

例子

public ActionResult DoSomething(String id, String type)
{
    var _id = String.Empty
    var _type = String.Empty

    if(id != null)
    {
        _id = id
    }

    if(type != null)
    {
       _type = type
    }

    ViewBag.Title = "Do Something By id and type conditionally";
    return View();
}

当以下请求发出时,它们都将根据单个动作中的逻辑条件工作。

  • “/MyController/DoSomething”
  • "/MyController/DoSomething/[Guid 字符串]
  • "/MyController/DoSomething/[Guid String]/TypeA

【讨论】:

  • 是的,这是处理这个问题的好方法。如果未指定参数,则 type 将为 null(假设您在路由中将参数设为可选)虽然,如果您没有 id,则不能有类型。所以不确定这是否是必需的。
猜你喜欢
  • 2011-06-26
  • 2014-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-14
  • 2015-12-09
  • 2018-05-31
相关资源
最近更新 更多