Difference between ApiController and Controller in ASP.NET MVC - asp.net-mvc

I've been playing around with ASP.NET MVC 4 beta and I see two types of controllers now: ApiController and Controller.
I'm little confused at what situations I can choose a particular controller.
For ex: If I want to return a view then I've to use ApiController or the ordinary Controller? I'm aware that the WCF Web API is now integrated with MVC.
Since now we can use both controllers can somebody please point at which situations to go for the corresponding controller.

Use Controller to render your normal views. ApiController action only return data that is serialized and sent to the client.
here is the link
Quote:
Note If you have worked with ASP.NET MVC, then you are already familiar with controllers. They work similarly in Web API, but controllers in Web API derive from the ApiController class instead of Controller class. The first major difference you will notice is that actions on Web API controllers do not return views, they return data.
ApiControllers are specialized in returning data. For example, they take care of transparently serializing the data into the format requested by the client. Also, they follow a different routing scheme by default (as in: mapping URLs to actions), providing a REST-ful API by convention.
You could probably do anything using a Controller instead of an ApiController with the some(?) manual coding. In the end, both controllers build upon the ASP.NET foundation. But having a REST-ful API is such a common requirement today that WebAPI was created to simplify the implementation of a such an API.
It's fairly simple to decide between the two: if you're writing an HTML based web/internet/intranet application - maybe with the occasional AJAX call returning json here and there - stick with MVC/Controller. If you want to provide a data driven/REST-ful interface to a system, go with WebAPI. You can combine both, of course, having an ApiController cater AJAX calls from an MVC page.
To give a real world example: I'm currently working with an ERP system that provides a REST-ful API to its entities. For this API, WebAPI would be a good candidate. At the same time, the ERP system provides a highly AJAX-ified web application that you can use to create queries for the REST-ful API. The web application itself could be implemented as an MVC application, making use of the WebAPI to fetch meta-data etc.

Which would you rather write and maintain?
ASP.NET MVC
public class TweetsController : Controller {
// GET: /Tweets/
[HttpGet]
public ActionResult Index() {
return Json(Twitter.GetTweets(), JsonRequestBehavior.AllowGet);
}
}
ASP.NET Web API
public class TweetsController : ApiController {
// GET: /Api/Tweets/
public List<Tweet> Get() {
return Twitter.GetTweets();
}
}

I love the fact that ASP.NET Core's MVC6 merged the two patterns into one because I often need to support both worlds. While it's true that you can tweak any standard MVC Controller (and/or develop your own ActionResult classes) to act & behave just like an ApiController, it can be very hard to maintain and to test: on top of that, having Controllers methods returning ActionResult mixed with others returning raw/serialized/IHttpActionResult data can be very confusing from a developer perspective, expecially if you're not working alone and need to bring other developers to speed with that hybrid approach.
The best technique I've come so far to minimize that issue in ASP.NET non-Core web applications is to import (and properly configure) the Web API package into the MVC-based Web Application, so I can have the best of both worlds: Controllers for Views, ApiControllers for data.
In order to do that, you need to do the following:
Install the following Web API packages using NuGet: Microsoft.AspNet.WebApi.Core and Microsoft.AspNet.WebApi.WebHost.
Add one or more ApiControllers to your /Controllers/ folder.
Add the following WebApiConfig.cs file to your /App_Config/ folder:
using System.Web.Http;
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Finally, you'll need to register the above class to your Startup class (either Startup.cs or Global.asax.cs, depending if you're using OWIN Startup template or not).
Startup.cs
public void Configuration(IAppBuilder app)
{
// Register Web API routing support before anything else
GlobalConfiguration.Configure(WebApiConfig.Register);
// The rest of your file goes there
// ...
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ConfigureAuth(app);
// ...
}
Global.asax.cs
protected void Application_Start()
{
// Register Web API routing support before anything else
GlobalConfiguration.Configure(WebApiConfig.Register);
// The rest of your file goes there
// ...
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
// ...
}
This approach - together with its pros and cons - is further explained in this post I wrote on my blog.

Quick n Short Answer
If you want to return a view, you should be in "Controller".
Normal Controller - ASP.NET MVC: you deal with normal "Controller" if you are in ASP.net Web Application. You can create Controller-Actions and you can return Views().
ApiController Controller: you create ApiControllers when you are developing ASP.net REST APIs. you can't return Views (though you can return Json/Data for HTML as string). These apis are considered as backend and their functions are called to return data not the view
More Details here

Every method in Web API will return data (JSON) without serialization.
However, in order to return JSON Data in MVC controllers, we will set the returned Action Result type to JsonResult and call the Json method on our object to ensure it is packaged in JSON.

The main difference is: Web API is a service for any client, any devices, and MVC Controller only serve its client. The same because it is MVC platform.

If you create a new web application in latest framework 4.7.2 you will both of them to be configured by default and can build you application on that

In Asp.net Core 3+ Vesrion
Controller: If wants to return anything related to IActionResult & Data also, go for Controllercontroller
ApiController: Used as attribute/notation in API controller. That inherits ControllerBase Class
ControllerBase: If wants to return data only go for ControllerBase class

Related

how to map this route from mvc controller to a web api controller?

We have a mvc project and we would like to move to a web api. The mvc project doesn't have any UI,so it was a mistake to use mvc controller other than a web api controller.
However, our customers access the mvc controller via url such as:
https://mysite.azurewebsites.net/indexes/unit/docs/search (both httppost)
https://mysite.azurewebsites.net/indexes/unit/docs/post (both httppost)
https://mysite.azurewebsites.net/indexes/unit/docs/get
the part unit/docs is actually dynamic (something we send to a database to do some query).
If we move this controller to web api, how can we handle the route as we need to be backward compatible?
in your WebApi controller, do the following:
[route("{controller}")]
public IndexesController : ControllerBase
{
[HttpPost("{unit}/{docs}/{search}")]//or whatever those variables should be
public async Task<IactionResult> Search(string unit, string docs, string search)
{
//Do your stuff
var result = _logic.DoStuff();
return Ok(result);
}
}
There's no reason to move away from MVC controller though. Just always return a JsonResult() and it'll behave exactly like a WebApi from the caller's perspective.

ASP.NET Core MVC consuming Internal Web API without using Http request

I'm using ASP.NET Core MVC and Web API and trying to consume the internal Web API (done using ApiController, prepare for future cross-platform application use), I saw an answer which doesn't need to use HttpClient or any Http Request features to get data from Web API, refer: Consuming web api controller action from mvc controller
I'm trying to do the similar thing, but my auto generated Web API Controller comes with DBContext parameter, which causing me unable to follow what is mentioned from the link.
Below is what i have in my Controller which caused me unable to follow actions mentioned in the link above:
private readonly MyTestDBContext _context;
public MfgProductsController(MyTestDBContext context)
{
_context = context;
}
If the "MyTestDBContext context" parameter supposed to remain, what should I write in my Controller in order to pass the DBContext in?
Or if there's a way to remove "MyTestDBContext context" from the parameter, how the constructor supposed to change to?
Let the container do its job, just add the controller as a dependency in your controller:
public class MyController : Controller
{
public MyController(MfgProductsController productsController)
{
_productsController = productsController;
}
private readonly MfgProductsController _productsController;
}
It should fill all dependencies for you.

Why does .NET Core Web API calls AddMVC() and UseMVC()?

When the scaffold for a .NET core Web API is used it includes:
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
in the ConfigureServices method and
app.UseMvc();
in the Configure method.
Why is this? A web API doesn't need "Model View Controller". It might only need "Model" and "Controller". I relate MVC very much to Views and Razor. Can these declarations be left out?
If we check the source code for the internal AddMvc extension we can see these things clearly:
public static IMvcBuilder AddMvc(this IServiceCollection services)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
var builder = services.AddMvcCore();
builder.AddApiExplorer();
builder.AddAuthorization();
AddDefaultFrameworkParts(builder.PartManager);
// Order added affects options setup order
// Default framework order
builder.AddFormatterMappings();
builder.AddViews();
builder.AddRazorViewEngine();
builder.AddRazorPages();
builder.AddCacheTagHelper();
// +1 order
builder.AddDataAnnotations(); // +1 order
// +10 order
builder.AddJsonFormatters();
builder.AddCors();
return new MvcBuilder(builder.Services, builder.PartManager);
}
In my opinion, for Web API, you probably need AddJSONFormatters() and AddCors(). However, you would also need AddMvcCore(). This includes stuff like routing, attributes, filters, result executors, model binders, controllers etc.
Refer to https://codingblast.com/using-web-api-asp-net-core-without-mvc-specific-stuff/
app.UseMvc() tells your app to add MVC to the request execution
pipeline. This will ensure that all requests to your web application
are routable to the MVC framework, meaning you can use controllers,
views and anything else contained within the MVC implementation
(action filters etc).
if you don't need view functionality then you
Don't create a web API controller by deriving from the Controller class. Controller derives from ControllerBase and adds support for views, so it's for handling web pages, not web API requests. There's an exception to this rule: if you plan to use the same controller for both views and APIs, derive it from Controller. The ControllerBase class provides many properties and methods that are useful for handling HTTP requests.
For more details checkout this link.
https://learn.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-2.2

Is it possible to use ASP.NET Core Web API and Views with Razor and get Intellisense?

If I build a Web API Project in Asp.Net Core 1.x, and I want to build the front-end in the same Project or Solution, is it possible to create front-end pages and use Razor with Visual Studio's Intellisense?
The application is built around an API for public consumption, but since my application will use the same data, I thought it would make sense to consume my own API instead of building separate methods or constructs for API calls vs "regular" MVC (call the controller, gets the model data, return the view). A client will have their own front-end and get the data. I will have my own front-end, but I want it integrated in the same VS Solution.
One downside is I lose my Intellisense because I am building it around consuming the JSON returning from the API. I understand that an API is about returning data, not Views. I'm trying to get the best of all worlds and be more productive with Visual Studio features.
All I have read is older. SO has older question as well. I read a a lot about returning a View with an API, but I'm not sure I want that. I want to do like a normal non-Web API project and API project at the same time.
Is this possible?
My understanding is no/sort of because the whole point of Razor is that it is done on the server and the API is for clients outside your application. In other words, I'd need to build a controller that called my API controllers, so I get Intellisense which seems a bit redundant and harder work on the server.
Some possibilities:
Building REST APIs using ASP.NET Core with Razor syntax
ASP.NEt MVC using Web API to return a Razor view
asp.net mvc consuming asp.net web api end point
EDIT: This seems to be logical, https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/areas
EDIT: Here is what I did, using this as a guide:
https://msdn.microsoft.com/en-us/magazine/mt763233.aspx
I created an Area in my Project. Under this I created the name of an Area and under this I created Controllers, Views (and under this Home).
In my Startup.cs file I added,
app.UseMvc(routes =>
{
routes.MapRoute(name: "areaRoute",
template: "{area:exists}/{controller=Home}/{action=Index}");
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}");
});
The URL is localhost:port/AreaName
From within my Controller, I was able to reuse the services from my Service Layer, an abstraction I had decided on earlier in the project.
namespace books.Areas.Controllers
{
[Area("Books")]
public class HomeController : Controller
{
private readonly AppSettings _appSettings;
public HomeController(Microsoft.Extensions.Options.IOptions<AppSettings> appSettings)
{
_appSettings = appSettings.Value;
}
// GET: /<controller>/
public IActionResult Index()
{
var myConn = _appSettings.ConnectionString;
var getBooks = new BookLoanService(myConn);
return View(getBooks.GetAll());
}
}
}
This is the same Service Layer my API controller uses. The Service Layer has (I am using Dapper),
public List<books> GetAll()
{
using (IDbConnection db = new SqlConnection(_connectionString))
{
string SqlString = "SELECT TOP 5 last_name, first_name FROM books";
var myBooks = (List<books>)db.Query<books>(SqlString);
return myBooks ;
}
}
Once I was able to get my types, I was able to use Razor in my Index in my Area:
#model System.Collections.Generic.List<books>
#{
}
<html>
<body>
#foreach(var person in Model)
{
<ul><li>#person.last_name</li></ul>
}
</body>
</html>
Without modification, I am still able to use my api/values type of URL to get to my API, and I will be able to refresh part of my page after that initial server rendering by calling the API via Ajax.

Using Web Api in a MVC Controller

Is it possible to use/call my Web API methods inside a MVC controller?
I have a Web Api to use in mobile and others plattaforms and I´m developing a .NET Mvc Website.
Does that architecture makes sense?
Thanks
Yes it's possible although if you're expecting to consume your API from a number of different clients I would suggest you create your API as a separate application that can then be managed/scaled accordingly.
Essentially you are referring to "dog-fooding" your own API, making your own web application no different to any other client.
We do something similar and have our MVC application call our API (using HttpClient). We also have a lot of client side code within the same application that calls the API directly using CORS.
We've had this architecture running in production for 2 years now without any issue.
Here is How I call my Web API controller from MVC controller:
public class invoiceController : ApiController
{
private myEntities db = new db1Entities();
// GET api/invoices
public IQueryable<invoices> Getinvoices()
{
return db.invoices;
}
}
inside separate MVC controller:
public ActionResult ShowInvoices()
{
var webApi = new invoicesController();
//this must return strongly typed object
var myarray = webApi.Getinvoices();
return View(myarray);
}

Resources