使用Model-View-Presenter Pattern重定向页面的最正确方法

时间:2010-01-15 19:35:25

标签: asp.net redirect separation-of-concerns mvp

在坚持正确的层分离的同时,在模型 - 视图 - 展示器模式中调用Response.Redirect的最佳方法是什么?

4 个答案:

答案 0 :(得分:6)

我处理此问题的一种方法是让演示者举起视图订阅的事件(如Succeeded或其他内容)。当演示者完成它的处理时,它会引发事件,这将由View处理。在该处理程序中,视图将重定向到下一页。

这样,演示者不需要知道有关页面或URL或任何内容的任何信息。它只知道它什么时候完成了它的任务,并通过提出一个事件让视图知道。如果演示者成功或失败,您可以提出不同的事件,以防您需要重定向到不同的地方。

答案 1 :(得分:4)

我不知道这是否是最正确的方式,从概念上讲。 但是我在上一个MVP应用程序中所做的是创建HttpContext.Current的包装器,我称之为HttpRedirector。 我还创建了一个虚拟重定向器用于测试目的。两者都跟踪最后一个重定向的url,这样我就可以在我的单元测试中检查当我在控制器/演示者上调用方法时重定向实际发生了。使用IOC容器,我可以根据环境(生产/测试)切换IRedirector的实现。

答案 2 :(得分:1)

一旦完成一些基础工作,我们这样做的方式很好。我确信有几种方法可以给猫皮肤。 (无论如何,猫皮都是猫。猫很可爱,可爱!)

首先,这只适用于ASP.Net编译的Web项目,而不适用于网站。

每个页面都应该从一个自定义抽象基类继承,它看起来像这样:

public abstract class PageBase : Page
{
  private static string _baseUrl = "/";

  public static string BaseUrl
  {
    get { return _baseUrl; }
    set { _baseUrl = value; }
  }

  protected static string BuildUrl(string basePath)
  {
    if( !string.IsNullOrEmpty(basePath) && basePath.StartsWith("~/"))
    {
      basePath = basePath.replace("~/", BaseUrl);
    }
    return basePath;
  }

  protected static string LoadView(string path)
  {
    Response.Redirect(path);
  }
}

每个页面还实现了特定于页面的界面。每个特定于页面的界面也都从基本接口继承:

public interface IPageBase()
{
  void LoadView(string path);
}

然后,每个页面定义它自己的BaseUrl版本。您可能想要考虑查询字符串/路径加密/等。

最后,您的任何演示者(应该引用特定于页面的界面)都可以获取所需页面上的静态BuildUrl()以查看,然后使用返回的路径调用LoadView()。

答案 3 :(得分:1)

这取决于您的演示者的通用程度。如果您的演示者完全与UI无关(可以在WinForms和WebForms之间重用),那么您将不得不抽象重定向操作。在WebForms中,重定向操作将由Response.Redirect在视图中实现。在WinForms中,(我放弃了很多WinForms的经验)我的猜测是它将由SomeForm.Show实现。

一个简单的,不受欢迎的选项是在视图的界面中包含一个ShowViewX()方法。您可以为视图可以逻辑重定向到的每个表单创建一个。或者,视图可以实现类似于Show(ConnectedViews)的接口方法,其中ConnectedViews是一个枚举,其中包含可以从特定视图“重定向”到的每个视图的值。这个枚举将存在于主持人层面。

以上方法特定于视图 - 演示者对。您可以将其实现为系统范围内的事物。逻辑与上面的类似,在基本视图和演示者中实现。每个表单都会有一个ShowView __(),或者一个Show(Views)方法,其中Views是所有表单的枚举。

这是封装和DRY-ness之间的折腾。