Action呈现第一个名为Action的视图(当Action调用另一个Action时)

时间:2010-09-08 23:59:41

标签: c# asp.net-mvc

名字很可能令人困惑。我有一个要求,其中URL必须是名称友好的,以表示日期(schedule/todayschedule/tomorrow等)。我想要将DateTime.NowDateTime.Now.AddDays(1)等的路由映射混淆为不同的参数,所以我决定创建映射到同名操作的路由:< / p>

routes.MapRoute(RouteNames.ScheduleToday, "schedule/today", new { controller = "Schedule", action = "Today" });
routes.MapRoute(RouteNames.ScheduleTomorrow, "schedule/tomorrow", new { controller = "Schedule", action = "Tomorrow" });

行动的想法是,我希望能够调用Today()操作,但实际上调用List(DateTime date)操作,例如DateTime.Now作为{date 1}}参数。

这很有效:

public ActionResult Today()
{
    return this.List(DateTime.Now);
}

public ViewResult List(DateTime date)
{
    this.ViewData["Date"] = date;
    return this.View("List");
}

我希望能够拨打this.View()而不是this.View("List")。这可能不是我上面发布的内容吗?似乎所呈现的视图与调用的第一个操作的名称相匹配,因为实现此操作的唯一方法是显式呈现List视图。

3 个答案:

答案 0 :(得分:1)

我不知道如何使无参数View()返回除第一个动作方法名称之外的视图。但是,这种解决问题的方法如果没有将DateTime.Now放在路由映射中 - 如果你定义了这样的路由映射:

routes.MapRoute(RouteNames.ScheduleToday, "schedule/today", new { controller = "Schedule", action = "List", identifier = "today" });
routes.MapRoute(RouteNames.ScheduleTomorrow, "schedule/tomorrow", new { controller = "Schedule", action = "List", identifier = "tomorrow" });

这里我们引入了一个名为“identifier”的新路由令牌,它与路由中的匹配。您可以做的另一件事是定义一个路由,如下所示:

routes.MapRoute(RouteNames.ScheduleToday, "schedule/{identifier}", new { controller = "Schedule", action = "List" });

但是在这种情况下,您需要一个路由约束来将{identifier}令牌限制为仅支持您的有效值。有了这些路线,您只需创建一个自定义ActionFilterAttribute,负责设置日期

这样的事情:

public class DateSelectorAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var identifier = filterContext.RouteData.Values["identifier"] as string;
        switch (identifier)
        {
            case "today":
                filterContext.ActionParameters["date"] = DateTime.Now;
                break;
            case "tomorrow":
                filterContext.ActionParameters["date"] = DateTime.Now.AddDays(1);
                break;
        }
    }
}

现在你的List()方法可能如下所示:

[DateSelector]
public ActionResult List(DateTime date)
{
    this.ViewData.Model = date;
    return this.View();
}

作为旁注,我意识到设置DateTime.Now在路由中无论如何都不会工作,因为只会在应用程序启动时调用,有效地缓存日期值。动作过滤器是一种更好的方法,因为它可以实时调用并为您提供准确的日期。

希望这有帮助。

答案 1 :(得分:0)

您从Today()重定向到另一个控制器操作的方式错误。您应该使用RedirectToAction()重载之一。这样您就不必在List()操作中指定视图。并且您可以将DateTime作为路由值提供给RedirectToAction()

答案 2 :(得分:0)

我仍然找不到为什么被调用的第一个动作与视图匹配而不是最后动作(也许我会深入研究源代码)。暂时我会坚持我所拥有的东西,因为没有理由让事情过于复杂。