RedbinToAction上没有保留MVC路由

时间:2017-02-15 13:52:02

标签: c# asp.net asp.net-mvc asp.net-mvc-routing

我有这条路线配置:

routes.MapRoute(
           "routeB",
           "routeB/{action}/{id}",
           new { controller = "Sample", action = "IndexB", id = UrlParameter.Optional });

        routes.MapRoute(
           "routeA",
           "routeA/{action}/{id}",
           new { controller = "Sample", action = "IndexA", id = UrlParameter.Optional });

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );

我的Sample控制器包含以下Action方法:

 public ActionResult IndexA(string id)
    {

        return View("Index");
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult IndexA()
    {
        return RedirectToAction("Confirmation");
    }

    public ActionResult Confirmation()
    {
        return View("Confirmation");
    }

    public ActionResult IndexB(string id)
    {
        return View("Index");
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult IndexB()
    {
        return RedirectToAction("Confirmation");
    }

如果我登陆localhost / RouteA页面并进行POST(通过按钮),它会将我重定向到localhost / RouteB / Confirmation。

如何让页面重定向到RouteA / Confirmation页面?

感谢。

3 个答案:

答案 0 :(得分:1)

这里有2个问题。正如其他人指出的那样,您的HTTP POST需要更正。由于您要为2个不同的操作共享单个视图,因此最简单的方法是将actionName参数设置为null。这告诉MVC使用当前请求中的动作名称。

@{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Layout.cshtml"; }

<h2>Index</h2>

@using (Html.BeginForm(null, "Sample", new { id = "OrderForm" }))
{

    @Html.AntiForgeryToken()
    <button type="submit" id="orderFormBtn">Extend my discount.</button>
}

第二个问题是RedirectToAction生成网址时routeArouteB之间的RedirectToRoute调用不明确。由于第一次匹配总是获胜,因此您重定向到的URL始终是配置中的最高位置。

您可以使用public class SampleController : Controller { public ActionResult IndexA(string id) { return View("Index"); } [HttpPost] [ValidateAntiForgeryToken] public ActionResult IndexA() { return RedirectToRoute("routeA", new { action = "Confirmation" }); } public ActionResult Confirmation() { return View("Confirmation"); } public ActionResult IndexB(string id) { return View("Index"); } [HttpPost] [ValidateAntiForgeryToken] public ActionResult IndexB() { // Note that changing this one to RedirectToRoute is not strictly // necessary, but may be more clear to future analysis of the configuration. return RedirectToRoute("routeB", new { action = "Confirmation" }); } } 明确指定路由名称(除现有匹配条件之外)来解决此问题。

@escaping

答案 1 :(得分:0)

你的问题很简单。 看看你的控制器,方法IndexA和IndexB,返回相同的视图; (来自你的评论)

@{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Layout.cshtml"; } 

<h2>Index</h2>

using (Html.BeginForm("IndexB", "Sample", new { @id = "OrderForm" })) { 

@Html.AntiForgeryToken() 
<button type="submit" id="orderFormBtn">Extend my discount.</button> 
}

当您点击提交时,您总是发帖到IndexB

有很多方法可以纠正这样一个简单的错误,例如,您可以使用2个不同的视图IndexAIndexB并更改

using (Html.BeginForm("IndexB", "Sample", new { @id = "OrderForm" })) {

using (Html.BeginForm("IndexA", "Sample", new { @id = "OrderForm" })) {

答案 2 :(得分:0)

问题在于,routeArouteB路由都可用于为IndexA中的SampleController操作创建链接。结果,BeginForm将只是短路并选择将起作用的第一条路线,这可能是也可能不是正确的&#34;一个你正在寻找的人。要区分路线,请通过路线名称生成它们:

@using (Html.BeginRouteForm("routeA", new { @id = "OrderForm" })) {

然而,这只会让你得到&#34;默认&#34; routeA路由,即/routeA/。除路由的默认操作外,无法指定其他操作。

为了获得更大的灵活性,您可以使用属性路由,这将允许您为每个操作提供自定义路由名称,然后您可以使用该名称来获取该操作的URL。

除此之外,您需要以某种方式区分这两条路线,以便在生成URL时不应使用这些路线。对于标准路由来说,这通常很难做到,这就是为什么属性路由是一个更好的方法,如果你不再仅仅使用默认路由来解决所有问题。

或者,您可以重新构建项目以保持相同的URL结构,但可以更轻松地区分路径。通过使用区域,您可以指定应从中创建路径的区域。例如,假设您有RouteARouteB区域,则可以执行以下操作:

@using (Html.BeginForm("IndexB", "Sample", new { area = "RouteA", @id = "OrderForm" })) { 

这意味着在每个区域都有SampleController,但您可以使用继承来重用代码。