我试图看看是否可以更改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
会附加到网址?
如果我删除多余的部分并刷新页面,那么所有内容都会从故障单集合中完美加载。
我想在HttpHandler代码完成之后就会发生这种情况。
我该怎么做才能阻止这种行为?
答案 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);
}
现在,重定向仅填充网址中的故障单部分。