Actions in ASP.NET Core

Actions in ASP.NET Core

On my last tutorial on Controllers in ASP.NET Core I tough about Controller. A controller contains Action methods, they can have any return type like string, int, datetime, ViewResult, IActionResult, etc. In all of them the return type of IActionResult is quite useful. It is because it fits everywhere, allowing the action method to return a View, redirect to another View, or return a data type like string, int, datetime, etc.

When the return type of action method is IActionResult or ViewResult then it can tell MVC to render a given View. This is done by the View() method.

The given action method is telling MVC to return a View which in this case is the ‘Index’ View.

public IActionResult Index()
{
    return View();
}

The View() method has 4 different versions which are described in the below table:

Method Description
View() Targets the default View for the MVC to render it. Eg if the action method name is ‘List’ and you are using the View() method then the ‘List.cshtml’ view will be rendered by MVC.
View(“name_of_view”) This version takes the view name in its parameter and this view will be rendered.Eg if you use View(“Show”) then the ‘Show.cshtml’ view will be rendered
View(model) This version will render the default view by providing it with model data (class data). This is used to make the rendered view strongly typed.
View(“name_of_view”, model) This version specifies the View by its name along with the model data that it will be provided with./td>

Passing Data from Action Method to View

There are 4 different ways of passing data from Action Method to a View. These are:

1. View Model Object
2. ViewBag
3. TempData
4. Session Variable

View Model Object

Previously I explained the View() method to you. This method is used to send an object to the View. To understand it, create a new Controller and name it ‘Example’ and let its ‘Index’ Action returns current date & time (by DateTime.Now) as shown below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace UnderstandingControllers.Controllers
{
    public class ExampleController : Controller
    {
        public IActionResult Index()
        {
            return View(DateTime.Now);
        }
    }
}

I have passed DateTime object to the View. Now create Index View inside the ‘Views/Example/’ folder with the code as given below. Notice I am displaying the date & time value which is returned by the Action method as @Model.

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    Model: @Model and Year: @(((DateTime)Model).Date)    
</body>
</html>

Now to display the current Year my code is – @(((DateTime)Model).Date). This is because I have to cast the Model to DateTime first only then I can extract the Date from it.

Run the application and go to – ‘/Example’. You will see the date Time and current year displayed on the browser as shown in the below image.

untyped view

This is an Untyped View or Weakly Typed View. The View has no prior knowledge about the View Model Object it will be receiving from the Action. So I have to cast it to an instance of DateTime.

I can make this view Strongly Typed View by telling the View the type of the View Model Object it will be receiving from the Action.

The below highlighted code makes my View strongly typed:

@model DateTime
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
    Model: @Model and Year: @Model.Year
</body>
</html>

Notice I defined the View Model Object by – @model DateTime.

Now I can simply display the current year as – @Model.Year without having to cast it.

In the same way you can also send View Model Object of type String, class, bool, etc.

Note: In the above section of Model Binding I explained how to pass class object from Action method to a View.

If you are passing string from action to view then cast your string to Object, like this way:

retrun View((object)"How are you");

The reason for this is because if the parameter of the View() method is string then it will search for the view that has the name same like the string in the parameter.

ViewBag

View Bag allows you to define properties on a dynamic object. These properties can then be accessed in Views. The dynamic object can be accessed through the ViewBag property.

Create a new action by name ‘ViewBagExample’ in the ‘Example’ Controller having code shown below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace UnderstandingControllers.Controllers
{
    public class ExampleController : Controller
    {
        public IActionResult Index()
        {
            return View(DateTime.Now);
        }

        public IActionResult ViewBagExample()
        {
            ViewBag.CurrentDateTime = DateTime.Now;
            ViewBag.CurrentYear = DateTime.Now.Year;
            return View();
        }
    }
}

I have added 2 properties – CurrentDateTime & CurrentYear to the ViewBag variable. These contains the current datetime and current year.

Now on my View I can simply access these values like ViewBag.CurrentDateTime & ViewBag.CurrentYear. See the below ‘ViewBagExample’ View’s code:

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>ViewBagExample</title>
</head>
<body>
    Model: @ViewBag.CurrentDateTime and Year: @ViewBag.CurrentYear
</body>
</html>

Now run the application and go to the URL – ‘/Example/ViewBagExample’, it will give the same display like the View Model Object example above.

Points to Remember

1. ViewBag is lightweight method of transferring values to Views from Controllers.
2. ViewBag only transfers data from controller to view, not visa-versa. ViewBag values will be null if redirection occurs.
3. It can contain primitive or a complex type object.
4. You can assign any number of properties and values to ViewBag.

TempData

You know that ViewBag values are lost in case there is a redirection therefore for such cases you use TempDate. TempData is similar to ViewBag except that its values live during redirection also.

MVC automatically removes the values of the TempData as soon as they are read.

Let’s add 2 new actions in the Example Controller. The codes for these 2 actions are given below:

public IActionResult TempDataExample()
{
    TempData["CurrentDateTime"] = DateTime.Now;
    TempData["CurrentYear"] = DateTime.Now.Year;
    return RedirectToAction("TempDataShow");
}

public IActionResult TempDataShow()
{
    return View();
}

The ‘TempDataExample’ action adds the current datetime and current year to 2 properties of TempDate – ‘CurrentDateTime’ & ‘CurrentYear’. It then redirects to the ‘TempDataShow’ using the RedirectToAction method as shown below:

return RedirectToAction("TempDataShow");

The ‘TempDataShow’ just invokes the default View.

Create the ‘TempDataShow’ View inside the ‘Views/Example’ folder. Then add the below code to it:

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>TempDataShow</title>
</head>
<body>
    Model: @TempData["CurrentDateTime"] and Year: @TempData["CurrentYear"]
</body>
</html>

TempData stores values in dictionary manner so I am accessing these values using brackets ‘[]’.

Note that TempData relies on Session Middleware therefore you have to add it to the Startup class.

The highlighted lines in the below code tells what you have to add to the Startup class.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;

namespace UnderstandingControllers
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddMemoryCache();
            services.AddSession();
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseDeveloperExceptionPage();
            app.UseStatusCodePages();
            app.UseStaticFiles();
            app.UseSession();
            app.UseMvc(routes =>
            {
                // Default Route
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

The AddMemoryCache and AddSession methods create services required by session
management.

The UseSession method adds a middleware component to the pipeline. It associates
session data with requests and adds cookies to responses.

You must add UseSession method before the UseMvc method so that the session component can intercept requests before they reach MVC middleware.

Now run the application and go to the URL – ‘/Example/TempDataExample, it will show the current datetime and year, like the View Model Object example above.

Note: We can’t use ViewBag in this case as Viewbag values gets lost during redirection. You can check it by replacing the TempData with ViewBag in the TempDataShow View and the ‘TempDataExample’ action.

MVC automatically removes the values of the TempData as soon as they are read. There is ‘Keep’ method to prevent MVC from removing the value once read. However if the value is read again (2nd time) then MVC will delete it.

The ‘Peek’ method allows you to get the value and also prevent it from deletion. This is because it does not tells MVC that the value has been read.

Use session to store the value permanently (until the session expires) for as many reads as you want and in any part of the application.

Session Variable

Session state is a storage of data while the user browses a website. Session state uses a store maintained by the app to persist data across requests from a client. You can use the data stored in the Session variable anywhere in your website.

You know that I have enabled session for the application in the previous section by adding services and configuration in the Startup class. See the highlighted lines in the below code:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(); 
    services.AddMemoryCache();
    services.AddSession();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseDeveloperExceptionPage();
    app.UseStatusCodePages();
    app.UseStaticFiles();
    app.UseSession();
    app.UseMvc(routes =>
    {
        // Default Route
        routes.MapRoute(
            name: "default",
            template: "{controller=Home}/{action=Index}/{id?}");
    });
}

Now to check how session state works, create a new action ‘SessionExample’ inside the ‘Example’ Controller. The code of this action is given below:

public IActionResult SessionExample()
{
    HttpContext.Session.SetString("CurrentDateTime", DateTime.Now.ToString());
    HttpContext.Session.SetString("CurrentYear", DateTime.Now.Year.ToString());
    return View();
}

To use session in controller class, you need to reference “Microsoft.AspNet.Http” in controller.

The SetString() will add any value as string to the session variable. In my case I am adding the current datetime and year as string to the 2 session variables.

To access the session’s variable value in the view you have to add a singleton service – services.AddSingleton(); to the ConfigureServices method of startup class. See the below highlighted line:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddMemoryCache();
    services.AddSession();
    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}

Now create the SessionExample View inside the ‘Views/Example’ folder and add the following code to it:

@using Microsoft.AspNetCore.Http
@inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContextAccessor
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>SessionExample</title>
</head>
<body>
    Model: @HttpContextAccessor.HttpContext.Session.GetString("CurrentDateTime") and Year: @HttpContextAccessor.HttpContext.Session.GetString("CurrentYear")
</body>
</html>

I have included the namespace ‘Microsoft.AspNetCore.Http’ just like controller. Then injected my created singleton object.

Finally I access the session values using @HttpContextAccessor.HttpContext.Session.GetString().

Run the application and go to the URL – ‘/Example/SessionExample to see the current datetime and year displayed by the view.

More information about Session

Just like the SetString() method the session also has SetInt32() which stores the int value in the session variable:

HttpContext.Session.SetInt32("MySession", 100);

To store complex data types like class variable in the session you have to serialize them. Then to get the serialized value from session you have to Deserialize them.

To do this following extension methods to set and get serializable objects

public static class SessionExtensions
{
    public static void Set<T>(this ISession session, string key, T value)
    {
        session.SetString(key, JsonConvert.SerializeObject(value));
    }

    public static T Get<T>(this ISession session, string key)
    {
        var value = session.GetString(key);

        return value == null ? default(T) : 
            JsonConvert.DeserializeObject<T>(value);
    }
}

// Setting the value
HttpContext.Session.Set<Person>("MyPersonClass", person);

// Getting the value
HttpContext.Session.Get<Person>("MyPersonClass");

Session’s cookie name and expiration time can be set inside the services.AddSession() method as shown below:

services.AddSession(options =>
    {
        options.Cookie.Name = "AdventureWorks.Session"; // Cookie name
        options.IdleTimeout = TimeSpan. FromHours(1); // 1 hours expiry
    });

Performing Redirections in Action Methods

There are many ways to perform redirection form an action method to another action method. There are many methods for it like:

1. Redirect
2. RedirectPermanent
3. RedirectToRoute
4. RedirectToRoutePermanent
5. RedirectToAction
6. RedirectToActionPermanent

Redirect

The redirect method is used to perform a temporary redirection (HTTP 302). It takes the redirection URL as a string argument and returns an instance of the RedirectResult class.

Example: The below Action method by the name ‘RedirectAction’ performs a temporary redirect to URL – ‘/List/Search’.

public RedirectResult RedirectAction() => Redirect("/List/Search");

RedirectPermanent

RedirectPermanent method is similar to Redirect method except it redirects user permanently (HTTP 301).

Example: This time the action method by name of ‘RedirectAction’ performs a permanent redirect to URL – ‘/List/Search’.

public RedirectResult RedirectAction() => RedirectPermanent("/List/Search");

RedirectToRoute

If you want to redirect user by following the routes of your application then you should use RedirectToRoute() method. It performs temporary redirection and takes an anonymous type as parameter. The properties of the anonymous type are then passed to the routing system to generate a URL.

The RedirectToRoute() method returns an instance of the RedirectToRouteResult.

Let’s take an example. My application has the route:

routes.MapRoute(
    name: "default",
    template: "{controller=Home}/{action=Index}/{id?}");

To perform based on this route I can use the RedirectToRoute() method as shown below:

public RedirectToRouteResult Redirect() {
    RedirectToRoute(new { controller = "Admin", action = "Users", ID = "10" });
}

So it will redirect user to – ‘/Admin/Users/10’.

RedirectToRoutePermanent

The RedirectToRoutePermanent similar to RedirectToRoute method except it redirects user permanently.

Example:

public RedirectToRouteResult Redirect() {
    RedirectToRoutePermanent(new { controller = "Admin", action = "Users", ID = "10" });
}

RedirectToAction

The RedirectToAction method performs temporary redirection to a given action method.

This method returns an instance of RedirectToActionResult class.

The redirect URL is formed based on the routes of your application.

Consider that my application route is:

routes.MapRoute(
    name: "default",
    template: "{controller=Home}/{action=Index}/{id?}");

Now consider you apply RedirectToAction() method on the Index View as shown in the below code:

public class HomeController : Controller
{
    public RedirectToActionResult Index()
    {
        return RedirectToAction("List");
    }
	
    public RedirectToActionResult List()
    {
        return View();
    }
}

So this will redirect user (based on the routes) to the URL – ‘/Home/List’.

If you give just an action method, then ASP.NET Core MVC assumed that you are referring to an action method in the current controller.

So to redirect to the action of a different Controller you need to specify the Controller name also. In the below code I am redirecting to the ‘List’ Action of ‘Customer’ Controller:

public RedirectToActionResult Index()
{
    return RedirectToAction("Customer","List");
}

RedirectToActionPermanent

The RedirectToActionPermanent method performs permanent redirection. In all other cases it is similar to RedirectToAction method.

Example:

public RedirectToActionResult Index()
{
    return RedirectToActionPermanent("List");
}

Returning Different Types of Content from Action Methods

So far you have seen Action method returning string and View. But these are not the only things. In fact actions can return JSON and HTTP Status codes. The below topics teaches you these methods.

Returning JSON from Action

We use method Json() to return JSON (JavaScript Object Notation) objects from Action methods. This method returns an object of JsonResult class.

The below Action method in the Example Controller return a JSON:

public JsonResult ReturnJson()
{
    return Json(new[] { "Brahma", "Vishnu", "Mahesh" });
}

To test it run the application and go to the URL – ‘/Example/JsonResult’, you will see the JSON as shown in the given image:

return json from action

Returning OK (HTTP Status Code 200) from Action

The OK method produces an empty HTTP Status Code 200 response. It can be used to return objects in common format between the browser and the application with HTTP 200 status code.

The return type of this method is OkObjectResult class.

Example:

public OkObjectResult ReturnOk()
{
    return Ok(new string[] { "Brahma", "Vishnu", "Mahesh" });
}

To return just 200 status code simply use an empty Ok() method.

Returning BadRequest (400), Unauthorized (401), NotFound (404) status codes from Action

The StatusCode method that resides inside the Microsoft.AspNetCore.Http namespace is used to return any type of status codes like BadRequest, Unauthorized, NotFound, etc.

The return type of this method is StatusCodeResult class object.

Example: Returning BadRequest – 400 Status Code
public StatusCodeResult ReturnBadRequst()
{
    return StatusCode(StatusCodes.Status400BadRequest);
}

Example: Returning Unauthorized – 401 Status Code
public StatusCodeResult ReturnUnauthorized()
{
    return StatusCode(StatusCodes.Status401Unauthorized);
}

Example: Returning NotFound – 404 Status Code
public StatusCodeResult ReturnNotFound()
{
    return StatusCode(StatusCodes.Status404NotFound);
    //or return NotFound();
}

You can download the full codes of this tutorial from the below link:

Download

Conclusion

In this tutorial I explained Action Methods and their usage in Controllers. I hope you find it useful.

I will continue with Views in my next tutorial – Views in ASP.NET Core

Share this article -

yogihosting

ABOUT THE AUTHOR

This article has been written by the Technical Staff of YogiHosting. Check out other articles on "ASP.NET Core, jQuery, EF Core, SEO, jQuery, HTML" and more.