2013-06-28 42 views
1

我想知道是否可以更改Mvc路由以使用基於票據的系統,其中路由是指向值的外部字典的guid字符串。所以我設置像這樣的新路線:我可以停止將路由值添加到查詢字符串的RedirectToAction?

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,填充與控制器/動作值新票:

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的代碼完成後發生了什麼事。

我該怎麼做才能阻止這種行爲?

+0

這個「return RedirectToAction(action,controller,new {ticketid = ticket.Id});」追加到URL!請使用返回視圖! – Fals

回答

0

圍繞mvc4源挖後,我想我找到了解決辦法:

RedirectToRouteResult派生新類,覆蓋ExecuteResult和修改URL生成只退票字符串:

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); 
    } 

現在重定向僅填充url中的票證部分。

+0

:)幹得好!希望我的awnsear幫助你! – Fals

+0

@Fals這對於這個特定的案例並沒有幫助,但是我把它看作是一個普遍的想法,我遇到的問題越多,比如你現在不能寫動作鏈接怎麼做外部導航?我認爲這個想法太深刻了。我將很快開始看你的建議。 – asawyer

+0

你爲什麼不試圖將動作/控制器添加到票證中?所以用戶不會在url處注意到這一點,而且您仍然可以使用操作鏈接! – Fals

2

的RedirectToAction方法,使新的要求,改變了瀏覽器的網址:

這部分改變的網址:

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

1)返回查看不使一個新的請求時,它只是呈現視圖而不更改瀏覽器地址欄中的URL。

2)返回RedirectToAction使瀏覽器地址欄中的新請求和URL用MVC生成的URL更新。

3)返回重定向也使得在瀏覽器的地址欄中顯示的新要求和URL被更新,但你必須指定完整的URL重定向

4)RedirectToAction和重定向之間,最好的做法是使用RedirectToAction用於處理應用程序操作/控制器的任何事情。如果您使用重定向並提供URL,則當您更改路由表時,您需要手動修改這些URL。

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

但是,查看不會,請嘗試調整您的代碼以返回視圖!或者,在最糟糕的情況下,做一些事情來處理來自Response的URL!