从不同的控制器重定向到相同的ActionResult

时间:2010-02-17 12:37:29

标签: asp.net-mvc refactoring asp.net-mvc-routing

我有一个User实体,在各种视图中,我想基本创建一个用户主页的链接。此功能应该在不同的控制器中可用,因此我可以轻松地重定向到用户的主页。我网站中的每个用户都有一个角色;例如读者,作家,编辑,经理和管理员。理想情况下,我想尝试实现这样的目标:

在控制器中,例如

public ActionResult SomeThingHere() {
    return View(User.GetHomePage());
//OR 
    return RedirectToROute(User.GetHomePage());
}

在View中,我也想使用相同的功能,例如:

<%= Html.ActionLink("Link to home", user.GetHomePage() %>

是否有可能在MVC中实现这样的设计?如果是这样,我应该怎么做呢?

我目前使用这样的方法,但目前仅在一个控制器中。现在我需要在其他地方使用相同的代码,我想弄清楚如何折射这个并避免重复自己?

....
private ActionResult GetHomePage(User user){
    if (user.IsInRole(Role.Admin))
        return RedirectToAction("Index", "Home", new { area = "Admin" });

    if (user.IsInRole(Role.Editor))
        // Managers also go to editor home page
        return RedirectToAction("Index", "Home", new {area = "Editor"});

    if (user.IsInRole(Role.Reader))
        // Writer and reader share the same home page
        return RedirectToAction("Index", "Home", new { area = "Reader" });

    return RedirectToAction("Index", "Home");
}
...

3 个答案:

答案 0 :(得分:1)

这样的事情怎么样:

private string GetArea(User u)
{
   string area = string.empty;
   if (User.IsInRole(Admin)) area = "admin";
   else if (...)


   return area;
}

答案 1 :(得分:0)

我建议对HtmlHelper类进行自定义扩展。我的头脑(可能有语法错误),像这样

public static class RoleLinksExtension
{
    public static string RoleBasedHomePageLink(this HtmlHelper helper, string text)
    {
        if (user.IsInRole(Role.Admin))
             return helper.ActionLink(text, "Index", "Home", new { area = "Admin" });

        // other role options here

        return string.Empty; // or throw exception
    }
}

然后就是

<%= Html.RoleBasedHomePageLink("Link to home") %>

在你的标记中。

如果可以避免的话,你真的不想拥有一个只是重定向到其他地方的链接。

编辑:不知道为什么我之前没有想到这一点,但是如果你需要重定向(也许如果你在去家之前需要一些功能页面),你可以扩展IPrinciple

public static class AreaHomePageExtensions
{
    public static string GetArea(this IPrinciple user)
    {
        if (user.IsInRole(Role.Admin))
            return "Admin";
        // Other options here
    }
}

然后你可以做

return RedirectToAction("Index", "Home", new { area = User.GetArea() });

随时随地。

答案 2 :(得分:0)

好吧,我终于想出了一个似乎有用的设计。我写了一个控制器扩展, 使用GetHomePage方法。此扩展程序也可用于您的视图。我是这样做的:

public static class UserHelperExtension    {
    public static string GetHomePage(this ControllerBase controller, User user) {
        return = "http://" + controller.ControllerContext
                            .HttpContext.Request
                            .ServerVariables["HTTP_HOST"] + "/"
                           + GetHomePage(user);
    }

    //need this for views
    public static string GetHomePage(string httphost, User user) {
        return  = "http://" + httphost + "/" + GetHomePage(user});
    }

    private static string GetHomePage(User user) {
        if (user.IsInRole(Role.Admin))
            return "/Admin/Home/Index";
        if (user.IsInRole(Role.Editor))
            return "/Editor/Home/Index";
        if (user.IsInRole(Role.Reader))
            return "/Reader/Home/Index";
        return "/Home/Index";
    }
}

控制器中的操作方法如下所示:

    using Extensions;
...
public ActionResult SomethingHere() {
    return Redirect(this.GetHomePage(user));
}
...

在视图中我有这个:

...
<%@ Import Namespace="Extensions"%>
<%=UserHelperExtension.GetHomePage(Request.ServerVariables["HTTP_HOST"], user)%>
...

优点是我可以在各种控制器中轻松使用这个“GetHomePage”方法,  或者查看我的应用程序,并且逻辑在一个地方。缺点是  我宁愿让它更安全。例如,在我的orignal测试中,我可以访问RouteValues集合:

public void User_should_redirect_to_role_home(Role role,
    string area, string controller, string action) {
...
var result = (RedirectToRouteResult)userController.SomeThingHere();
    Assert.That(result.RouteValues["area"], 
        Is.EqualTo(area).IgnoreCase);
    Assert.That(result.RouteValues["controller"], 
        Is.EqualTo(controller).IgnoreCase);
    Assert.That(result.RouteValues["action"], 
        Is.EqualTo(action).IgnoreCase);
...

}

但是现在我正在使用一个字符串,因此它不是类型安全的,并检查RedirectResult.Url。

...
var result = (RedirectResult) userController.SomethingHere();
Assert.That(result.Url.EndsWith("/" + area + "/" + controller + "/" + action), 
    Is.True);
...