Response.Redirect
的工作方式有一个恼人的怪癖:你几乎总是希望立即终止执行并跳转到新页面:
If ThisIsTheWrongPage Then
Response.Redirect(sUrl, False)
End If
'this code should not execute
DoSomethingWithThisPage
但是Response.Redirect
并没有结束执行,它只是继续前进并执行后续的代码行。这对我正在维护的遗留应用程序造成了很大的破坏。所以你必须这样做:
If ThisIsTheWrongPage Then
Response.Redirect(sUrl, False)
Return
End If
我想要做的是实现这样的方法:
Sub RedirectToUrl(sUrl As String)
'redirect to the specified url
HttpContext.Current.Response.Redirect(sUrl, False)
'return from the CALLING method
End Sub
然后我可以写下这个:
If ThisIsTheWrongPage Then
RedirectToUrl(sUrl)
End If
不必担心丢失的Return语句。我知道编写返回语句并不难,但代码中大约有1000个,并且添加了新的语句,我想要一个开发人员可以调用的方法,而不必小心它{{1}声明。这是一个等待发生的错误。
我知道在传统的.NET代码中没有办法做到这一点,但我想知道它是否可以在IL中实现,弹出堆栈两次并跳转到调用方法的返回位置。
答案 0 :(得分:2)
方法可以更改调用它的方法的返回点的唯一方法是抛出异常。考虑到使用异常处理程序编写许多Web应用程序以防止页面向用户返回500个错误的方式,可能很难通过抛出异常来提供所需的行为。
指示调用者返回的一个问题是无法指定该方法的返回值。异常通过将异常本身传播到堆栈直到找到处理程序来解决此问题。
答案 1 :(得分:2)
这是不可能的。你打破了调用方法的不变量。当你打电话给你没有写过的方法时会发生什么事情是不可预测的。
Redirect
有一个参数可以设置为使其在当前线程上抛出ThreadAbortException
。这完全是针对您的用例。它有效地中止了页面的执行。
答案 2 :(得分:1)
看看这个,它使用jmp opcode, 也许这符合你的需求。
.assembly JumpTest{}
.module JumpTest.exe
.namespace Test{
.class public auto ansi JumpClass extends [mscorlib]System.Object {
.method public static void Main() cil managed{
.entrypoint
.maxstack 8
ldstr "start"
call void [mscorlib]System.Console::WriteLine(string)
ldstr ""
call void Test.JumpClass::Page(string)
ldstr "end"
call void [mscorlib]System.Console::WriteLine(string)
ret
}
.method public static void Page(string sUrl) cil managed{
ldc.i4.1 //always redirect in this test
brfalse.s target
jmp void Test.JumpClass::RedirectToUrl(string)
target:
ldstr "Page() stuff here"
call void [mscorlib]System.Console::WriteLine(string)
ret
}
.method public static void RedirectToUrl(string sUrl) cil managed{
ldstr "RedirectToUrl() stuff here"
call void [mscorlib]System.Console::WriteLine(string)
ret
}
}}