如何在 MVC 中重载控制器

how to overload controllers in MVC

我正在尝试重载 MVC 控制器,如何正确重载它?

我想在 ListCompanies() 控制器中列出我网站上的所有公司,如下所示

http://localhost:21047/Home/ListCompanies

如果用户进行如下搜索,我想添加搜索条件

http://localhost:21047/Home/ListCompanies/sera

"sera" 是我的搜索条件。如果存在搜索条件,我想根据搜索条件过滤我的搜索结果。

这是我的控制器

public ActionResult ListCompanies()
{
   return View(db.AY_COMPANIES);
}

[ActionName("ListCompaniesFilter")]
public ActionResult ListCompanies(string filter)
{
    var filtredCompanies = from c in db.AY_COMPANIES
                  where c.COMPANY_FULL_NAME.StartsWith(filter)
                               select c;
    return View(filtredCompanies);
}

这是我的 ROUTING,它的行为不正确。

public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
        );

        routes.MapRoute(
            "Home", // Route name
            "{controller}/{action}/{filter}", // URL with parameters
            new { controller = "Home", action = "ListCompanies", filter = UrlParameter.Optional} // Parameter defaults
        );
    }

我的 MapRoutes 不正确,因为它没有正确获得搜索条件。我该如何解决这个问题?

如果您只有一个带有可选参数的操作会怎样?如下所示:

public ActionResult ListCompanies(string filter = null)
{
    var filteredCompanies = string.IsNullOrEmpty(filter)
         ? db.AY_COMPANIES
         : from c in db.AY_COMPANIES
           where c.COMPANY_FULL_NAME.StartsWith(filter)
           select c;
    return View(filteredCompanies);
}

首先这些路线是完全一样的:

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "Home", action = "Index",
              id = UrlParameter.Optional } // Parameter defaults
    );

    routes.MapRoute(
        "Home", // Route name
        "{controller}/{action}/{filter}", // URL with parameters
        new { controller = "Home", action = "ListCompanies", 
              filter = UrlParameter.Optional} // Parameter defaults
    );

它们完全一样,因为参数个数完全匹配(你给参数起的名字和参数类型都不会改变http请求方法的签名)。

有几种不同的方法可以完成这项工作。如果 controller/action/id 符合一组特定的条件,您可以为 Default 编写一个 MapRoute Constraint 来阻止它工作。可能不是最好的做法。

自从

http://localhost:21047/Home/ListCompanies http://localhost:21047/Home/ListCompanies/sera http://localhost:21047/Home/ListCompanies/text http://localhost:21047/Home/ListCompanies/search

在编程上与 {id} 的请求相同,您的方法具有空值 ListCompanies() 我可能会这样写:

public ActionResult ListCompanies(string id)
{
  var query = db.AY_COMPANIES;

  if (!string.IsNullOrWhiteSpace(id))
  {
    query.Where(c => c.COMPANY_FULL_NAME.StartsWith(id))
  }

  var model = query.ToList();

  return View(model);
}

并删除您的 "Home" MapRoute,不需要它。

您不能以这种方式超载,因为两条路线具有相同的三个部分,因此存在调度问题,它们本质上是相同的。

"{controller}/{action}/{id}"

"{controller}/{action}/{filter}"

一种方法是将两个操作方法合并为一个

public ActionResult ListCompanies(string filter)

然后如果过滤器为空 return 完整列表,否则 return 过滤列表。 我不喜欢这种方法。

一个更好但更简单的解决方法是:

1) 删除第二条路由(带过滤器的路由)

2) 更改动作方法的签名

public ActionResult ListCompanies(string filter)

public ActionResult ListCompanies(string id)

允许第一个路由匹配名称上的参数。

3) 由于无法重载方法,因此在请求过滤结果时需要使用 ActionName,

 http://localhost:21047/Home/ListCompaniesFilter/sera