使用内置路由是不可能的,但您可以扩展 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变量中。 (在我们的解决方案中,我们有一个更复杂的解决方案 - 我们使用 DI 容器来获取类的实例,而不是简单的变量,该类负责从 DB 加载和缓存数据)