asp.net mvc 路由:如何使用默认操作但非默认参数?

Posted

技术标签:

【中文标题】asp.net mvc 路由:如何使用默认操作但非默认参数?【英文标题】:asp.net mvc routing: how to use default action but non-default parameter? 【发布时间】:2011-08-01 06:50:10 【问题描述】:

我正在重写这个问题,因为到目前为止的答案告诉我,我对它的定义不够好。我将在下面留下原始问题以供参考。

设置路由时,您可以为不同的 url/路由部分指定默认值。让我们考虑 VS 向导生成的示例:

        routes.MapRoute(
            "Default", // Route name
            "controller/action/id", // URL with parameters
            new  controller = "DefaultPage", action = "Index", id = UrlParameter.Optional  // Parameter defaults

在此示例中,如果未指定控制器,将使用 DefaultPageController,如果未指定操作,则将使用“索引”操作。 url 通常看起来像:http://mysite/MyController/MyAction

如果 Url 中没有类似这样的操作:http://mysite/MyController,则将使用索引操作。

现在假设我的控制器 Index 和 AnotherAction 中有两个动作。对应的url分别是http://mysite/MyControllerhttp://mysite/MyController/AnotherAction。我的“索引”操作接受一个参数 id。因此,如果我需要将参数传递给我的索引操作,我可以这样做:http://mysite/MyController/Index/123。请注意,与 URL http://mysite/MyController 不同,我必须明确指定 Index 操作。我想要做的是能够通过http://mysite/MyController/123 而不是http://mysite/MyController/Index/123。我不需要这个 URL 中的“索引”我希望 mvc 引擎识别,当我要求 http://mysite/MyController/123 时,123 不是一个动作(因为我没有用这个名称定义一个动作),而是一个参数我的默认操作“索引”。如何设置路由来实现这一点?

以下是问题的原文。


我有一个控制器,其中定义了两种方法

    public ActionResult Index()
    
        return View();
    

    [HttpPost]
    public ActionResult Index(SomeFormData data)
    
        return View();

    

这使我可以在用户导航到此 url (GET) 以及随后发回表单 (POST) 时像 http://website/Page 这样处理 Url。

现在,当我处理回帖时,在某些情况下我想将浏览器重定向到这个网址:

http://website/Page/123

其中 123 是某个整数,我需要一种方法来在我的控制器中处理此 url。

如何设置路由,这样才有效?目前我有向导生成的“默认”路由,如下所示:

        routes.MapRoute(
            "Default", // Route name
            "controller/action/id", // URL with parameters
            new  controller = "DefaultPage", action = "Index", id = UrlParameter.Optional  // Parameter defaults

我尝试像这样添加另一个控制器方法:

public ActionResult Index(int id)

    return View();

但这不起作用,因为引发了模棱两可的动作异常:

当前对“索引”操作的请求 在控制器类型“PageController”上 在以下之间是模棱两可的 行动方法: System.Web.Mvc.ActionResult Index() on 类型 PageController System.Web.Mvc.ActionResult PageController 类型上的索引(Int32)

我必须补充一点,我在这个控制器中还有其他操作。如果我不这样做,This 会起作用。

【问题讨论】:

【参考方案1】:

解决方法如下:

您可以创建一个路由约束,以向路由引擎指示,如果您在 url 中有一些看起来像数字 (123) 的内容,那么这是默认操作的操作参数,如果您有一些没有的内容看起来像一个数字(AnotherAction)那么它就是一个动作。

考虑这段代码:

routes.MapRoute(
  "MyController", "MyController/productId", 
  new controller="My", action="Index", 
  new productId = @"\d+" );

此路由定义将仅匹配 http://mysite/MyController/123 中 MyController 之后的数值,因此它不会干扰在同一控制器上调用另一个操作。

来源:Creating a Route Constraint

【讨论】:

我遇到了完全相同的问题。控制器是“/Profile/xxxxx”,其中 XXXX 可以是我网站上的用户名,或者是配置文件控制器中的其他方法。路线限制不太有效 b/c 所有 XXX 都是 alpha。相反,我创建了一个“/Profiles/Username”路由(注意复数形式)并映射了 Profiles --> Profile 控制器。 不错!谢谢分享!【参考方案2】:

如果您将变量名保持为 ID,则无需更改任何内容。

将帖子一重命名为“PostIndex”并添加此属性:

[ActionName("Index")]

关于 SO here 的同样问题。

好的,如果有帮助,这是一个剪切/粘贴的答案。

public ActionResult Index()            
return View();    
    
[AcceptVerbs(HttpVerbs.Post), ActionName("Index")]   
public ActionResult PostIndex(SomeFormData data)            
return View();    

【讨论】:

正如我在问题中提到的,在这种情况下我遇到了一个例外。以下是文本:当前对控制器类型“ActionController”的操作“索引”的请求在以下操作方法之间不明确: System.Web.Mvc.ActionResult Index() on type ActionController System.Web.Mvc.ActionResult Index(Int32 ) 在 ActionController 类型上 post方式没有问题。发布方法工作得很好。它是默认操作和非默认参数,这给我带来了麻烦。 我明白,但这是因为你有重复的名字。按照说明重命名 POST 并为其赋予 Index 的 ActionName 属性。 如果对您来说更容易,请完全忽略 post 操作。即使它根本不存在,这个问题仍然有效。我在问题中提到它是为了提供更完整的图片。 除非您明确什么是 SomeData 并证明它有效,否则我们将无法提供帮助。你需要一种方法来区分。如果它通常是一个字符串,并且你想在它是一个整数时做出不同的响应,你只能使用 1 个 Action。在该操作中,自己进行整数测试并相应地返回适当的视图。【参考方案3】:

哦,我现在明白了。我认为默认路由是不可能的,你需要映射自定义路由。

    // /MyController/AnotherAction
    routes.MapRoute(
        null,
        "MyController/AnotherAction",
        new  controller = "DefaultPage", action = "AnotherAction" 
    );

    // /MyController
    // /MyController/id
    routes.MapRoute(
        null,
        "MyController/id",
        new  controller = "DefaultPage", action = "Index", id = UrlParameter.Optional 
    );

ps。默认路由如 /MyController/id 必须最后映射。

【讨论】:

谢谢,但这也不起作用。当我尝试获取website/Page/123 时,我收到一个错误,即没有操作,称为 123。我怀疑有可能以某种方式更改路由以使 asp.net mvc 了解 123 不是操作,而是用于默认操作,但我不知道如何。这是我想知道的。 是的,更接近了。它确实需要单独指定每个操作。在我发现的文章中(见我的回答),他们使用基于正则表达式的约束。这样,您无需指定您拥有的所有其他操作。非常感谢您的意见。 +1 呃,我不知道——因为这个,我映射了路线中的所有动作。约束看起来很棒。谢谢你告诉我。【参考方案4】:

我认为您希望返回相同的视图,但您需要了解您正在做两件不同的事情。一个是receive post,一个是get访问,一个是get和parameter访问……

您应该使用不同的名称执行 3 个 actionresult,并返回与 View("ThisIsTheResult") 相同的视图

【讨论】:

以上是关于asp.net mvc 路由:如何使用默认操作但非默认参数?的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET MVC、本地化路由和用户的默认语言

asp.net mvc 路由约束正则表达式

asp.net MVC路由问题? 删除默认路由可以正常访问 路由配置请看下面内容 asp.net?dotNet编程? C#语言编程

在 ASP.NET MVC 3 中为控制器设置默认操作(而不是索引)

asp.net core 系列 5 MVC框架路由(上)

如何正确处理 ASP.NET MVC 中的 404?