在坚持正确的层分离的同时,在模型 - 视图 - 展示器模式中调用Response.Redirect
的最佳方法是什么?
答案 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之间的折腾。