我正在尝试将ASP.NET MVC中的TinyURL克隆作为学习项目。
现在,我想要的是能够通过表单向我的/ Home / Create操作提交新的URL。
我有我的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
答案 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 );
它会完成同样的事情,并且当没有提供哈希时,它无关紧要