In this blog post, I want to show you the difference between the ASP.NET Core methods AddMvc() and AddMvcCore() when working with ASP.NET Core.

ASPNETCore-WebAPI-Sample

Startup.cs

When creating an ASP.NET Core Web API you often see a Startup.cs file to configure your services and configure your pipeline. That's what the methods ConfigureServices(IServiceCollection services) and Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) are for.

ConfigureServices is preparing your services for being used as you configure them.

This is also the place to add dependency injection, but that is a separate topic.

You can have a lot of configuration in here but we want to focus on the main point: adding the mvc framework.

When starting with “File” –> “New Project” in Visual Studio the default setting in the method is AddMvc() . And it works straight away. Let's take a look:

public void ConfigureServices(IServiceCollection services) { // ... services.AddMvc(); }

Now, when an API with Controllers kicks in we can consume it like normal.

dotnet run makes the API work on localhost:5000

GET localhost:5000/api/house

brings:

[ { "id": 1, "street": "Street1", "city": "Town1", "zipCode": 1234 }, { "id": 2, "street": "Street2", "city": "Town2", "zipCode": 1234 }, { "id": 3, "street": "Street3", "city": "Town3", "zipCode": 1234 }, { "id": 4, "street": "Street4", "city": "Town4", "zipCode": 1234 } ]

What happens, if we change AddMvc() to AddMvcCore() ?

public void ConfigureServices(IServiceCollection services) { // ... services.AddMvcCore(); }

Let's run the same command again:

GET localhost:5000/api/house

now brings a 406 error saying “Not Acceptable.”

If we check the console which hosts the web API we see more information about this error:

warn: Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor[1]No output formatter was found for content type ‘’ to write the response.

So we deactivated something we should not have deactivated ;-).

The error says that we do not have an output formatter which can parse our output. Even if we add an 'accept' header in the request like Accept: application/json we would get the same error message because the server does not know how to handle the response.

Let's take a closer look at what is the real difference between AddMvc() and AddMvcCore() .

Due to the fact that the framework is an open source we can take a look at the sources:

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.AddCacheTagHelper(); // +1 order builder.AddDataAnnotations(); // +1 order // +10 order builder.AddJsonFormatters(); builder.AddCors(); return new MvcBuilder(builder.Services, builder.PartManager); }

MvcServiceCollectionExtensions.cs tells us that we are adding the complete MVC Services needed in order to get the whole MVC functionality.

It is adding Authorization, the RazorViewEngine, and the JsonFormatters we need to get our output going. And most interesting it is also calling the AddMvcCore() method itself.

So if we use the AddMvc() method we get the ability to render view with razor and so on.

Let's have a look at AddMvcCore() on the other hand:

MvcCoreServiceCollectionExtensions.cs

public static IMvcCoreBuilder AddMvcCore(this IServiceCollection services) { if (services == null) { throw new ArgumentNullException(nameof(services)); } var partManager = GetApplicationPartManager(services); services.TryAddSingleton(partManager); ConfigureDefaultFeatureProviders(partManager); ConfigureDefaultServices(services); AddMvcCoreServices(services); var builder = new MvcCoreBuilder(services, partManager); return builder; }

This method is a lot shorter and only adding the basic things to get started. Both methods, however, are returning an IMvcCoreBuilder. Interesting is the AddMvcCoreServices(services); method which is adding the ability to return FileContents, RedirectToRouteResults, ActionResolvers, use Controllers, use routing, and so on. Really basic functionality.

So when using AddMvcCore() we have to add everything by ourselves. This means that we only have what we really want in our application, thus getting rid of needless functionalities, like razor functionality for example.

Now that we know the difference between those two methods, how can we get our web API going again? We still have the error and we cannot return any data.

We can fix that by simply telling ASP.NET that it should use JsonFormatters like:

public void ConfigureServices(IServiceCollection services) { // ... // Add framework services. services.AddMvcCore().AddJsonFormatters(); }

If we now call our GET localhost:5000/api/house again we should see the output as json like we expected.

I hope this clarified a bit what is the main difference between AddMvc() and AddMvcCore().

Best regards,

Fabian