为了我们的web应用程序,我需要根据视图-或者更准确地说是生成视图的控制器和操作(以及用户id,但这不是重点)来保存获取和显示项的顺序。
我想,与其在每个控制器动作中自己提供一个标识符(以便用于某些视图相关的数据库输出排序),不如自动从调用它的控制器和动作方法中创建此标识符,这样更安全、更容易实现。
如何在控制器的操作方法内获取控制器和操作的名称?或者需要反射吗?
为了我们的web应用程序,我需要根据视图-或者更准确地说是生成视图的控制器和操作(以及用户id,但这不是重点)来保存获取和显示项的顺序。
我想,与其在每个控制器动作中自己提供一个标识符(以便用于某些视图相关的数据库输出排序),不如自动从调用它的控制器和动作方法中创建此标识符,这样更安全、更容易实现。
如何在控制器的操作方法内获取控制器和操作的名称?或者需要反射吗?
string actionName = this.ControllerContext.RouteData.Values["action"].ToString();
string controllerName = this.ControllerContext.RouteData.Values["controller"].ToString();
routes.LowercaseUrls = true;
,则您的操作名称和控制器名称将被转换为小写。我想知道是否有解决方法。 - Maksim Vi.以下是一些用于获取信息(包括ID)的扩展方法:
public static class HtmlRequestHelper
{
public static string Id(this HtmlHelper htmlHelper)
{
var routeValues = HttpContext.Current.Request.RequestContext.RouteData.Values;
if (routeValues.ContainsKey("id"))
return (string)routeValues["id"];
else if (HttpContext.Current.Request.QueryString.AllKeys.Contains("id"))
return HttpContext.Current.Request.QueryString["id"];
return string.Empty;
}
public static string Controller(this HtmlHelper htmlHelper)
{
var routeValues = HttpContext.Current.Request.RequestContext.RouteData.Values;
if (routeValues.ContainsKey("controller"))
return (string)routeValues["controller"];
return string.Empty;
}
public static string Action(this HtmlHelper htmlHelper)
{
var routeValues = HttpContext.Current.Request.RequestContext.RouteData.Values;
if (routeValues.ContainsKey("action"))
return (string)routeValues["action"];
return string.Empty;
}
}
使用方法:
@Html.Controller();
@Html.Action();
@Html.Id();
可能会有用。我需要在控制器的构造函数中执行操作,而在MVC生命周期的这个时刻,this
尚未初始化,ControllerContext = null
。为了避免深入MVC生命周期并找到适当的函数名称进行覆盖,我只需在RequestContext.RouteData
中找到该操作。
但是为了这样做,与构造函数中的任何HttpContext
相关的使用一样,您必须指定完整的命名空间,因为this.HttpContext
也还没有初始化。幸运的是,System.Web.HttpContext.Current
是静态的。
// controller constructor
public MyController() {
// grab action from RequestContext
string action = System.Web.HttpContext.Current.Request.RequestContext.RouteData.GetRequiredString("action");
// grab session (another example of using System.Web.HttpContext static reference)
string sessionTest = System.Web.HttpContext.Current.Session["test"] as string
}
注意:这可能不是访问HttpContext中所有属性的最受支持的方式,但对于我的应用程序中的RequestContext和Session,它似乎可以正常工作。
var routeValues = HttpContext.Current.Request.RequestContext.RouteData.Values;
if (routeValues != null)
{
if (routeValues.ContainsKey("action"))
{
var actionName = routeValues["action"].ToString();
}
if (routeValues.ContainsKey("controller"))
{
var controllerName = routeValues["controller"].ToString();
}
}
@this.ViewContext.RouteData.Values["controller"].ToString();
这是我目前的进展:
var actionName = filterContext.ActionDescriptor.ActionName;
var controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
var actionName = RouteData.Values["action"];
var controllerName = RouteData.Values["controller"];
或者
string actionName = RouteData.Values["action"].ToString();
string controllerName = RouteData.Values["controller"].ToString();
上面的代码是使用ASP.NET MVC 5进行测试的。
对我来说(到目前为止),这似乎很好用,如果您正在使用属性路由,则也适用。
public class BaseController : Controller
{
protected string CurrentAction { get; private set; }
protected string CurrentController { get; private set; }
protected override void Initialize(RequestContext requestContext)
{
this.PopulateControllerActionInfo(requestContext);
}
private void PopulateControllerActionInfo(RequestContext requestContext)
{
RouteData routedata = requestContext.RouteData;
object routes;
if (routedata.Values.TryGetValue("MS_DirectRouteMatches", out routes))
{
routedata = (routes as List<RouteData>)?.FirstOrDefault();
}
if (routedata == null)
return;
Func<string, string> getValue = (s) =>
{
object o;
return routedata.Values.TryGetValue(s, out o) ? o.ToString() : String.Empty;
};
this.CurrentAction = getValue("action");
this.CurrentController = getValue("controller");
}
}
将以下内容添加到您的基本控制器中的GetDefaults()方法中
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
GetDefaults();
base.OnActionExecuting(filterContext);
}
private void GetDefaults()
{
var actionName = filterContext.ActionDescriptor.ActionName;
var controllerName = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
}
将你的控制器实现到Basecontroller中
添加一个局部视图_Breadcrumb.cshtml,并在所有必需的页面中添加@Html.Partial("_Breadcrumb")
_Breadcrumb.cshtml
<span>
<a href="../@ViewData["controllerName"]">
@ViewData["controllerName"]
</a> > @ViewData["actionName"]
</span>
GetDefaults()
中你从哪里获取 filterContext
变量? - chriszo111尝试这段代码
将此覆盖方法添加到控制器中
protected override void OnActionExecuting(ActionExecutingContext actionExecutingContext)
{
var actionName = actionExecutingContext.ActionDescriptor.ActionName;
var controllerName = actionExecutingContext.ActionDescriptor.ControllerDescriptor.ControllerName;
base.OnActionExecuting(actionExecutingContext);
}