2

ルートパラメータにカスタムルーティング制約を追加すると、リンクの構築に使用するUrl.Actionメソッドが壊れていることがわかりました。ルート制約が単なる正規表現である場合、Url.Actionメソッドは引き続きパラメーターを認識しますが、それが私が定義するカスタム制約である場合、Url.Actionメソッドはパラメーターを要求パラメーターとして提供します。

これが私のルート定義です:

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.Actionメソッドを使用してURLを作成します。

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

結果のリンクは次のとおりです:/ Events?strDate = 2012-08-15

/ Events / 2012-08-15と入力すると、すべてが正しくルーティングされます。カスタムルーティング制約を適用した場合にのみ、Url.ActionメソッドがstrDateがルートで定義されたパラメーターであることを認識しないだけです。カスタムルーティング制約をコメントアウトすると、Url.ActionメソッドはURLを正しくマップします。

カスタムルート制約を定義しているのに、Url.Actionがルートパラメーターを認識しない理由について何か考えはありますか?

4

1 に答える 1

4

あなたはあなたがどのようにIsValidDateConstraint見えるかを示していませんが、あなたがyyyy-MM-ddフォーマットのために文化不変の構文解析をしていることを確認してください:

public class IsValidDateConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        DateTime date;
        return DateTime.TryParseExact(
            values[parameterName] as string, 
            "yyyy-MM-dd", 
            CultureInfo.InvariantCulture, 
            DateTimeStyles.None, 
            out date
        );
    }
}

また、このルートがデフォルトルートの前に配置されていることを確認してください。

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コードのほんの少しに見えます。がすでにDateTimeである場合ViewBag.CurrentDateは、次のように直接記述できます。

@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") 
    }
)

アップデート:

コードを示したので、問題は制約に設定したif条件に起因します。

if (routeDirection == RouteDirection.IncomingRequest)

Url.Actionヘルパーを使用する場合、この条件が満たされることはありません。着信URLを解決する場合のみ。したがって、この制約をURLヘルパーで機能させる場合は、これを削除する必要があります。

于 2012-08-14T16:21:04.997 に答える