Building Responses
In this lesson, we will gain more insights on all response types an action method can return.
We already said that action methods return IAsyncResult
implementations, which are then executed by the framework after possible action filters have been applied. This lesson classifies all predefined IAsyncResult
implementations and gives more details about each of them.
ViewResult and View method
The ViewResult
implementation is returned when an action method calls the View
method when we write return View(...);
. The View
method has several overloads. Each overload can specify whether or not which of the paths of the view to invoke and which ViewModel to pass it. If no view name is specified the framework tries to find a view with the same name of the action method, while if no ViewModel is specified a null ViewModel is passed to the view.
In order to retrieve a view, the View
method adds the .cshtml
extension to the view name it receives and then interprets it as paths. If the path is relative the view is first searched in a folder with the same name of the controller. For instance, Home
for the HomeController
, which is under the Views
folder. If the view is not found there it is searched under the “Shared” folder, which is always under the Views
folder. Absolute paths that start with a /
are not searched in the hard disk root, but in the application root folder.
When a view is invoked it is passed the current request HttpContext
, the controller TempData
, and the Controller ViewData
, plus the whole controller ModelState
that is used to show all errors computed so far, in the view.
We already used the View
method in several examples, so you should already know everything was said in this section.
PartialViewResult and PartialView method
We never used the PartialViewResult
and the PartialView
method, but they are completely analogous to ViewResult
and View
. They invoke a view with exactly the same procedure we described in the previous section, but the view they invoke is not inserted inside any layout view.
This is because their purpose is not to render a whole HTML page but just an HTML fragment to be returned to an AJAX call. Sometimes, instead of completely changing a page, it is convenient to modify an area of the current page. This can be achieved by invoking an action method that returns the HTML that must replace a part of the page via JavaScript. Then, the same JavaScript snippet that invoked the action method can perform all needed DOM manipulation to update the target page area with the newly received HTML.
Dynamic modification of the Web page HTML enables the user to continue their interaction with the page while the new HTML is being loaded.
AJAX calls that return HTML have lost their popularity since modern client-side JavaScript frameworks like REACT, Angular, and Vue.js can create new HTML without the help of the server. At the moment, the most common way to dynamically update page areas is to retrieve JSON data from API controllers and to use these client-side frameworks to render the retrieved data with fresh HTML fragments.
We will see some examples of usage of PartialView
in the chapter dedicated to HTML code reusability.
RedirectResult and Redirect
The Redirect
method accepts a URL and returns a redirect response to the browser. When the browser receives this response it issues a new GET
request to that URL. It is used mainly to move the browser to a different website because the best way to move the browser to a URL on the same website is the usage of RedirectToAction
.
RedirectToActionResult and RedirectToAction
Similar to Redirect
, RedirectToAction
returns a redirect response to the browser, but this time the URL is computed through the name of the target action name, controller, and route data.
This way, if the routing rules are changed there is no need to change the code. If the controller argument is omitted the current controller is taken to compute the URL. All route and query string parameters are passed through an anonymous object as shown below:
return RedirectToAction("MyActionMethod", "MyController", new {id=3, culture="it"});
We already used RedirectToActionResult
in various examples. If you need to refresh your knowledge, please review the second lesson of this chapter.
The Content and File methods
The Content
method returns a text result and gives us the opportunity to define its content-type
. We described the Content
method in the second to last lesson, please review it, if you don’t remember how to use it.
The File
method instead returns generic binary data and gives us the opportunity to define their content-type
. We described the File
method in the previous lesson, please review it, if you don’t remember how to use it.
The Unauthorized and Forbidden methods
The Unauthorized
method returns a 401
code, meaning login is required and the user is not logged in. If there is an authorization logic in place, this result might cause a redirect to the login URL. We will analyze authorization logic in detail in a dedicated chapter. Forbidden
returns a 403
code meaning the user is logged in but does not have enough privileges to access the URL.
We should never call these methods as they are called automatically by the [Authorize]
action filter that handles authorization logic, which we will describe in a dedicated chapter.
The Json method
The Json
method formats the objects passed as argument in JSON and adds it to the response. It has a second optional argument that may contain the options to pass to the .NET JsonSerializer
instance that carries out the serialization. This should only be used if we need to customize the way JSON must be produced with the options argument, otherwise, it is better to prefer the API controller-specific methods described in the next section.
StatusCode and API controllers
StatusCode
is used mainly by API controllers that accept and return JSON or XML. It allows specifying both the status code and the object to be converted in JSON and XML. StatusCode
has shortcuts for specific status codes. The table below summarizes and suggests when to use each of them:
Method | What it does | When to use it |
---|---|---|
Created(string uri, object o) | Returns a 201 code, with an object containing the URI of a new resource, and the newly created resource | After a successful POST that created a new resource. |
OK(object o = null) | Returns a 200 code with an optional object | After the successful completion of any operation different from creation. |
Accepted(sting URI, object o) | Returns a 202 code with an optional object containing an optional URI and an optional object representing a resource | Whenever an operation is accepted but not executed. The URI is the location of the updated or created resource. |
NoContent() | Returns a 204 code with an empty body | Whenever an operation is successfully executed but there is no information to return. |
NotFound(object o=null) | Returns a 404 code and an optional object with further information on the error | Whenever a resource required by the client is not found. |
BadRequest(ModelState errors) | Returns a 400 code and the list of all errors contained in the ModelState | Whenever the client sends an ill-formatted request. |
Both Accepted
and Created
have analogous AcceptedAtAction
and CreatedAtAction
methods that compute the URI contained in the response through action method name, controller name, and route parameters.
Get hands-on with 1400+ tech skills courses.