When in need of redirecting the user on client-side (e.g. when in ajax actions),
Most of the developers choose the easy way and just return a JavascriptResult('window.location = ...')
and passing to it Url.Action(...)
.
-
Testability: There are several ways that the above approach makes unit-testing difficult (if not impossible).
- By using
Url.Action(...)
the code heavily depend on the routing and request url configurations that requires a lot of mocking during unit-testing. - You would have to assert against a literal string (i.e.
window.location = ...
) instead of a state of action result (i.e. what action you wish to redirect to).
- By using
-
Breaking the MVC pattern: One of the building block of MVC is to seperate presentation (view) and controller; Altough they don't look like to be, both "building url" and "building script", are presentation concerns that in the solution mentioned above are included in the controller (wrong place).
Exactly in the same as ASP.NET MVC's built-in normal redirections works!
Instead of returning the javascript itself, we send out a specific type of ActionResult
that renders the same javascript as before but now at the right time.
So...
- It is easily testable: because it is strongly typed and has state to assert againist (i.e. URL or Route Data)
- It perfectly matches the principles of MVC pattern
- ControllerExtensions: Extension methods for redirecting to either action or custom url
- RedirectOnClientResultBase: The base class for client-side redirection action results.
- RedirectOnClientResult: The action result type for redirecting to a custom url.
- RedirectToRouteOnClientResult: The action result type for redirecting to a route.
- RouteValuesHelpers: Some helper methods (copied over from ASP.NET MVC source code) -- unfortunately this couldn't be reference from there as it has accessibility restrictions.