I've inherited an ASP.NET application built on top of webforms, and the application suffers from having all of its business logic embedded in the codebehind. As a result, this application can't be unit tested.
I want to break out the functionality of every form into an MVC style, but I've found that ASP.NET resists every effort on my part to refactor it. In general, I like to seperate my MVC classes as follows:
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
}
}
Once I've got my classes set up and nicely unit tested, I can implement the ILoginView
interface on my usercontrol or page:
public class LoginView : UserControl, ILoginView
{
public LoginView() : base()
{
new LoginController(this); // registers view with the controller
}
}
If this were a winform application, it would work beautifullly. But the ASP.NET lifecycle causes this style to break down.
ASP.NET creates and destroys the view on every page load. Since my Controller is held by the View, the Model is held by the Controller, every postback causes my page to lose its state.
I can remedy the problem above by holding my Controller in the users session, but that introduces a world of problems. In particular, putting Controllers in the session causes memory issues because Models and Controllersaren't reclaimed by garbage collection until the session expires. Navigating from page to page creates dozens of controllers, but the controllers don't dispose of themselves when the user navigates away from a page.
Since a view is destroyed/recreated on every postback, then I have to re-register the view with the controller on every postback. This is harder to do than it sounds, because the state of the Model needs to be copied back to the View on every postback, but simultaneously we don't want to overwrite a users changes to the View which were made in the previous postback. You have no idea what kind of additional nightmare this turns into when dealing with dynamically created or AJAXed controls using this MVC style.
I know I'm overthinking this and there is an easier way to get the results I want, but how do I implement an MVC style properly using webforms?