【问题标题】:Overload Index() Method in MVC ControllerMVC 控制器中的重载 Index() 方法
【发布时间】:2012-07-26 16:17:20
【问题描述】:

我想同时访问 /Blog 和 /Blog/1,其中“1”是博客的 ID。这是我的代码:

    '
    ' GET: /Blog/

    Function Index() As ViewResult
        Return (View(db.Blogs.ToList()))
    End Function

    '
    ' GET: /Blog/(Integer)

    Function Index(id As Integer) As ViewResult
        Dim blog As Blog = db.Blogs.Find(id)
        Return View("Details", "_MyLayout", blog)
    End Function

它给出了错误:

“/”应用程序中的服务器错误。

当前对控制器类型的操作“索引”请求 'BlogController' 在以下操作方法之间不明确: System.Web.Mvc.ViewResult Index() 类型 GemcoBlog.GemcoBlog.BlogController System.Web.Mvc.ViewResult GemcoBlog.GemcoBlog.BlogController 类型的索引(Int32)

描述:执行过程中发生了未处理的异常 当前的网络请求。请查看堆栈跟踪以获取更多信息 有关错误的信息以及它在代码中的来源。

异常详细信息:System.Reflection.AmbiguousMatchException: 当前对控制器类型“BlogController”的操作“索引”请求 以下动作方法之间有歧义: System.Web.Mvc.ViewResult Index() 类型 GemcoBlog.GemcoBlog.BlogController System.Web.Mvc.ViewResult GemcoBlog.GemcoBlog.BlogController 类型的索引(Int32)

来源错误:

在执行过程中产生了一个未处理的异常 当前的网络请求。有关原产地和位置的信息 可以使用下面的异常堆栈跟踪来识别异常。

如何重载 Index() 方法?

编辑:

我也在尝试像这样组合它们:

    '
    ' GET: /Blog/

    Function Index(id As Integer) As ViewResult
        If (id) Then
            Dim blog As Blog = db.Blogs.Find(id)
            'Return View(blog)
            Return View("Details", "_MyLayout", blog)
        Else
            Return (View(db.Blogs.ToList()))
        End If
        'Return View(db.Blogs.Where(Function(x) x.Name = "Test").ToList())
    End Function

但是,我得到的错误是:

“/”应用程序中的服务器错误。

参数字典包含参数“id”的空条目 方法“System.Web.Mvc.ViewResult”的不可空类型“System.Int32” 'Blog.Blog.BlogController' 中的索引(Int32)'。一个可选的 参数必须是引用类型、可为空的类型或声明为 一个可选参数。参数名称:参数

描述:执行过程中发生了未处理的异常 当前的网络请求。请查看堆栈跟踪以获取更多信息 有关错误的信息以及它在代码中的来源。

异常详细信息:System.ArgumentException:参数字典 包含不可为空类型的参数“id”的空条目 方法“System.Web.Mvc.ViewResult Index(Int32)”的“System.Int32” '博客.博客.博客控制器'。可选参数必须是 引用类型,可为空的类型,或被声明为可选 范围。参数名称:参数

来源错误:

在执行过程中产生了一个未处理的异常 当前的网络请求。有关原产地和位置的信息 可以使用下面的异常堆栈跟踪来识别异常。

【问题讨论】:

    标签: asp.net-mvc vb.net asp.net-mvc-3


    【解决方案1】:

    您不能在同一个控制器上使用相同的 HTTP 动词访问 2 个操作。因此,要么更改操作名称,要么您必须使用不同的 HTTP 动词来消除歧义。例如:

    <HttpPost>
    Function Index(id As Integer) As ViewResult
        Dim blog As Blog = db.Blogs.Find(id)
        Return View("Details", "_MyLayout", blog)
    End Function
    

    但由于其他操作似乎也在获取数据,我猜你不想让它只能通过 POST 访问。所以在这种情况下只需重命名它。坚持标准 RESTful 约定,您可以使用 Index 返回资源列表,使用 Show 返回特定资源:

    Function Index() As ViewResult
        Return (View(db.Blogs.ToList()))
    End Function
    
    '
    ' GET: /Blog/(Integer)
    
    Function Show(id As Integer) As ViewResult
        Dim blog As Blog = db.Blogs.Find(id)
        Return View("Details", "_MyLayout", blog)
    End Function
    

    【讨论】:

    • 这是否意味着 URL 必须是 /Blog/Show/1 而不是 Blog/1?如果我只是将它们组合成一种方法会怎样。我用新代码更新了问题,但它也给了我一个错误。
    • 您可以在 Global.asax 的路由配置中将 Show 操作设为默认:action = "Show" 而不是 action = "Index"。现在您可以使用/Blog/123。不,不要将 2 组合成一个动作。那将是一个糟糕的设计决策。
    【解决方案2】:

    有几种方法可以做到这一点。最简单的方法是将第一个方法重命名为“ShowBlog”或您想要的任何名称,然后在 global.asax 中设置一个路由,该路由无需参数即可路由到 /Blog 路由。

    例如(在 c# 中):

    routes.MapRoute("Blog", "Blog", new { controller = "Blog", action = "ShowBlog" });
    

    确保 MapRoute 位于默认路由之前。

    要使您的第二种方法有效,您需要使 id 可以为空,然后在您的方法中检查 null。

    【讨论】:

      【解决方案3】:

      由于它不可为空,它会自动假定您默认提供了一个 id。将 Id 设为 Nullable Integer,它将适用于两个 URL。

      函数索引(id As Nullabe(Of Integer)) As ViewResult

      【讨论】:

        【解决方案4】:

        对 Erik 的帖子进行小修改以使其正常工作(我正在使用 MVC4)

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-10-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-12-06
          • 1970-01-01
          • 2017-11-07
          相关资源
          最近更新 更多