为什么这个表单不能在ASP.NET MVC中调用我的控制器操作?

时间:2009-04-12 05:10:12

标签: asp.net-mvc webforms

我正在尝试将ASP.NET MVC中的TinyURL克隆作为学习项目。

现在,我想要的是能够通过表单向我的/ Home / Create操作提交新的URL。

alt text

我有我的LINQ表达式所有设置,我有我的路由设置,我有我的视图设置但我的设置有问题。

路由:

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

 routes.MapRoute(
            "Redirect",
            "{hash}",
            new { controller = "Home", action = "RequestLink", hash = "" }
        );

这些路线让我可以访问我的网站www.tinyurlclone.com/,如果没有通过,我只会转到我的Home / Index()动作。但是,如果在斜杠之后放置任何内容,它将考虑使用Link Hash并尝试检索哈希。

我的HomeController如下:

[HandleError]  
public class HomeController : Controller  
{  
    TinyGetRepository repo = new TinyGetRepository();

    public ActionResult Index()
    {
        return View();
    }


    public ActionResult Create(String url)
    {
        String hash = repo.addLink(url);
        ViewData["LinkHash"] = hash;
        return View();
    }

    public ActionResult RequestLink(String hash)
    {
        String url = repo.getLink(hash);
        return Redirect(url);

    }
}

我的repo类中包含了所有用于处理数据库的LINQ表达式,我并不需要包含它们,因为它与这个问题无关。

最后,我的基本Home / Index()视图(用于提交网址)如下:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Index</title>
</head>
<body>
    <div>
    <center>
            <span style="font-size: 14pt">TinyGet <em>(beta)</em></span><br />
            <span style="font-family: Tahoma">Reduce your long links to smaller ones to keep them more memorable....<br />
            </span>
            <% using(Html.BeginForm("Create", "Home")) %>
            <% { %>
            <%= Html.TextBox("url") %>
            <input type="submit" name="submitButton" value="Shorten Link!" />
            <% } %>

      </center>
    </div>
</body>
</html>

但是,当我点击提交时,我的表单根本没有触发任何方法。

此外,如果我查看生成的HTML的来源,我可以看到它没有正确执行我的表单操作,它显示为:

<form action="" method="post"><input id="url" name="url" type="text" value="" />
            <input type="submit" name="submitButton" value="Shorten Link!" />
            </form>

为什么HTML帮助器将“”作为动作放在/ Home / Create中?为什么不调用我的/ Home / Create操作方法?即使我不使用Html助手并指定<form&gt;手动标记它会引发错误。

这里有什么问题?

项目来源:here

2 个答案:

答案 0 :(得分:3)

问题是您没有与路线值匹配的路线(controller = Home,action = Create)。

你有两条路线,一条是空字符串(没有参数),它匹配Controller =“Home”,Action =“Index”。另一个是您的哈希路由,它匹配Controller =“Home”,Action =“RequestLink”。因此,当ASP.Net Routing根据您提供的路由值构建URL时,它找不到一个(因为它们都没有“{controller}”和“{action}”参数)。

在这种情况下,最简单的解决方案是创建一个指向“创建”操作的直接路径,这样您仍然可以使用“哈希”路径。将它放在RegisterRoutes方法的顶部。注意:订单确实很重要! ASP.Net Routing按添加的顺序检查每条路由,直到找到匹配为止。

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

由于您具有“哈希”路由,因此您无法真正使用默认的“{controller} / {action} / {id}”技术,因为“哈希”值将被视为有效的控制器名称。因此,如果有人请求:http://www.mysite.com/fjhas82,MVC会寻找一个名为“fjhas82”的控制器并抱怨它无法找到它。不幸的是,这意味着您必须为每个新的Controller Action手动添加新路由(如上所示),这很痛苦。

最好的解决方案(在我看来)是使用正则表达式约束:如果您的哈希值具有非常明确的格式(例如:5个字母后跟2个数字,或“_”后跟任何字母数字字符等。),或者如果您愿意强加这样的格式,您可以使用ASP.Net Routing支持的Regex约束。那么,你只需要这两条路线

routes.MapRoute(
        "Redirect",
        "{hash}",
        new { controller = "Home", action = "RequestLink" },
        new { hash = @"[a-zA-Z]{5}[0-9]{2}" } // Regex Constraints
    );

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

在这些路由下,如果MVC看到控制器名称如“Home”,它将检查第一条路径,发现它与正则表达式不匹配,然后移动到下一条路径。注意:我的正则表达式语法可能有点生疏,所以我首先使用类似http://regexpal.com/的东西来测试正则表达式,以确保它适用于您的哈希和控制器名称。

希望有所帮助,我知道我写了很多,但MVC非常灵活,你可以用很多不同的方式做事!

答案 1 :(得分:0)

我遇到的问题与路由采用最后路径

有关

所以它使用你的哈希路线,因此它的推杆“”

基本上你可以摆脱那个哈希路线,只需要这个

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

它会完成同样的事情,并且当没有提供哈希时,它无关紧要