Обновление
Оказывается, это возможно.Ниже приведен пример, его следует изменить, чтобы добавить остальные маршруты, поддерживаемые сайтом.
- Использование настраиваемого атрибута для определения действий, которые следует использовать для создания динамического маршрута
[AttributeUsage(AttributeTargets.Method)]
public class DynamicUrlAttribute : Attribute
{
}
- Украсьте свои действия с помощью пользовательского атрибута
public class SampleController : Controller
{
[DynamicUrl]
public ActionResult Index(int param2)
{
return View(param2);
}
[DynamicUrl]
public ActionResult MultipleParams(int param1, int param2)
{
return View(new { param1, param2 });
}
}
- Создание маршрутов с помощьюof отражения
public static class Extensions
{
/// <summary>
/// Detect all the actions whose route should be generated dynamically
/// </summary>
/// <returns>List of actions</returns>
private static IEnumerable<MethodInfo> GetTypesWithHelpAttribute()
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (Type type in assembly.GetTypes())
{
foreach (var method in type.GetMethods())
{
if (method.GetCustomAttributes(typeof(DynamicUrlAttribute),
true).Length > 0)
{
yield return method;
}
}
}
}
}
/// <summary>
/// Get the list of routes to add to the Route Table
/// </summary>
/// <returns>List of routes</returns>
public static List<Route> GetRoutes()
{
List<Route> routes = new List<Route>();
foreach (var action in GetTypesWithHelpAttribute())
{
string controllerName = action.DeclaringType.Name.Replace("Controller","");
string actionName = action.Name;
List<string> parameters = new List<string>();
int index = 0;
foreach (var parameterInfo in action.GetParameters())
{
parameters.Add(GetParamName(action, index++));
}
string parameterSection = action.GetParameters().Length > 0 ?
parameters.Aggregate("", (a, b) => $"{a}/{{{b}}}")
: "";
string finalRoute = $"dynamic/{controllerName}/{actionName}{parameterSection}";
routes.Add(new Route(
url: finalRoute,
defaults: new RouteValueDictionary(
new {
controller = controllerName,
action = actionName }),
routeHandler: new MvcRouteHandler()
));
}
return routes;
}
/// <summary>
/// Return the name of the parameter by using reflection
/// </summary>
/// <param name="method">Method information</param>
/// <param name="index">Parameter index</param>
/// <returns>Parameter name</returns>
public static string GetParamName(System.Reflection.MethodInfo method, int index)
{
string retVal = string.Empty;
if (method != null && method.GetParameters().Length > index)
retVal = method.GetParameters()[index].Name;
return retVal;
}
}
- Добавить обнаруженные маршруты в коллекцию маршрутов
public static void RegisterRoutes(RouteCollection routes)
{
foreach (var route in Extensions.GetRoutes())
{
routes.Add(route);
}
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
Для этого кода выбудет иметь следующие два действительных URL-маршрута
- / dynamic / Sample / Index / 2
- / dynamic / Sample / MultipleParams / 1/2
Оригинал (недействительно)
Представьте себе обратное.Допустим, у нас есть представление с этим содержимым
@Url.Action("Action","Controller",
new {
assetCode = "code",
mode = "mode",
assetParam = "assetParam",
someOtherProperty = "someOtherProperty"
})
Теперь, какой URL вы хотите создать?
- / Контроллер / Действие / Код
- / Контроллер / Действие / Код / Режим
- / Контроллер / Действие / Код / Режим / assetParam
- / Контроллер / Действие / Код / Mode / assetParam / someOtherProperty (еще хуже, потому что одиндаже не существует)
- / Controller / Action / someOtherProperty / code / assetParam / mode (что еще хуже, это может быть возможный URL, так как нет никакой информации о порядке, в котором URL долженбыть сгенерированным)
Когда вы определяете 3 маршрута, для инфраструктуры ясно, какой URL должен быть создан.Если бы это было как-то динамично, для фреймворка будет невозможно правильно сгенерировать действительный соответствующий URL.То есть, если вы не начнете заполнять свои контроллеры и действия настраиваемыми атрибутами, и перед тем, как начать это делать, имеет смысл фактически использовать RouteAttribute и / или определять фактические маршруты в таблице маршрутов.