I have copied the following code from Wrox Professional ASP.NET 4.0 MVC 4 book, page 179 (Chapter “Understanding the Security Vectors in a Web Application”) with the little modification of making it protected and storing as utility method in my abstract application-wide Controller
protected ActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
The code above is aimed at securing the MVC application from open redirection attacks, which are not subject of the question.
The code is obviously well-formed, compiles and I trust it works.
The problem arises when “smartly” changing the code above into the following one-liner
return (Url.IsLocalUrl(returnUrl)) ? Redirect(returnUrl) : RedirectToAction("Index", "Home");
The one-liner above is supposed to do exactly the same as the extended code (no, ReSharper didn’t suggest me to replace, it was my initiative).
The compilation error is the following: there is no implicit conversion between System.Web.Mvc.RedirectResult and System.Web.Mvc.RedirectToRouteResult.
ReSharper then comes to help and suggests the following modification
return (Url.IsLocalUrl(returnUrl)) ? (ActionResult) Redirect(returnUrl) : RedirectToAction("Index", "Home");
The question is “why do I have to cast Redirect method”?
Since both Redirect and RedirectToAction return a subclass of ActionResult (verified via F12) and that subclass is the return value of the function, it should be automatically compatible. Or at least, in my knowledge of C#, either both codes compile or they both don’t.
To be more general, the question could be reformulated as follows:
Suppose I have class A, B and C
abstract class A {}
class B: A{}
class C: A{}
And suppose the following function works
private A Function(){
if (condition) return new B();
else return new C();
}
Why the following one-liner doesn’t compile?
private A Function(){
return (condition) ? new B(): new C();
}
It doesn’t compile because the compiler decides what the return-type of the one-liner is based upon one of the two return-values. Since type B doesn’t derive of type C, or the other way around, the two types are not mutually exclusive, and the return type of the if (as a whole) cannot be derived that way.
If you would want to do it in a one-liner, you have to cast the return-values to the type that you want to return, which is type A.
UPDATE: I didn’t see that you already do the casting in your question, my apologies.