我在这里有两个问题,如果第一个问题得到回答,第二个问题是无关紧要的,但我认为在技术上仍然很有趣......我会尽量清楚:
- 第一个问题:我的目标是在 MVC 中伪造一个 Server.Transfer,是否有任何下降的方法可以做到这一点,我发现了很多关于它的文章,但大多数都是关于重定向/重新路由的,这在我的情况下是不可能的(不是至少我能想到)。
这是上下文,我们有两个版本的网站,一个“桌面”版本和一个移动版本。我们的营销人员希望在同一个 url 上提供两个版本的主页(因为 SEO 专家是这么说的)。
这听起来微不足道和简单,在大多数情况下,除了...相同的应用程序)。
因为桌面版本代表了我们大约 95% 的流量,所以这应该是默认设置,并且我们希望仅当用户在移动设备上或确实需要时,才从后面的 ASPX 代码“传输”(因此相同的 url)到 MVC 视图看手机版。据我目前所见,没有简单的方法可以做到这一点(Server.Transfer 只执行一个新的处理程序 - 因此页面 - 如果有一个物理文件)。因此,到目前为止,有没有人以适当的方式做到这一点?
这让我想到:
- 第二个问题:我确实建立了自己的转移到 MVC 机制,但后来发现 Response.End() 实际上不再结束正在运行的线程,有人知道为什么吗?
显然,我不希望有任何答案出乎意料,所以这就是我正在做的事情:
在需要转移到移动设备的页面中,我执行以下操作:
protected override void OnPreInit(EventArgs e) {
base.OnPreInit(e);
MobileUri = "/auto/intro/index"; // the MVC url to transfer to
//Identifies correct flow based on certain conditions 1-Desktop 2-Mobile
BrowserCheck.RedirectToMobileIfRequired(MobileUri);
}
而我由 RedirectToMobileIfRequired 调用的实际 TransferToMobile 方法(我跳过了检测部分,因为它非常不相关)看起来像:
/// <summary>
/// Does a transfer to the mobile (MVC) action. While keeping the same url.
/// </summary>
private static void TransferToMobile(string uri) {
var cUrl = HttpContext.Current.Request.Url;
// build an absolute url from relative uri passed as parameter
string url = String.Format("{0}://{1}/{2}", cUrl.Scheme, cUrl.Authority, uri.TrimStart('/'));
// fake a context for the mvc redirect (in order to read the routeData).
var fakeContext = new HttpContextWrapper(new HttpContext(new HttpRequest("", url, ""), HttpContext.Current.Response));
var routeData = RouteTable.Routes.GetRouteData(fakeContext);
// get the proper controller
IController ctrl = ControllerBuilder.Current.GetControllerFactory().CreateController(fakeContext.Request.RequestContext, (string)routeData.Values["controller"]);
// We still need to set routeData in the request context, as execute does not seem to use the passed route data.
HttpContext.Current.Request.RequestContext.RouteData.DataTokens["Area"] = routeData.DataTokens["Area"];
HttpContext.Current.Request.RequestContext.RouteData.Values["controller"] = routeData.Values["controller"];
HttpContext.Current.Request.RequestContext.RouteData.Values["action"] = routeData.Values["action"];
// Execute the MVC controller action
ctrl.Execute(new RequestContext(new HttpContextWrapper(HttpContext.Current), routeData));
if (ctrl is IDisposable) {
((IDisposable)ctrl).Dispose(); // does not help
}
// end the request.
HttpContext.Current.Response.End();
// fakeContext.Response.End(); // does not add anything
// HttpContext.Current.Response.Close(); // does not help
// fakeContext.Response.Close(); // does not help
// Thread.CurrentThread.Abort(); // causes infinite loading in FF
}
在这一点上,我希望 Response.End() 调用也能结束线程(如果我跳过整个伪造控制器执行位,它会结束),但事实并非如此。
因此,我怀疑要么是我伪造的上下文(这是我发现能够使用新 url 传递当前上下文的唯一方法),要么是控制器阻止了线程被杀死。
fakeContext.Response 与 CurrentContext.Response 相同,并且结束虚假上下文响应或终止线程的几次尝试并没有真正帮助我。
在 Response.End() 之后运行的任何代码实际上都不会呈现给客户端(这是一个小小的胜利),因为正在关闭响应流(以及连接,客户端中没有“无限加载”)。但是代码仍在运行,这并不好(在尝试编写 ASPX 页面、编写标题等时,显然也会产生大量错误)。
因此,任何新的领导都将受到欢迎!
总结一下: - 有没有人有一种不那么老套的方法来实现在同一个 url 上共享 ASPX 页面和 MVC 视图?- 如果没有,有没有人知道我如何确保我的回复真的被结束了?
提前谢谢了!