Strongly-Typed Configuration in ASP.NET Core MVC

Over the last two posts I worked through the basics of configuration in ASP.NET and how to leverage structured data in your JSON config files. Now it’s time to take a deeper look at how to access relevant parts of your configuration throughout the rest of your project.

Strongly-Typed Settings Classes in ASP.NET Core

Feature Folders in ASP.net Core MVC 1

Feature folders provide an alternative, and possibly better approach to arranging your code inside of an MVC project.

JSON Configuration in ASP.NET Core MVC

Structured data in earlier versions of ASP.NET meant creating and registering custom types and configuration sections for our applications. In ASP.NET Core and in Core MVC, structured configuration is a breeze with support for JSON documents as the storage mechanism and the ability to flatten hierarchies into highly portable keys.

Structured JSON Configuration

ASP.net vNext is now ASP.net 5 is now ASP.net Core 1.0

Did you hear the news? ASP.NET 5 is dead it is now called ASP.NET Core 1.0. The name for this next generation of ASP.net(that’s the capitalization I’m using because this isn’t your grandmother typing in YAHOO.COM) has been up in the air for a while. We first heard the real details about ASP.net vNext at the MVP summit in 2014 and the first question on everybody’s mind was “what it was going to be called?”. At the time there wasn’t a decision on that.

Configuration in ASP.NET Core MVC

Config in Startup.cs

ASP.NET Core MVC introduces a new configuration system that adds flexibility and simultaneously enables cross-platform support (in a way that makes sense on other platforms). In this post we’re going to cover the basics of configuration and what you can expect as you look at the project template from File -> New Project in Visual Studio 2015.

Grrr, Rowr - The Monsters are Here

The ASP.NET Monsters are here to explain everything they know about ASP.NET Core and the new version of the MVC Framework, known as ASP.NET Core MVC. Once or so per week Dave, James and Simon publish a new, short video about some aspect of ASP.net in their own, monstrous, style.

Watch the Videos

Our monsterific videos are hosted on Channel 9, and you can view the entire list here, or start watching from the beginning below.

Meet The Monsters.

Goodbye Child Actions, Hello View Components

Originally posted to: http://www.davepaquette.com/archive/2016/01/02/goodbye-child-actions-hello-view-components.aspx

In previous versions of MVC, we used Child Actions to build reusable components / widgets that consisted of both Razor markup and some backend logic. The backend logic was implemented as a controller action and typically marked with a [ChildActionOnly] attribute. Child actions are extremely useful but as some have pointed out, it is easy to shoot yourself in the foot.

Child Actions do not exist in MVC 6. Instead, we are encouraged to use the new View Component feature to support this use case. Conceptually, view components are a lot like child actions but they are a lighter weight and no longer involve the lifecycle and pipeline related to a controller. Before we get into the differences, let’s take a look at a simple example.

A simple View Component

View components are made up of 2 parts: A view component class and a razor view.

To implement the view component class, inherit from the base ViewComponent and implement an Invoke or InvokeAsync method. This class can be anywhere in your project. A common convention is to place them in a ViewComponents folder. Here is an example of a simple view component that retrieves a list of articles to display in a What’s New section.

namespace MyWebApplication.ViewComponents
{
public class WhatsNewViewComponent : ViewComponent
{
private readonly IArticleService _articleService;
public WhatsNewViewComponent(IArticleService articleService)
{
_articleService = articleService;
}
public IViewComponentResult Invoke(int numberOfItems)
{
var articles = _articleService.GetNewArticles(numberOfItems);
return View(articles);
}
}
}

Much like a controller action, the Invoke method of a view component simply returns a view. If no view name is explicitly specified, the default Views\Shared\Components\ViewComponentName\Default.cshtml is used. In this case, Views\Shared\Components\WhatsNew\Default.cshtml. Note there are a ton of conventions used in view components. I will be covering these in a future blog post.

Views\Shared\Components\WhatsNew\Default.cshtml
@model IEnumerable<Article>
<h2>What's New</h2>
<ul>
@foreach (var article in Model)
{
<li><a asp-controller="Article"
asp-action="View"
asp-route-id="@article.Id">@article.Title</a></li>
}
</ul>

To use this view component, simply call @Component.Invoke from any view in your application. For example, I added this to the Home/Index view:

Views\Home\Index.cshtml
<div class="col-md-3">
@Component.Invoke("WhatsNew", 5)
</div>

The first parameter to @Component.Invoke is the name of the view component. Any additional parameters will be passed to the Invoke method that has a matching signature. In this case, we specified a single int, which matches the Invoke(int numberOfItems) method of the WhatsNewViewComponent class.

What's New View Component

How is this different?

So far this doesn’t really look any different from what we had with Child Actions. There are however some major differences here.

No Model Binding

With view components, parameters are passed directly to your view component when you call @Component.Invoke() or @Component.InvokeAsync() in your view. There is no model binding needed here since the parameters are not coming from the HTTP request. You are calling the view component directly using C#. No model binding means you can have overloaded Invoke methods with different parameter types. This is something you can’t do in controllers.

No Action Filters

View components don’t take part in the controller lifecycle. This means you can’t add action filters to a view component. While this might sound like a limitation, it is actually an area that caused problems for a lot of people. Adding an action filter to a child action would sometimes have unintended consequences when the child action was called from certain locations.

Not reachable from HTTP

A view component never directly handles an HTTP request so you can’t call directly to a view component from the client side. You will need to wrap the view component with a controller if your application requires this behaviour.

What is available?

Common Properties

When you inherit from the base ViewComponent class, you get access to a few properties that are very similar to controllers:

[ViewComponent]
public abstract class ViewComponent
{
protected ViewComponent();
public HttpContext HttpContext { get; }
public ModelStateDictionary ModelState { get; }
public HttpRequest Request { get; }
public RouteData RouteData { get; }
public IUrlHelper Url { get; set; }
public IPrincipal User { get; }
[Dynamic]
public dynamic ViewBag { get; }
[ViewComponentContext]
public ViewComponentContext ViewComponentContext { get; set; }
public ViewContext ViewContext { get; }
public ViewDataDictionary ViewData { get; }
public ICompositeViewEngine ViewEngine { get; set; }
//...
}

Most notably, you can access information about the current user from the User property and information about the current request from the Request property. Also, route information can be accessed from the RouteData property. You also have the ViewBag and ViewData. Note that the ViewBag / ViewData are shared with the controller. If you set ViewBag property in your controller action, that property will be available in any ViewComponent that is invoked by that controller action’s view.

Dependency Injection

Like controllers, view components also take part in dependency injection so any other information you need can simply be injected to the view component. In the example above, we injected the IArticleService that allowed us to access articles form some remote source. Anything that you could inject into a controller can also be injected into a view component.

Wrapping it up

View components are a powerful new feature for creating reusable widgets in MVC 6. Consider using View Components any time you have complex rendering logic that also requires some backend logic.

Special Guests on The Monsters

Guests from the ASP.NET Community

Without a diverse set of folks working in the web space, I think we could all agree that web development would be a lot less interesting. We are fortunate to have some of the community’s best and brightest thinkers join us to chat here on the Monsters.


Jon Galloway
Episode 79: ASP.NET Core Code Labs Nov 17, 2016


Christopher Anderson
Episode 78: Azure Functions Nov 15, 2016


Darrel Miller
Episode 61: Building APIs Aug 25, 2016


Taylor Mullen
Episode 59: The Razor View Engine Aug 18, 2016


Jeffery Palermo
Episode 55: Moving the Business to ASP.NET Core Aug 4, 2016


Eric Flemming
Episode 53: Basics of Web API July 28, 2016


Julie Lerman
Episode 47: The State of EF Core July 8, 2016


Mads Kristensen
Episode 43: Hello Bundler Minifier June 23, 2016


Maixime Rouiller
Episode 42: Goodbye to Gulp June 21, 2016


Complex Custom Tag Helpers in MVC 6

In a previous blog post we talked about how to create a simple tag helper in MVC 6. In today’s post we take this one step further and create a more complex tag helper that is made up of multiple parts.

ApiController in ASP.NET 5? Nopesauce.

If you’re developing in ASP.NET Web API you are familiar with the concept of inheriting from the base ApiController class. This class is still around in ASP.NET 5, but it is likely not meant for you to use.  Here’s why your cheese has moved.