我可以阻止RedirectToAction将路由值添加到查询字符串吗?

时间:2013-06-28 15:33:53

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

我试图看看是否可以更改Mvc路由以使用基于票证的系统,其中路由是指向外部字典值的guid字符串。所以我设置了一条新的路线:

routes.Add(new Route("{ticketid}", new Shared.TicketRouteHandler()));

并创建了一个新的路由处理程序:

public class TicketRouteHandler : IRouteHandler
{
    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        return new TicketHttpHandler(requestContext);
    }
}

一个新的HttpHandler类。在ProcessRequest方法中,我读取了故障单中控制器和操作的值,并将它们放入路径数据集中:

string ticketidString = this.Request.RouteData.GetRequiredString("ticketid");

var ticket = Shared.Ticket.GetTicket(ticketId);

foreach (var item in ticket)
{
    Request.RouteData.Values[item.Key] = item.Value;
}

从那里开始执行控制器。

在控制器中,我让它查找ticketid参数,如果没有找到它会创建一个,并执行RedirecToAction,用控制器/操作值填充新的Ticket:

public ActionResult Index(Guid? ticketid)
{
    var ticket = Shared.Ticket.GetOrCreateTicket(ticketid);

    if (ticketid == null)
    {
        //push the new values into the ticket dictionary instead of the route
        string controller = "Home";
        string action = "Index";
        ticket.SetRoute(controller, action);
        return RedirectToAction(action, controller, new { ticketid = ticket.Id });
    }

    return View();
}

这一切都运行正常,问题是从重定向操作创建的URL如下所示:

http://localhost:49952/df3b9f26-6c1c-42eb-8d0d-178e03b7e6f6?action=Index&controller=Home

为什么?action=Index&controller=Home会附加到网址?

如果我删除多余的部分并刷新页面,那么所有内容都会从故障单集合中完美加载。

page loading without the extra querystring values

我想在HttpHandler代码完成之后就会发生这种情况。

我该怎么做才能阻止这种行为?

2 个答案:

答案 0 :(得分:3)

RedirectToAction方法发出新请求并更改浏览器中的URL:

这部分正在更改网址:

return RedirectToAction(action, controller, new { ticketid = ticket.Id });

1)Return View不会发出新请求,它只是在浏览器的地址栏中更改URL而不是更改URL。

2)返回RedirectToAction使用MVC生成的URL更新浏览器地址栏中的新请求和URL。

3)返回重定向也会更新浏览器地址栏中的新请求和URL,但您必须指定要重定向的完整URL

4)在RedirectToAction和Redirect之间,最佳做法是将RedirectToAction用于处理应用程序操作/控制器的任何事情。如果您使用重定向并提供URL,则需要在更改路由表时手动修改这些URL。

5)RedirectToRoute重定向到Route表中定义的指定路由。

但是,View没有,请尝试调整代码以返回View!或者,在最坏的情况下,制作一些东西来处理来自Response的URL!

答案 1 :(得分:0)

在挖掘mvc4源代码后,我想我找到了一个解决方案:

RedirectToRouteResult派生新类型,覆盖ExecuteResult并修改网址生成以仅返回故障单字符串:

public class TicketRedirectResult : RedirectToRouteResult 
{
    public override void ExecuteResult(ControllerContext context)
    {
        string destinationUrl = UrlHelper.GenerateUrl(
            RouteName, 
            null /* actionName */, 
            null /* controllerName */, 
            //Only return the ticket id, not the entire dictionary
            new RouteValueDictionary(new { ticketid = RouteValues["ticketid"] }), 
            Routes, 
            context.RequestContext, false /* includeImplicitMvcValues */);
        // snip other code
    }
}

然后在您的控制器中覆盖RedirectToAction以返回新派生类型的实例:

    protected override RedirectToRouteResult RedirectToAction(string actionName, string controllerName, RouteValueDictionary routeValues)
    {
        RouteValueDictionary mergedRouteValues;

        if (RouteData == null)
        {
            mergedRouteValues = MergeRouteValues(actionName, controllerName, null, routeValues, includeImplicitMvcValues: true);
        }
        else
        {
            mergedRouteValues = MergeRouteValues(actionName, controllerName, RouteData.Values, routeValues, includeImplicitMvcValues: true);
        }

        //Only change here
        return new TicketRedirectResult(mergedRouteValues);
    }

现在,重定向仅填充网址中的故障单部分。