1

私は現在MVC4Webアプリケーションを使用していますが、処理方法がわからないルーティングの問題が発生しました。URLをコントローラーアクションにマップできるようにしたいのですが、URLには、どのURLがどのコントローラーアクションを必要とするかを理解するのに役立つ識別要素がありません。

URLの例:

  • /[製品カテゴリ]
  • /[商品カテゴリ]/[商品名]
  • /[製品カテゴリ]/[製品サブカテゴリ]/[製品名]
  • /[ランダムなコンテンツ名]

コントローラーアクションをマップするためにURL内に識別子を含めずにこれを処理できる方法はありますか?例えば:

  • / pc/[製品カテゴリ]
  • / p/[製品カテゴリ]/[製品名]
  • / p/[製品カテゴリ]/[製品サブカテゴリ]/[製品名]
  • / c/[ランダムなコンテンツ名]

これにより、pc、p、cを必要なコントローラーにマップできますが、可能であれば避けたいと思います。

私が概説したことを達成する方法はありますか?

4

1 に答える 1

1

組み込みのルートでは不可能ですが、RouteBase クラスを拡張してサポートすることができます。

public class ProductRoute : RouteBase {
    private readonly IRouteHandler _routeHandler;

    public ProductRoute(IRouteHandler handler) {
        _routeHandler = handler;
    }

    public override RouteData GetRouteData(HttpContextBase httpContext) {
        string virtualPath = httpContext.Request.AppRelativeCurrentExecutionFilePath + httpContext.Request.PathInfo;

        IDictionary<string, string> routeValues;
        if (TryGetRouteValuesForAlias(virtualPath, out routeValues)) {
            var data = new RouteData(this, _routeHandler);
            foreach (var routeValue in routeValues) {
                data.Values.Add(routeValue.Key, routeValue.Value);
            }

            return data;
        }
        //No route data for alias found, return null, which means that this route doesn't match the path
        return null;
    }

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) {
        string virtualPath = null;
        if (GetVirtualPathForRouteData(values, out virtualPath);) {
            VirtualPathData result = new VirtualPathData(this, match);

            return result;
        }
        //No virtual path found for the route data
        return null;
    }
}

CMS で同様のものを使用しています。関数の実装は私たちのソリューションGetVirtualPathForRouteDataTryGetRouteValuesForAlias結びついているので、ここには掲載しませんが、どのように機能するかはお分かりいただけると思います。

基本的に、このGetVirtualPathForRouteData関数はルート パラメーター (コントローラー、アクション、ID など) の辞書を取得し、それらの URL を見つけようとします。逆のTryGetRouteValuesForAliasプロセスを実行して、URL を取得し、そのルート パラメーターを見つけようとします。

編集(GetVirtualPathForRouteData および TryGetRouteValuesForAlias の実装例)

//key - url, value - route values
IDictionary<string, IDictionary<string, string>> _urls;

public bool TryGetRouteValuesForAlias(string path, out IDictionary<string, string> routeValues) {
    return _urls.TryGetValue(path, out routeValues);
}

public bool GetVirtualPathForRouteData(RouteValueDictionary routeValues, out string virtualPath) {
    foreach (var url in _urls) {
        if (this.CompareValuesLists(url.Value, routeValues)) {
            virtualPath = url.Key;
            return true;
        }
    }

    return false;
}

private bool CompareValuesLists(IDictionary<string, string> urlValues, IDictionary<string, object> routeValues) {
    if (urlValues.Count != routeValues.Count) {
        return false;
    }

    foreach (var key in urlValues.Keys) {
        if (!routeValues.ContainsKey(key)) {
            return false;
        }

        if (!string.Equals(urlValues[key], Convert.ToString(routeValues[key]), StringComparison.OrdinalIgnoreCase)) {
                return false;
            }
        }

        return true;
    }
}

ルーティングデータは_urls変数に保持されます。(私たちのソリューションでは、もう少し複雑なソリューションがあります。単純な変数の代わりに、DB からのデータのロードとキャッシュを担当するクラスのインスタンスを取得するために DI コンテナーを使用しています)

于 2012-12-16T11:04:50.223 に答える