C# tutorials > Frameworks and Libraries > ASP.NET Core > Controllers and Actions (MVC and Razor Pages)
Controllers and Actions (MVC and Razor Pages)
Understanding Controllers and Actions in ASP.NET Core
This tutorial explains controllers and actions in ASP.NET Core, focusing on both MVC (Model-View-Controller) and Razor Pages paradigms. Controllers and actions are fundamental building blocks for handling HTTP requests and generating responses in web applications.
Basic Controller Structure (MVC)
This code demonstrates a simple controller named Key elements:HomeController
with two actions: Index
and Privacy
. Each action returns an IActionResult
, which represents the result of the action. In this case, they return a ViewResult
, indicating that a View should be rendered.
Controller
.IActionResult
return type allows flexibility in returning different types of responses.
using Microsoft.AspNetCore.Mvc;
namespace MyWebApp.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
}
}
Basic Razor Page Structure
This example shows a basic Razor Page. The Key elements:IndexModel
class inherits from PageModel
and contains a handler method OnGet
that is executed when the page is requested with an HTTP GET. The handler sets a value for the Message
property, which is then displayed in the Razor view.
PageModel
.OnGet
, OnPost
, etc., handle specific HTTP verbs.@page
directive in the Razor view identifies it as a Razor Page.@model
directive specifies the page model type.
// Pages/Index.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace MyWebApp.Pages
{
public class IndexModel : PageModel
{
public string Message { get; set; }
public void OnGet()
{
Message = "Hello, Razor Pages!";
}
}
}
// Pages/Index.cshtml
@page
@model MyWebApp.Pages.IndexModel
@{ ViewData["Title"] = "Index"; }
<h1>@Model.Message</h1>
Action Parameters
Actions can accept parameters, allowing you to pass data from the request to the action method. In this example, the Key elements:Details
action accepts an id
parameter. This parameter can be passed in the URL (e.g., /Product/Details/123
) or through other mechanisms like form data.
using Microsoft.AspNetCore.Mvc;
namespace MyWebApp.Controllers
{
public class ProductController : Controller
{
public IActionResult Details(int id)
{
// Fetch product details based on id
// Example: var product = _productService.GetProduct(id);
// return View(product);
// Dummy return for example
return Content($"Details for product with ID: {id}");
}
}
}
IActionResult Return Types
The IActionResult
interface provides a flexible way to return different types of responses from an action. Here are some common IActionResult
implementations:
ViewResult
: Renders a View.ContentResult
: Returns a string of content.JsonResult
: Returns data as JSON.RedirectResult
: Redirects the user to another URL.StatusCodeResult
: Returns an HTTP status code.OkResult
: Returns a 200 OK status code.BadRequestResult
: Returns a 400 Bad Request status code.NotFoundResult
: Returns a 404 Not Found status code.
using Microsoft.AspNetCore.Mvc;
namespace MyWebApp.Controllers
{
public class SampleController : Controller
{
public IActionResult GetProduct(int id)
{
if (id <= 0)
{
return BadRequest("Invalid product ID");
}
//Assume product exist
var product = new { Id = id, Name = "Sample Product", Price = 19.99 };
return Ok(product);
}
}
}
Routing
Routing determines how HTTP requests are mapped to controllers and actions. ASP.NET Core supports both conventional routing and attribute routing. Conventional Routing: Defines route templates in the Attribute Routing: Uses attributes on controllers and actions to define routes. This provides more control and flexibility.Startup.cs
file. A common template is {controller}/{action}/{id?}
.
Attribute Routing Example
This example demonstrates attribute routing. The [Route("api/[controller]")]
attribute on the controller class defines a base route for all actions in the controller. The [HttpGet]
and [HttpGet("{id}")]
attributes on the actions define specific routes for those actions.[controller]
will be replaced by the controller name without the `Controller` suffix (e.g., `Items` in this case).
using Microsoft.AspNetCore.Mvc;
namespace MyWebApp.Controllers
{
[Route("api/[controller]")]
public class ItemsController : Controller
{
[HttpGet]
public IActionResult Get()
{
return Ok(new string[] { "item1", "item2" });
}
[HttpGet("{id}")]
public IActionResult Get(int id)
{
return Ok($"Item with ID: {id}");
}
}
}
Real-Life Use Case: Handling Form Submissions
This example shows how to handle form submissions using controllers and actions. The The `Required` and `EmailAddress` attributes are examples of data annotations used for validation.ContactForm
action handles both the GET request (to display the form) and the POST request (when the form is submitted). The ModelState.IsValid
property checks if the form data is valid based on validation attributes defined in the ContactModel
class.
// Controller Action
using Microsoft.AspNetCore.Mvc;
namespace MyWebApp.Controllers
{
public class ContactController : Controller
{
[HttpGet]
public IActionResult ContactForm()
{
return View();
}
[HttpPost]
public IActionResult ContactForm(ContactModel model)
{
if (ModelState.IsValid)
{
// Process the form data (e.g., send an email)
return RedirectToAction("Success");
}
else
{
// Redisplay the form with validation errors
return View(model);
}
}
public IActionResult Success()
{
return View();
}
}
}
// Model (ContactModel.cs)
public class ContactModel
{
[Required(ErrorMessage = "Name is required")]
public string Name { get; set; }
[EmailAddress(ErrorMessage = "Invalid email address")]
public string Email { get; set; }
[Required(ErrorMessage = "Message is required")]
public string Message { get; set; }
}
Best Practices
Interview Tip
When discussing controllers and actions in an interview, be prepared to explain:
IActionResult
and its various implementations.
When to Use MVC vs. Razor Pages
MVC: Suitable for complex applications with a clear separation of concerns (model, view, controller). Offers greater flexibility and control over the request pipeline. Razor Pages: Simpler and more lightweight, ideal for page-centric applications where each page has its own logic. Easier to learn and use for basic scenarios. The choice depends on the complexity and requirements of your application.
Alternatives
While controllers and actions are the standard way to handle requests in ASP.NET Core, alternative approaches exist:
Pros of Using Controllers and Actions
Cons of Using Controllers and Actions
FAQ
-
What is the difference between
ViewResult
andPartialViewResult
?
ViewResult
renders a complete view, including the layout.PartialViewResult
renders only a partial view, without the layout. Partial views are typically used for reusable UI components within a larger view. -
How can I pass data from a controller to a view?
You can pass data usingViewBag
,ViewData
, or strongly-typed models.ViewBag
andViewData
are dynamic containers, while strongly-typed models provide compile-time type safety. -
How can I implement custom routing?
You can use attribute routing or conventional routing to define custom routes. Attribute routing provides more control and flexibility, while conventional routing is simpler for basic scenarios. You can also implement custom route constraints to further refine the routing process.