我继承了一个建立在 webforms 之上的 ASP.NET 应用程序,该应用程序的所有业务逻辑都嵌入在代码隐藏中。因此,无法对该应用程序进行单元测试。
我想将每个表单的功能分解为 MVC 样式,但我发现 ASP.NET 拒绝我为重构它所做的一切努力。一般来说,我喜欢按如下方式分离我的 MVC 类:
public class LoginModel
{
public string Username, Password;
public bool IsAuthenticated;
}
public interface ILoginView
{
event Action UserLoggedIn;
void SetMode(bool isAuthenticated);
}
public class LoginController
{
ILoginView View;
LoginModel Model;
public LoginController(ILoginView view, LoginModel model)
{
this.View = view;
this.Model = model;
// hook onto view events
}
}
一旦我设置好我的类并进行了很好的单元测试,我就可以ILoginView
在我的用户控件或页面上实现接口:
public class LoginView : UserControl, ILoginView
{
public LoginView() : base()
{
new LoginController(this); // registers view with the controller
}
}
如果这是一个 winform 应用程序,它会很好地工作。但是 ASP.NET 生命周期导致这种风格崩溃。
ASP.NET 在每次页面加载时创建和销毁视图。由于我的控制器由视图持有,模型由控制器持有,每次回发都会导致我的页面丢失其状态。
我可以通过在用户会话中持有我的控制器来解决上述问题,但这会带来很多问题。特别是,将控制器放在会话中会导致内存问题,因为模型和控制器在会话到期之前不会被垃圾收集回收。从一个页面导航到另一个页面会创建几十个控制器,但是当用户离开一个页面时,这些控制器不会自行处理。
由于视图在每次回发时都被销毁/重新创建,因此我必须在每次回发时向控制器重新注册视图。这比听起来更难做到,因为模型的状态需要在每次回发时复制回视图,但同时我们不想覆盖用户在之前的回发中对视图所做的更改。当使用这种 MVC 样式处理动态创建或 AJAXed 控件时,您不知道这会变成什么样的额外噩梦。
我知道我想多了,有一种更简单的方法可以获得我想要的结果,但是如何使用 webforms 正确实现 MVC 样式?