組み込みのルートでは不可能ですが、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 で同様のものを使用しています。関数の実装は私たちのソリューションGetVirtualPathForRouteData
とTryGetRouteValuesForAlias
結びついているので、ここには掲載しませんが、どのように機能するかはお分かりいただけると思います。
基本的に、この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 コンテナーを使用しています)