【发布时间】:2019-02-28 00:25:15
【问题描述】:
我正在构建一个带有 angularjs 前端和 ASP.NET 后端的应用程序。为了让我的 Angular 服务发出请求,我需要在给定 ASP.NET 控制器和操作列表的情况下构造一个 url 模板列表,然后我可以将其发送给客户端。
我正在寻找的结果类似于:
[RoutePrefix("my-controller")]
public class MyController : ControllerBase
{
[Route("my-action/{arg1}/{arg2}")]
public ActionResult MyAction(int arg1, string arg2) {
// ...
}
}
// Elsewhere in my code
GetRouteTemplate("MyController", "MyAction") // => "my-controller/my-action/{arg1}/{arg2}"
我不希望将这些硬编码到前端,因为对路由的任何更改都会破坏角度代码,所以我正在寻找一种生成它们的方法。
我的第一次尝试是使用反射来获取所有的动作方法,然后调用 Url.Action 来获取 url。我把它放在我的基本控制器类中:
protected Dictionary<String, String> GetUrlTemplates()
{
var controllerName = this
.GetType()
.Name;
var actionNames = this
.GetType()
.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)
.Where(m => !m.IsDefined(typeof(NonActionAttribute), false))
.Select(m => m.Name)
.Distinct()
.ToList();
return actionNames
.ToDictionary(
actionName => actionName,
actionName => Url.Action(actionName, controllerName));
}
这对于不需要参数的任何操作都可以,但否则无法返回正确的路线。
我的下一个尝试是尝试将模板直接拉出 RouteTable:
protected Dictionary<String, String> GetUrlTemplates()
{
var controllerName = this
.GetType()
.Name;
var actions = this
.GetType()
.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)
.Where(m => !m.IsDefined(typeof(NonActionAttribute), false))
.Select(m => m.Name)
.Distinct()
.ToList();
return RouteTable.Routes
.OfType<LinkGenerationRoute>()
.Select(lgr => new {
url = lgr.Url,
routeAction = lgr.DataTokens["MS_DirectRouteActions"][0]
})
.Where(o => o.routeAction.ControllerDescriptor.ControllerName == controllerName
&& actions.Contains(o.routeAction.ActionName))
.ToDictionary(
o => o.routeAction.ActionName,
o => o.url);
}
这不起作用,因为 LinkGenerationRoute 是一个内部类,所以除非有另一种方法可以访问路由表中的这些值,否则这看起来也像死路一条。
这两种尝试都有点难看,而且似乎是错误的方法,但我看不出有任何其他方法可以解决。当然,为前端生成 url 模板是一项很常见的任务 - 在 ASP.NET 中获取 url 模板是否有“正确”的方法?我从根本上是不是以错误的方式处理这个问题?谢谢。
【问题讨论】: