Oh, gerçekten bir saatliğine kendimi meşgul etmek için iyi bir soru. Gerekli işlevselliği elde etmek için, MVC kaynağına ve çok az yansımaya bağlanmamız gerekir. Varsayılan Rota isimlerin By
kullanılamaz, bu yüzden RouteData jeton Route Adı kaydetmek için bir Rota toplama uzantısı yazmak gerekir.
public static Route MapRouteWithName(this RouteCollection routes,string name, string url, object defaults=null, object constraints=null)
{
Route route = routes.MapRoute(name, url, defaults, constraints);
route.DataTokens = new RouteValueDictionary();
route.DataTokens.Add("RouteName", name);
return route;
}
- MVC PathHelper biraz Modifiye önceki uzantıyı
routes.MapRouteWithName(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
çağırmak için global.asax Hattın çağrısını değiştirin.
using System;
using System.Collections.Specialized;
using System.Web;
public static class PathHelpers
{
// this method can accept an app-relative path or an absolute path for contentPath
public static string GenerateClientUrl(HttpContextBase httpContext, string contentPath)
{
if (String.IsNullOrEmpty(contentPath))
{
return contentPath;
}
// many of the methods we call internally can't handle query strings properly, so just strip it out for
// the time being
string query;
contentPath = StripQuery(contentPath, out query);
return GenerateClientUrlInternal(httpContext, contentPath) + query;
}
private static string GenerateClientUrlInternal(HttpContextBase httpContext, string contentPath)
{
if (String.IsNullOrEmpty(contentPath))
{
return contentPath;
}
// can't call VirtualPathUtility.IsAppRelative since it throws on some inputs
bool isAppRelative = contentPath[0] == '~';
if (isAppRelative)
{
string absoluteContentPath = VirtualPathUtility.ToAbsolute(contentPath, httpContext.Request.ApplicationPath);
string modifiedAbsoluteContentPath = httpContext.Response.ApplyAppPathModifier(absoluteContentPath);
return GenerateClientUrlInternal(httpContext, modifiedAbsoluteContentPath);
}
string relativeUrlToDestination = MakeRelative(httpContext.Request.Path, contentPath);
string absoluteUrlToDestination = MakeAbsolute(httpContext.Request.RawUrl, relativeUrlToDestination);
return absoluteUrlToDestination;
}
public static string MakeAbsolute(string basePath, string relativePath)
{
// The Combine() method can't handle query strings on the base path, so we trim it off.
string query;
basePath = StripQuery(basePath, out query);
return VirtualPathUtility.Combine(basePath, relativePath);
}
public static string MakeRelative(string fromPath, string toPath)
{
string relativeUrl = VirtualPathUtility.MakeRelative(fromPath, toPath);
if (String.IsNullOrEmpty(relativeUrl) || relativeUrl[0] == '?')
{
// Sometimes VirtualPathUtility.MakeRelative() will return an empty string when it meant to return '.',
// but links to {empty string} are browser dependent. We replace it with an explicit path to force
// consistency across browsers.
relativeUrl = "./" + relativeUrl;
}
return relativeUrl;
}
private static string StripQuery(string path, out string query)
{
int queryIndex = path.IndexOf('?');
if (queryIndex >= 0)
{
query = path.Substring(queryIndex);
return path.Substring(0, queryIndex);
}
else
{
query = null;
return path;
}
}
}
- (projede bu yardımcısı dahil)
Denetleyici'de birkaç Yardımcı yöntem ekle Add
public static string GenerateUrl(string routeName, string actionName, string controllerName, RouteCollection routeCollection, RequestContext requestContext)
{
RouteValueDictionary mergedRouteValues = MergeRouteValues(actionName, controllerName);
VirtualPathData vpd = routeCollection.GetVirtualPathForArea(requestContext, routeName, mergedRouteValues);
if (vpd == null)
{
return null;
}
string modifiedUrl = PathHelpers.GenerateClientUrl(requestContext.HttpContext, vpd.VirtualPath);
return modifiedUrl;
}
public static RouteValueDictionary MergeRouteValues(string actionName, string controllerName)
{
// Create a new dictionary containing implicit and auto-generated values
RouteValueDictionary mergedRouteValues = new RouteValueDictionary();
// Merge explicit parameters when not null
if (actionName != null)
{
mergedRouteValues["action"] = actionName;
}
if (controllerName != null)
{
mergedRouteValues["controller"] = controllerName;
}
return mergedRouteValues;
}
Şimdi denetleyicileri, eylemleri ve rotamayları okumak için bazı yansıma mantıklarını yazabiliriz.
Dictionary<string, List<string>> controllersAndActions = new Dictionary<string, List<string>>();
// Get all the controllers
var controllers = Assembly.GetExecutingAssembly().GetTypes().Where(t => typeof(Controller).IsAssignableFrom(t));
foreach (var controller in controllers)
{
List<string> actions = new List<string>();
//Get all methods without HttpPost and with return type action result
var methods = controller.GetMethods().Where(m => typeof(ActionResult).IsAssignableFrom(m.ReturnType)).Where(a=>!a.GetCustomAttributes(typeof(HttpPostAttribute),true).Any());
methods.ToList().ForEach(a => {
actions.Add(a.Name);
});
var controllerName = controller.Name;
if (controllerName.EndsWith("Controller"))
{
var nameLength = controllerName.Length - "Controller".Length;
controllerName = controllerName.Substring(0, nameLength);
}
controllersAndActions.Add(controllerName, actions);
}
List<string> allowedRoutes = new List<string>();
var routeNames = RouteTable.Routes.Where(o=>o.GetRouteData(this.HttpContext)!=null).Select(r=>r.GetRouteData(this.HttpContext).DataTokens["RouteName"].ToString());
foreach (var cName in controllersAndActions)
{
foreach (var aName in cName.Value)
{
foreach (var item in routeNames)
{
allowedRoutes.Add(GenerateUrl(item, aName, cName.Key, RouteTable.Routes, this.Request.RequestContext));
}
}
}
Puan hatırlamak: rotada sonra bu denetleyici için url ve eylem boş olacak, herhangi bir varsayılan parametreleri tanımladıysanız. Örneğin. Yukarıdaki örnekte "/ Ev/İndeksi" "/"
İndir örnek uygulama olarak gösterilir Link To Download
kök değerlerini anlama geliyor ..? – MethodMan
Bir ağacın/grafiğin var mı? – Adrian
RouteTable gerçekten de bakılacak bir yer ... Şöyle söyleyelim, başka bir yoldan yaptık: rotaları tanıtmak için özellikleri kullanıyoruz ve yansıtma yoluyla rota tablosunu oluşturuyoruz - ve tabii ki bu yansımayı kapriste yapabiliriz. rotaları listelemek –