Action Results in ASP.NET Core

In this tutorial, we will explore how to create a formatted response in Controller Action methods. The ASP.NET Core provides several APIs collectively called as Action Results to generate the correctly formatted response, which can be consumed by the Clients. Let us explore what is Action Results are and what are the different types of the Action Results that are available to us 

What is Action Results

The Controller Action methods are expected to return the results to the Client. The Client may expect simple results like string & integers or complex results like Json formatted data, HTML views or a file to download etc.

The Controller in ASP.NET Core is Simple C# Classes. They do not need to inherit from any base classes. The ASP.NET Core provides a Controller base class, which in turn inherits from the ControllerBase Class. This helper class provides a lot of helper methods, which makes the working with Controller easier. Hence, generally, our controllers inherit from the Controller class

The Controller Base class implements various result types out of the box, which helps to build various types of results, which can be sent back to the client. For Example, the ViewResult return the HTML response.  A RedirectResult will redirect to another URL etc. The Content Results return a string. These result types are collectively known as Action results.

IActionResult and ActionResult

The IActionResult is an Interface, which defines a contract that represents the result of an action method. 

The ActionResult is an Abstract base class which implements IActionResult.

The Action results like ViewResult, PartialViewResult, JsonResult, etc derive from ActionResult base class.

Why Action Results

There is no need to use Action Results in ASP.NET Core. The Controllers are not required to Inherit from the Controller Class. You can directly manipulate HTTP Response object in the Controller to produce the desired result.

The following example shows how to Inject HttpContext object in the Constructor of the Controller and then use it to create a response. 

public class HomeController {
   HttpContext ctx;
   public HomeController(IHttpContextAccessor _ctx) {
       ctx = _ctx.HttpContext;        
   }
    
   public async void Index() {
       //Set Status Code
       ctx.Response.StatusCode = 200;
       //Set Content Type
       ctx.Response.ContentType = "text/html";
       //Create Response
       ctx.Response.Headers.Add("SomeHeader", "Value");            
       byte[] content = Encoding.ASCII.GetBytes($"<html><body>Hello World</body></html>");
       //Send it to the Client
       await ctx.Response.Body.WriteAsync(content, 0, content.Length);                    
   }
}

Although this approach works, it is not the best way to generate a response from the Controller. The Handling of every controller response this way is tedious, error-prone and difficult to maintain.

The Action Results encapsulate all these low-level details from us. It has many useful features and makes it easier to build responses.

Producing the Response directly in the controller classes, as shown above, makes it hard to Unit Test. To Unit Test of such a controller class, we need to mock the implementations of the Response object. To test the result, we need to Parse the generated HTML Response. 

The Action Results eliminates the need to run the controllers and Action methods under the web server. The context objects can be easily mocked through their base classes.  You don’t need to parse any HTML to test the result of an action method. You can inspect the ActionResult object that is returned to ensure that you received the expected result.

How to Use Action Results

As mentioned above, the ActionResult is an Abstract base class which implements the IActionResult. This class is defined in the namespace Microsoft.AspNetCore.Mvc.  

The ContentResult is one of the Action Results, which returns the string.

public class HomeController : Controller {

    public ContentResult Index()
    {
        ContentResult v = new ContentResult();
        v.Content = "Hello World";
        return v;
    }
}

The Index method above returns the ContentResult.

We. First instantiate a ContentResult (ContentResult v = new ContentResult();). Next, assign a value to it(v.Content = “Hello World”;). And Finally, return it (return v;)

We have a helper method in the Controller base class, View which does the same thing, but in much simpler way.

public ContentResult Index()
{
    return Content("Hello");
}

The Content method invokes the ContentResult internally.

Almost all Action Results have helper method defined in the Controller base class. Usually, these method names have the word “Result” stripped away. For Example Content for ContentResult, View for ViewResult

The Return Type

The Index method above returns the ContentResult. 

The prefered way is to use the ActionResult as the return Type as shown below.

public ActionResult Index()
{
    return Content("Hello");
}

Returning the ActionResult instead of the Actual Type, helps us to use the any of the Action Result. Consider the following code snippet.

public ActionResult Index(int id)
{
    if (id==0) {
       return NotFound();
    }
    else  {
       return Content("Hello");
    }
}

The Index Action method returns two Action Results.  NotFoundResult and ContentResult depending on the value of id parameter.

Action Result Sets

There are many Action Results available in the Microsoft.AspNetCore.Mvc namespace. These can be broadly classified based on their usage as follows.

  1. Producing the HTML
  2. Redirecting the Users
  3. Returning Files
  4. Content Results
  5. Returning Errors and HTTP Codes
  6. Security Related Results

Producing the HTML 

There are two Action results, which uses the model to render the HTML Response. ViewResult and PartialViewResult.

ViewResult

The View() method searches for the View in Views/<Controller> folder to locate the .cshtml file and parses it using the Razor view engine. You can also inject the model data into the view. View method returns the ViewResult, which produces the HTML Response. 

Open the HomeController and copy the following Code 

public ActionResult Index()
{
    var movie = new Movie() { Name = "Avatar" };
    return View(movie);
}

The Index method invokes the View() method, which returns the ViewResult

PartialViewResult

The PartialView Results uses the model to render the part of the View. 

We use ViewResult to get the Complete view, the PartialView results return a part of the View. This Result type is useful in Single Page Applications (SPA) where you would like to update a part of the View via an AJAX call. 

public ActionResult Index()
{
    var movie = new Movie() { Name = "Avatar" };
    return PartialView(movie);
}

Redirecting the Users

The Redirect results are used where you wish to redirect the clients to another URL. 

There are four types redirect results are available for use. RedirectResult, LocalRedirectResult, RedirectToActionResult, and RedirectToRouteResult.

Each of these redirects can return any of the following status codes

  1. 302 Found (Temporarily moved)   
  2. 301 Moved Permanently 
  3. 307 Temporary Redirect 
  4. 308 Permanent Redirect 

RedirectResult

The RedirectResult will redirect the user to the provided relative or absolute URL

Action ResultController methodStatus Code
RedirectResultRedirect302 Found (Temporarily moved)   
RedirectPermanent301 Moved Permanently
RedirectPermanentPreserveMethod308 Permanent Redirect
RedirectPreserveMethod307 Temporary Redirect 

Example:

Redirect("/Product/Index");
RedirectPermanent("/Product/Index");
RedirectPermanentPreserveMethod("/Product/Index");
RedirectPreserveMethod("/Product/Index");

Alternatively, you can use the RedirectResult directly method, which is defined in the microsoft.Aspnetcore.mvc namespace. The syntax is RedirectResult(string url, bool permanent, bool preserveMethod)

return new RedirectResult(url:"/Product/Index", permanent: true, preserveMethod: true);

LocalRedirectResult

This action result is similar to the RedirectResult with one exception. Only the local URLs are accepted. If you provide any external URL, this method throws an InvalidOperationException.  This action method helps us from the open redirect attacks.

Action ResultController methodStatus Code
LocalRedirectResultLocalRedirect302 Found (Temporarily moved)   
LocalRedirectPermanent301 Moved Permanently
LocalRedirectPermanentPreserveMethod308 Permanent Redirect
LocalRedirectPreserveMethod307 Temporary Redirect 

Example:

LocalRedirect("/Product/Index");
LocalRedirectPermanent("/Product/Index");
LocalRedirectPermanentPreserveMethod("/Product/Index");
LocalRedirectPreserveMethod("/Product/Index");

RedirectToActionResult

This action result redirects the client to a specific action and controller. It takes in action name, controller name, and route value.

Action ResultController methodStatus Code
RedirectToActionResultRedirectToAction302 Found (Temporarily moved)   
RedirectToActionPermanent301 Moved Permanently
RedirectToActionPermanentPreserveMethod308 Permanent Redirect
RedirectToActionPreserveMethod307 Temporary Redirect 

Example:

//Redirects to test action in AboutUsController
RedirectToAction(actionName: "Index", controllerName: "AboutUs");

//Redirects to Index action in the current Controller
RedirectToAction(actionName: "Index");

RedirectToRouteResult

This action result redirects the client to a specific route. It takes a route name, route value and redirect us to that route with the route values provided.

Action ResultController methodStatus Code
RedirectToRouteResultRedirectToRoute302 Found (Temporarily moved)   
RedirectToRoutePermanent301 Moved Permanently
RedirectToRoutePermanentPreserveMethod308 Permanent Redirect
RedirectToRoutePreserveMethod307 Temporary Redirect 
// Redirect using route name
return RedirectToRoute("default");

//Redirect using Route Value
var routeValue = new RouteValueDictionary(new { action = "Index", controller = "Home"});
return RedirectToRoute(routeValue);

Returning Files

The FileResult is the Action Result uses the Controller action to serve the files to the user.

FileResult

The FileResult Represents a base class that is used to send binary file content to the response. It is an abstract base class, which is implemented by  FileContentResult, FileStreamResult, VirtualFileResult, & PhysicalFileResult. These classes take care of the job of returning files to the client. 

FileContentResult

The FileContentResult reads from a byte array and returns as a file

return new FileContentResult(byteArray, "application/pdf")

FileStreamResult

The FileStreamResult reads from a stream and returns as a file

return new FileStreamResult(fileStream, "application/pdf");

VirtualFileResult

This action result reads the contents of a file from a path relative to the application on the host and sends the contents to the client as a file.

return new VirtualFileResult("/path/filename", "application/pdf");

PhysicalFileResult

This action result reads the contents of a file from a physical location and sends the contents to the client as a file. Note that the path must be an absolute path.

return new PhysicalFileResult("c:/path/filename", "application/pdf");

Content Results

JsonResult

This action result returns the JSON-formatted data. It serializes the given object into JSON and returns it to the client.

public JsonResult About()
{
    return Json(object);
}

or

public JsonResult About()
{
    return new JsonResult(object);
}

ContentResult

The ContentResult writes the specified content directly to the response as plain-text-formatted string data. 

public ContentResult About()
{
    return Content("Hello World");
}

or

public ContentResult About()
{
    return new ContentResult() { Content = "Hello World" };
}

EmptyResult

The EmptyResult as the name suggests does not return anything. Use this when you want to execute some controller logic, but does not want to return anything

return new EmptyResult();

Returning Errors and HTTP Codes

The Action Results in this section are generally used in Web API controller. These Results sends an HTTP Status Code back to the Client. The some of them can also send an object in the response. 

StatusCodeResult

The StatusCodeResult action result sends a specified HTTP status code to the client. 

return StatusCode(200);
or
return new StatusCodeResult(200);

ObjectResult

This action result will use content negotiation to send an object to the client and sets the HTTP 200 status Code. The overload of the StatusCode method can take an object as the second argument and returns an ObjectResult.

return StatusCode(200, new { message = "Hello" });
or
return new ObjectResult(new { message = "Hello" });

Note that the StatusCode controller helper method can send any status code along with an object.

OkResult

This action result sends an HTTP 200 status code to the client. 

return Ok();
or 
return new OkResult();

OkObjectResult 

This action result sends an HTTP 200 status code to the client. 

return Ok(new {message="Hello"});
or
return new OkObjectResult(new { message = "Not found" });

CreatedResult

The CreatedResult is used when a Resource is created after a Post Request. This sends the status code 201 along with the object created.

return Created(new Uri("/Home/Index", UriKind.Relative), new {message="Hello World"});
or
return new CreatedResult(new Uri("/Home/Index", UriKind.Relative), new { message = "Hello World" });

CreatedAtActionResult

This Action Result is similar to CreatedResult Action but takes Controller & Action name instead of  Uri.

return CreatedAtAction("Index", new {message="Hello World"});

CreatedAtRouteResult

This Action Result takes route values and is similar to CreatedResult and CreatedAtActionResult.  

CreatedAtRoute("default", new { mesage = "Hello World" });

BadRequestResult

This action result sends an HTTP 400 status code to the client. Use this response status code to indicate the invalid syntax or request that cannot be understood.

return BadRequest()

BadRequestObjectResult

This ActionResult is similar to the BadRequestResult. The difference is that you can send ModelStateDictionary (which is an object containing details of error) along with the 400 status code.

var modelState = new ModelStateDictionary();
modelState.AddModelError("message", "errors found. Please rectify before continuing");
return BadRequest(modelState);

The Controller Helper method BadRequest has a second overload, which returns the BadRequestObjectResult.

NotFoundResult

This Action Result sends an HTTP 404 status code to the client.

return NotFound();

NotFoundObjectResult

This action result is similar to the NotFoundResult, but returns an object along with the 404 status code. The Second overload of NotFound controller helper method takes an object as the argument and returns the NotFoundObjectResult.

return NotFound( new { message = "Not found" });

UnsupportedMediaTypeResult

This action result sends an HTTP 415 status code to the client. Use this action result, when the request is in a format not supported by the server.

return new UnsupportedMediaTypeResult();

NoContentResult

This action result sends an HTTP 204 status code. Use the NoContentResult when the request is fulfilled, but there is no content to send back to the client

return NoContent();

Security Related Results

SignInResult

The SignInResult Represents the result of a sign-in operation. The SignInManager.SignInAsync or PasswordSignInAsync returns SignInResult, which has four properties Succeeded, IsLockedOut, IsNotAllowed, and RequiresTwoFactor etc.

You can refer to the ASP.NET Core Identity tutorial 

SignOutResult

The SignOutResult Represents the result of a sign-out operation.

ForbidResult

The ForbidResult returns 403 (Forbidden) status code when a user isn’t authorized to perform the requested operation on the given resource.

The ForbidResult does not mean that the user is not authenticated. The unauthenticated users should get ChallengeResult or UnauthorisedResult

return new ForbidResult();

or

return Forbid();

The Forbid is a method on the controller base class that returns the instance of the ForbidResult.

Alternatively, you can also use the Status Code result.

return StatusCode(403);

ChallengeResult

The ChallengeResult is returned, when the user authentication is failed. This Result will inform any authentication middleware to take the appropriate response, for example returning a 401 (Unauthorized)  or 403 (Forbidden) status code, or redirecting the user to a login page for interactive browser clients.

UnauthorizedResult

The UnauthorizedResult returns “401 – Unauthorized” HTTP response status code. The Controller base class method Unauthorized returns an instance of UnauthorizedResult.

return Unauthorized();

OR

return new UnauthorizedResult();

The difference  UnauthorisedResult with ChallengeResult is that it just returns a status code and doesn’t do anything else with it.

Summary

In this article, we learnt what is Action Result are and how to use them. We also described most of the action results available in Asp.Net Core.

Related Articles

  1. ASP.NET Core Tutorial
  2. Building the First ASP.NET MVC Application
  3. Controller Basics
  4. ASP.NET Core MVC Views

5 thoughts on “Action Results in ASP.NET Core”

  1. Very good and helpfull, though i have a question why my SignOutResult geives me CORS issue while ChallengeResult is working fine.
    Note: i have application built in .Net Core as rest api and Angular as client side

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top