2012-08-14 101 views
2

當向我的路由參數添加自定義路由約束時,我發現它打破了我用來構建鏈接的Url.Action方法。如果路由約束只是一個正則表達式,則Url.Action方法將繼續識別該參數,但如果它是我定義的自定義約束,則Url.Action方法會將我的參數作爲請求參數提供。Url.Action當建立鏈接時,MVC3無法識別路由參數

這裏是我的路由定義:

routes.MapRoute(
      "Event", 
      "Events/{strDate}", 
      new { controller = "Events", action = "Index", strDate = DateTime.Today.ToString("yyyy-MM-dd") }, 
      new { strDate = new IsValidDateConstraint() }, 
      new[] { "MyProject.Controllers" } 
     ); 

routes.MapRoute(
      "Default", 
      "{controller}/{action}/{id}", 
      new { controller = "Home", action = "Index", id = UrlParameter.Optional }, 
      new[] { "MyProject.Controllers" } 
     ); 

的IsValidDateConstraint類從IRouteConstraint繼承,如果strDate參數正確地解析爲DateTime對象返回true或false:

public class IsValidDateConstraint : IRouteConstraint 
{ 
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) 
    { 
     if (routeDirection == RouteDirection.IncomingRequest) 
     { 
      DateTime dt = new DateTime(); 

      if (DateTime.TryParse(values["strDate"].ToString(), out dt)) 
       return true; 
     } 

     return false; 
    } 
} 

使用URL。建立URL的動作方法:

@Url.Action("Index", "Events", new { strDate = ViewBag.CurrentDate.AddDays(1).ToString("yyyy-MM-dd") }) 

resulti ng鏈接是:/ Events?strDate = 2012-08-15

如果我輸入/ Events/2012-08-15,所有的路徑都正確,只是Url.Action方法不能識別strDate是參數僅在應用我的自定義路由約束時在我的路由中定義。如果我註釋掉自定義路由約束,則Url.Action方法會正確映射URL。

當我定義了自定義路由約束時,爲什麼Url.Action不能識別我的路由參數?

回答

4

您還沒有表現出你的IsValidDateConstraint的樣子,但要確保你正在做一個文化不變解析爲yyyy-MM-dd格式:

還要確保這個路由的默認路由前放置:

public static void RegisterRoutes(RouteCollection routes) 
{ 
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

    routes.MapRoute(
     "Event", 
     "Events/{strDate}", 
     new { controller = "Events", action = "Index", strDate = DateTime.Today.ToString("yyyy-MM-dd") }, 
     new { strDate = new IsValidDateConstraint() }, 
     new[] { "MyProject.Controllers" } 
    ); 

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

DateTime.Parse(ViewBag.CurrentDate.ToString())看起來是一個WTFkish代碼的小部分。如果ViewBag.CurrentDate已經是一個DateTime,你可以直接寫:

@Url.Action(
    "Index", 
    "Events", 
    new { 
     strDate = ViewBag.CurrentDate.AddDays(1).ToString("yyyy-MM-dd") 
    } 
) 

顯然,一個更好的解決方案是使用視圖模型:

@Url.Action(
    "Index", 
    "Events", 
    new { 
     strDate = Model.CurrentDate.AddDays(1).ToString("yyyy-MM-dd") 
    } 
) 

UPDATE:

既然已經出你的代碼問題來自於你放在約束條件下的if條件:

if (routeDirection == RouteDirection.IncomingRequest) 

當使用Url.Action助手時,此條件永遠不會滿足。僅在解析傳入的網址時。所以如果你想讓這個約束與url助手一起工作,你將不得不刪除它。

+0

我已更新我的帖子以包含所有我使用的代碼。請記住,這個問題發生在每個我設置的路由約束上,而不僅僅是檢查一個有效的DateTime字符串。至於ViewBag你是對的,不知道爲什麼我在那裏做了雙解析,但因爲這是我需要的唯一變量,所以我發現不容易創建ViewModel。這些信息非常豐富和準確,但問題仍然存在。任何其他想法? – 2012-08-14 17:29:51

+0

在你的約束中,你正在使用'if(routeDirection == RouteDirection.IncomingRequest)'。這就是爲什麼你的代碼不起作用。當由Url.Action助手評估時,它總是返回false,因爲這不是傳入的請求。看看我在答案中顯示的代碼。我的約束中沒有這樣的if條件。我已經更新了我的答案,在最後包含了這些信息。 – 2012-08-14 17:34:46

+0

具有完美的感覺,我很感激幫助。謝謝! – 2012-08-14 17:53:43