If you’ve ever built a Single Page Application on top of ASP.NET, you’ve probably found yourself creating a number of MVC controllers to serve your SPA’s initial views. These views then pull in all of your javascript code and references etc.

In previous versions of ASP.NET, MVC and Web API controllers were separate so you’d often end up with two controllers called the same thing, but in different places.

For example, you might have an Orders MVC controller to serve the main Orders view and an Orders API controller to serve the data which that page uses.

Well hold the phone, in ASP.NET core you can now choose to perform both functions in one controller.

Crossing the streams

In .net core you can use IActionResult as the return type for all of your controller actions irrespective of whether they’re serving data or views.

For example, this action returns an Order.

public class OrderController : Controller {

    public IActionResult ById(string id){
        var order =_orders.Find(id);
        if(order == null){
            return NotFound();
        }
        return Ok(order);
    }
}

IActionResult is super useful because you can easily handle error cases and success cases but stick to one return type.

This example will either return a 404 Not Found result if the order can’t be found, or a 200 status code and the relevant order.

Now what about the Order view? Using .net core you can return the Orders view using the same controller.

public class OrderController : Controller {

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

    public IActionResult ById(string id){
        var order =_orders.Find(id);
        if(order == null){
            return NotFound();
        }
        return Ok(order);
    }
}

Using the standard .net core MVC routing, this will look for a view called Index.cshtml inside of Views/Order.

So how can we hit these two actions?

GET /Order returns Views/Order/Index.cshtml

GET /Order/ById/1 returns the relevant order data (as JSON)

Summary

Declutter your web application. Get rid of those controllers which return a single view for your SPA by moving the action into a .net core controller which also serves your application’s data.