如何在 ASP.NET MVC 视图中返回当前操作?

Posted

技术标签:

【中文标题】如何在 ASP.NET MVC 视图中返回当前操作?【英文标题】:How can I return the current action in an ASP.NET MVC view? 【发布时间】:2008-12-12 11:33:34 【问题描述】:

我想在我的母版页中设置一个 CSS 类,这取决于当前的控制器和操作。我可以通过ViewContext.Controller.GetType().Name 访问当前控制器,但是如何获取当前操作(例如IndexShow 等)?

【问题讨论】:

【参考方案1】:

在RC中你也可以像这样提取动作方法名这样的路由数据

ViewContext.Controller.ValueProvider["action"].RawValue
ViewContext.Controller.ValueProvider["controller"].RawValue
ViewContext.Controller.ValueProvider["id"].RawValue

MVC 3 更新

ViewContext.Controller.ValueProvider.GetValue("action").RawValue
ViewContext.Controller.ValueProvider.GetValue("controller").RawValue
ViewContext.Controller.ValueProvider.GetValue("id").RawValue

MVC 4 更新

ViewContext.Controller.RouteData.Values["action"]
ViewContext.Controller.RouteData.Values["controller"]
ViewContext.Controller.RouteData.Values["id"]

MVC 4.5 更新

ViewContext.RouteData.Values["action"]
ViewContext.RouteData.Values["controller"]
ViewContext.RouteData.Values["id"]

【讨论】:

我知道这早于 V2,但现在是 ViewContext.Controller.ValueProvider.GetValue("action").RawValue + 变体 此语法适用于 V4:(string)ViewContext.RouteData.Values["action"]; 这个解决方案对我不起作用(MVC4 + .NET Framework 4.5.1)。对我来说,它适用于 Viacheslav Smityukh 的答案:ViewContext.RouteData.Values["action"], ViewContext.RouteData.Values["controller"], ViewContext.RouteData.Values["id"], @kiprainey 在 V3.5 中:msdn.microsoft.com/en-us/library/… 试试:(string)HttpContext.Request.RequestContext.RouteData.Values["action"];【参考方案2】:

使用ViewContext 并查看RouteData 集合以提取控制器和操作元素。但我认为设置一些指示应用程序上下文的数据变量(例如,“editmode”或“error”)而不是控制器/动作会减少视图和控制器之间的耦合。

【讨论】:

您可以在控制器中获取数据并通过DTO将其传递给查看。***.com/a/31749391/4293929 这不能是公认的答案,请查看投票最多的答案。 @HakamFostok 我仍然认为向模型添加语义信息的建议在所有情况下都是比在您的视图中依赖路由数据(控制器、操作)更好的方法,即使其他答案提供了更多有关如何获取该数据的详细信息。【参考方案3】:

要获取视图上的当前 ID:

ViewContext.RouteData.Values["id"].ToString()

获取当前控制器:

ViewContext.RouteData.Values["controller"].ToString() 

【讨论】:

ViewContext.RouteData.Values[].ToString() 如果 RouteData 中不存在该值,则会引发异常 @ShaneLarson 只需比较 null 或先检查 ViewContext.RouteData.Values.ContainsKey(<key>)【参考方案4】:

我知道这是一个较老的问题,但我看到了它,并且我认为您可能对替代版本感兴趣,而不是让您的视图处理检索完成工作所需的数据。

在我看来,更简单的方法是覆盖 OnActionExecuting 方法。传递给您的是包含 ActionDescriptor 成员的 ActionExecutingContext,您可以使用该成员获取您要查找的信息,即 ActionName,您还可以访问 ControllerDescriptor,它包含 ControllerName。

protected override void OnActionExecuting(ActionExecutingContext filterContext)

    ActionDescriptor actionDescriptor = filterContext.ActionDescriptor;
    string actionName = actionDescriptor.ActionName;
    string controllerName = actionDescriptor.ControllerDescriptor.ControllerName;
    // Now that you have the values, set them somewhere and pass them down with your ViewModel
    // This will keep your view cleaner and the controller will take care of everything that the view needs to do it's job.

希望这会有所帮助。如果有的话,至少它会为您提出问题的其他人提供替代方案。

【讨论】:

不错的推荐;帮助我智能地实现控制器/动作感应。谢谢! 获取动作描述符是我所需要的,我真的找不到任何其他解决方案,所以我只是在这里做,然后将我想要的东西推到 viewbag 中。【参考方案5】:

我看到了不同的答案并想出了一个类助手:

using System;
using System.Web.Mvc;

namespace MyMvcApp.Helpers 
    public class LocationHelper 
        public static bool IsCurrentControllerAndAction(string controllerName, string actionName, ViewContext viewContext) 
            bool result = false;
            string normalizedControllerName = controllerName.EndsWith("Controller") ? controllerName : String.Format("0Controller", controllerName);

            if(viewContext == null) return false;
            if(String.IsNullOrEmpty(actionName)) return false;

            if (viewContext.Controller.GetType().Name.Equals(normalizedControllerName, StringComparison.InvariantCultureIgnoreCase) &&
                viewContext.Controller.ValueProvider.GetValue("action").AttemptedValue.Equals(actionName, StringComparison.InvariantCultureIgnoreCase)) 
                result = true;
            

            return result;
        
    

所以在视图(或主/布局)中,您可以像这样使用它(Razor 语法):

            <div id="menucontainer">

                <ul id="menu">
                    <li @if(MyMvcApp.Helpers.LocationHelper.IsCurrentControllerAndAction("home", "index", ViewContext)) 
                            @:class="selected"
                        >@html.ActionLink("Home", "Index", "Home")</li>
                    <li @if(MyMvcApp.Helpers.LocationHelper.IsCurrentControllerAndAction("account","logon", ViewContext)) 
                            @:class="selected"
                        >@Html.ActionLink("Logon", "Logon", "Account")</li>
                    <li @if(MyMvcApp.Helpers.LocationHelper.IsCurrentControllerAndAction("home","about", ViewContext)) 
                            @:class="selected"
                        >@Html.ActionLink("About", "About", "Home")</li>
                </ul>

            </div>

希望对你有帮助。

【讨论】:

【参考方案6】:

您可以从 ViewContext 的 RouteData 中获取这些数据

ViewContext.RouteData.Values["controller"]
ViewContext.RouteData.Values["action"]

【讨论】:

【参考方案7】:

在 MVC 中,您应该为 View 提供所有数据,而不是让 View 收集自己的数据,因此您可以在控制器操作中设置 CSS 类。

ViewData["CssClass"] = "bold";

并从 View 中的 ViewData 中选择此值

【讨论】:

这也是我的首选方法,以防止视图依赖于控制器结构,但也可以这样做。 不确定我是否将其命名为“CssClass”,因为这似乎表明显示逻辑正在悄悄进入您的控制器。 同意,我通常会做一些类似“上下文”的事情,所以它不依赖于表示层,如果你重命名视图也不会中断。【参考方案8】:

我投票给这 2 个:

string currentActionName = ViewContext.RouteData.GetRequiredString("action");

string currentViewName = ((WebFormView)ViewContext.View).ViewPath;

您可以检索当前视图的物理名称和触发它的操作。它可以在部分 *.acmx 页面中用于确定主机容器。

【讨论】:

【参考方案9】:

我正在使用 ASP.NET MVC 4,这对我有用:

ControllerContext.Controller.ValueProvider.GetValue("controller").RawValue
ControllerContext.Controller.ValueProvider.GetValue("action").RawValue

【讨论】:

【参考方案10】:

扩展 Dale Ragan's answer,他的重用示例,创建一个派生自 Controller 的 ApplicationController 类,然后让所有其他控制器派生自该 ApplicationController 类而不是 Controller。

例子:

public class MyCustomApplicationController : Controller 

public class HomeController : MyCustomApplicationController 

在您的新 ApplicationController 上使用此签名创建一个名为 ExecutingAction 的属性:

protected ActionDescriptor ExecutingAction  get; set; 

然后在 OnActionExecuting 方法中(来自 Dale Ragan 的回答),只需将 ActionDescriptor 分配给此属性,您就可以在任何控制器中随时访问它。

string currentActionName = this.ExecutingAction.ActionName;

【讨论】:

【参考方案11】:

在你的控制器中覆盖这个函数

protected override void HandleUnknownAction(string actionName) 
  TempData["actionName"] = actionName;
   View("urViewName").ExecuteResult(this.ControllerContext);

【讨论】:

以上是关于如何在 ASP.NET MVC 视图中返回当前操作?的主要内容,如果未能解决你的问题,请参考以下文章

在 ASP.NET MVC 站点中返回视图时操作页面滚动

Asp.Net MVC:如何获取当前控制器/视图的虚拟 url?

Asp.Net MVC:如何确定您当前是不是在特定视图上

如何在 ASP.NET MVC 中执行辅助操作(即计算字段)?

从 ASP.NET MVC 操作返回部分视图和 JSON

ASP.NET MVC 中返回视图的 URL