asp.net mvc - 在工作流程中重用页面/控制器

时间:2010-05-03 19:46:57

标签: asp.net asp.net-mvc

我有2个工作流程:

1)用户第一次注册。他们看到3个不同的屏幕,他们的基本用户信息,他们的信用卡和一些额外的个人资料信息。他们以时尚的向导完成这3个步骤,每当他们点击“提交”时,他们离开当前屏幕并继续前进到下一个。

2)用户已注册。他在导航中链接到这3个单独的页面。他可以按任何顺序更新它们。当他点击保存时,他不会离开他所在的页面,它只是在顶部显示“信用卡信息已保存......”或其他任何内容。可能使用ajax或整页刷新。

我想在两个工作流程之间不仅重复使用视图而且还在控制器中重用这3个屏幕的代码,但是没有大量的if ...那么逻辑来确定下一步的位置取决于它是否是a首次注册向导或更新配置文件的各个部分。

有什么想法吗?

以下是我尝试重用的代码类型:

    public ActionResult Index()
    {
        var model = this.GetModel();
        return this.View(Views.Index, model);
    }

    public ActionResult Save()
    {
        var model = this.GetModel();
        this.TryUpdateModel(model);
        this.UserAccountRepository.Save(model.CurrentUser);
        return this.RedirectToAction<EditCreditCardController>(c => c.Index());
    }

    private EditCreditCardModel GetModel()
    {
        var model = new EditCreditCardModel();
        model.CCTypes = ModelHelper.PopulateDropDownWithModel(this.CardTypeRepository, this.CurrentUser.CreditCard.CardType);
        model.States = ModelHelper.PopulateDropDownWithModel(this.StateRepository, this.CurrentUser.BillingAddress.State);
        model.CurrentUser = this.CurrentUser;
        return model;
    }

2 个答案:

答案 0 :(得分:0)

作为一般经验法则,控制器方法应该非常小,类似于:

public ActionResult SomeAction(int foo, string bar)
{
    MyViewModel model = repository.GetData(foo, bar);
    return View("SomeView", model);
}

因此,当您谈论控制器重用时,您不应该真正有任何需要或使用它。如果重用控制器逻辑似乎很难,那么它可能意味着你的控制器太胖了,它们做得太多了。

至于重用视图,您只需要明智地使用部分视图。我会更具体,但如果不了解这些观点中的细节,这很难做到。像部分用户配置文件字段这样的东西很容易放在局部视图中。


在查看您的编辑之后,我能说的最好的是GetModel()方法不应该是您的控制器的一部分,它应该是您的模型的一部分(即某个地方的存储库或服务),所以你不必继续重写那5行代码。

至于剩下的......虽然我没有真正看到你从任何进一步的抽象中获得什么。 Index方法只是两行代码,技术上可以减少到一行,Save方法是三行(第四行是重定向,每个控制器可能不同)。 / p>

我全都赞成抽象和代码重用,但对于2个不同的控制器,尝试做的比你看起来已经拥有的更多(基于更新的代码示例)可能是过度的(除了{{ 1}}件,可以移动)。如果您有5或20个控制器都重复此代码,那么我可能实现GetModel基类或CreditCardController实用程序类。但还没有,在这一点上它只会进一步模糊控制器逻辑。

答案 1 :(得分:0)

本质上,解决方案非常简单,需要创建一个名为“CommonController”(或XController,或者你喜欢的任何控件)的Controller抽象类,并将代码放在那里,而不是实际的控制器。 正常创建控制器时,这是您使用的代码:

public class HomeController : Controller

创建一个新控制器,并改为使用它:

public abstract class CommonController : Controller

注意那里的“abstract”关键字,这是唯一的区别。 现在,在您的实际控制器中,您需要它们继承此CommonController而不是普通的Controller,因此不使用:

public class HomeController : Controller

您需要使用:

public class HomeController : CommonController

现在,在这个类而不是通常的ActionResult方法中,你将设置一个类似的void方法:

public void CommonController() { 
ViewData["MyVariable"] = value; 
}

现在您已经完成了这项工作,所有在CommonController中设置的ViewData变量都可用于从Controller返回的视图。

总结: 设置一个名为“CommonController”的新控制器,如下所示:

public abstract class CommonController : Controller {
    public void CommonController() {
        // PUT ALL OF YOUR COMMON VARIABLES AND STUFF
        // IN HERE!
        ViewData["MyVariable"] = "BOB THE BUILDER!";
        if(isLoggedIn) {
            ViewData["User"] = "BOB";
        }else{
            ViewData["User"[ = "Unknown User";
        }
        // Etc, etc, etc.
    }
}

然后让现有的控制器使用CommonController作为其基本Controller类:

public class HomeController : CommonController {
    public ActionResult Index() {
       return View();
    }
}

在您的视图中,您应该能够写出&lt;%= ViewData [“MyVariable”]%&gt;和“BOB THE BUILDER!”会出现! }