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


291

我想在母版页中设置CSS类,具体取决于当前的控制器和操作。我可以通过电流控制器ViewContext.Controller.GetType().Name,但我如何获得当前的动作(例如IndexShow等)?

Answers:


83

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


您可以在控制器中获取数据并将其传递给DTO进行查看。stackoverflow.com/a/31749391/4293929
MstfAsan 2015年

5
这一定不是公认的答案,请参阅投票最多的答案。
HakanFıstık'16

1
@HakamFostok我仍然认为,在所有情况下,向语义模型添加语义信息的建议都比依赖于视图中的路由数据(控制器,操作)更好,即使其他答案提供了有关如何获取该数据的更多详细信息。
tvanfosson '16

467

在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"]

20
我知道这是V2之前的版本,但现在已经是ViewContext.Controller.ValueProvider.GetValue("action").RawValue变体了
Chris S

7
此语法在V4中有效:(string)ViewContext.RouteData.Values [“ action”];
kiprainey

2
此解决方案不适用于我(MVC4 + .NET Framework 4.5.1)。对我来说,它可以解决Viacheslav Smityukh的答案:ViewContext.RouteData.Values [“ action”],ViewContext.RouteData.Values [“ controller”],ViewContext.RouteData.Values [“ id”],
Tomas Kubes


2
试试:(string)HttpContext.Request.RequestContext.RouteData.Values [“ action”];
Martin Dawson

60

要在视图上获取当前ID:

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

获取当前控制器:

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

1
如果RouteData中不存在该值,则ViewContext.RouteData.Values [<key>]。ToString()会引发异常
Grizzly Peak Software

@ShaneLarson只需与null比较或先检查即可ViewContext.RouteData.Values.ContainsKey(<key>)
冥王星

40

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

我认为,更简单的方法是重写OnActionExecuting方法。传递给您的ActionExecutingContext包含ActionDescriptor成员,您可以使用该成员获取您要查找的信息,即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.
}

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


不错的推荐;帮助我智能地实现了控制器/动作感应。谢谢!
09年

我需要获得动作分解器,我找不到其他解决方案,因此我只在这里进行操作,然后将我想要的内容推入视图包。
克里斯·马里西奇

17

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

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("{0}Controller", 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;
        }
    }
}

因此,在View(或master / layout)中,您可以像这样使用它(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>

希望能帮助到你。



9

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

ViewData["CssClass"] = "bold";

并从View的ViewData中选择此值


同样,这也是我首选的方法,可以根据控制器的结构来阻止视图,但是也可以采用其他方法。
tvanfosson

1
我不确定我是否将其命名为“ CssClass”,因为这似乎表明显示逻辑正在潜入您的控制器。
tvanfosson

同意,我通常会执行“上下文”之类的操作,因此它与表示层无关,并且在您重命名视图时也不会中断。
RedFilter

6

我对此表示投票2:

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

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

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


2

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

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

0

扩展Dale Ragan的答案(他的重用示例),创建一个从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;

0

在控制器中覆盖此功能

protected override void HandleUnknownAction(string actionName) 
{  TempData["actionName"] = actionName;
   View("urViewName").ExecuteResult(this.ControllerContext);
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.