我已经从Wrox Professional ASP.NET 4.0 MVC 4
书籍,第179页(“了解Web应用程序中的安全性向量”一章)中复制了以下代码,并对其进行了少量修改protected
并将其作为实用程序方法存储在我的抽象应用程序范围Controller
protected ActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
上面的代码旨在保护MVC应用程序免受开放式重定向攻击,这些攻击不是问题的主题。
代码显然格式正确,编译并且我相信它有效。
当“巧妙地”将上面的代码更改为以下单行
时,就会出现问题return (Url.IsLocalUrl(returnUrl)) ? Redirect(returnUrl) : RedirectToAction("Index", "Home");
上面的单行应该与扩展代码完全相同(不,ReSharper不建议我替换,这是我的主动)。
编译错误如下:there is no implicit conversion between System.Web.Mvc.RedirectResult and System.Web.Mvc.RedirectToRouteResult
。
然后ReSharper来帮助并建议以下修改
return (Url.IsLocalUrl(returnUrl)) ? (ActionResult) Redirect(returnUrl) : RedirectToAction("Index", "Home");
由于Redirect
和RedirectToAction
都返回ActionResult
的子类(通过F12验证),并且该子类是函数的返回值,因此它应该是自动兼容的。或者至少,根据我对C#的了解,要么两个代码都编译,要么两者都不编译。
更一般地说,问题可以重新拟定如下:
假设我有A,B和C类
abstract class A {}
class B: A{}
class C: A{}
假设以下功能有效
private A Function(){
if (condition) return new B();
else return new C();
}
为什么下面的单行程序无法编译?
private A Function(){
return (condition) ? new B(): new C();
}
答案 0 :(得分:6)
它不会编译,因为编译器根据两个返回值之一决定一个内容的返回类型。由于类型B不是派生类型C,反之亦然,这两种类型不是互斥的,而if(作为一个整体)的返回类型不能以这种方式派生。
如果您希望在单行中执行此操作,则必须将返回值强制转换为要返回的类型,即类型A.
private A Function(){
return (condition) ? ((A)new B()): ((A)new C());
}
更新:我没有看到你已经在你的问题中进行了投射,我很抱歉。
答案 1 :(得分:2)
编译器期望在条件语句中使用相同的返回类型,因此它希望这两者都是相同的类型。如果将选项转换为ActionResult,它将起作用。您可以通过仅投射最后一个来与编译器相处。
return (Url.IsLocalUrl(returnUrl)) ? (ActionResult)Redirect(returnUrl) : (ActionResult)RedirectToAction("Index", "Home");