我目前正在使用MVC4 Web应用程序并遇到了一些我不确定如何处理的路由问题。我希望能够将我的URL映射到控制器操作,但URL没有区别因素来帮助我理解哪些URL需要哪些控制器操作。
网址示例:
有没有办法在不在URL中包含标识符来映射控制器操作的情况下工作。例如:
有了这个,我可以将pc,p,c映射到必要的控制器,但我希望尽可能避免。
有没有办法实现我的概述?
答案 0 :(得分: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中使用类似的东西。函数GetVirtualPathForRouteData
和TryGetRouteValuesForAlias
的实现与我们的解决方案相关联,因此我不会在此发布,但我认为您会了解它是如何工作的。
基本上GetVirtualPathForRouteData
函数接受路由参数字典(例如controller,action,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加载和缓存数据)