【发布时间】:2010-01-15 19:35:25
【问题描述】:
在模型-视图-演示者模式中调用Response.Redirect 的最佳方式是什么?同时坚持正确的层分离?
【问题讨论】:
标签: asp.net redirect separation-of-concerns mvp
在模型-视图-演示者模式中调用Response.Redirect 的最佳方式是什么?同时坚持正确的层分离?
【问题讨论】:
标签: asp.net redirect separation-of-concerns mvp
我处理此问题的一种方法是让演示者引发视图将订阅的事件(如Succeeded 或其他东西)。当演示者完成它的处理时,它会引发事件,该事件将由视图处理。在该处理程序中,视图将重定向到下一页。
这样,演示者不需要了解任何有关页面或 URL 或任何内容的信息。它只知道它何时完成了任务并通过引发事件让视图知道。如果演示者成功或失败,您可以引发不同的事件,以防您需要重定向到不同的地方。
【讨论】:
从概念上讲,我不知道这是否是最正确的方法。
但是我在上一个 MVP 应用程序中所做的是围绕 HttpContext.Current 创建一个包装器,我称之为 HttpRedirector。
我还为测试目的创建了一个虚拟重定向器。两者都跟踪最后一个重定向的 url,以便我可以在单元测试中检查当我在控制器/演示器上调用方法时重定向实际上发生了。使用 IOC 容器,我可以根据环境(生产/测试)切换 IRedirector 的实现。
【讨论】:
HttpContext我也很喜欢
一旦奠定了基础,我们的工作方式就会很好。我敢肯定有几种方法可以给猫剥皮。 (反正谁给猫剥皮。猫很可爱!)
首先,这仅适用于 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()。
【讨论】:
这取决于您的演示者的通用性。如果您的演示者完全与 UI 无关(可以在 WinForms 和 WebForms 之间重用),那么您将不得不抽象重定向操作。在 WebForms 中,重定向操作将通过 Response.Redirect 在视图中实现。在 WinForms 中,(我否认有很多使用 WinForms 的经验)我的猜测是它将由 SomeForm.Show 实现。
一个简单的、令人难以置信的选项是在视图的界面中包含一个 ShowViewX() 方法。您可以为视图可以逻辑重定向到的每个表单设置一个。或者,视图可以实现类似 Show(ConnectedViews) 的接口方法,其中 ConnectedViews 是一个枚举,其中包含每个视图的值,这些视图可以从特定视图“重定向”到。此枚举将存在于演示者级别。
上述方法特定于视图-演示者对。您可以改为将其实现为系统范围的事物。逻辑与上面类似,在基本视图和演示器中实现。每个表单都有一个 ShowView__(),或者一个 Show(Views) 方法,其中 Views 是所有表单的枚举。
这是封装和干燥性之间的折腾。
【讨论】: