Language

MVC Music Store Sample Application

By Cephas Lin|
Important: Visual Studio "14" CTP introduces tooling support for ASP.NET vNext. You do not need Visual Studio "14" CTP to run the samples, but if you want to work with Music Store vNext project in Visual Studio, you must first install Visual Studio "14" CTP. For information on working with the vNext project in Visual Studio "14" CTP, see Getting Started with ASP.NET vNext and Visual Studio "14".

Welcome to the MVC Music Store application written for ASP.NET vNext!

Here you can explore how an existing ASP.NET MVC 5 application is rewritten to be run on ASP.NET vNext. Much of the MVC 6 functionality is still being finalized, but you can get your hands dirty with ASP.NET vNext in this sample application by learning how things are changing, as well as see some new features in action.

You can run Music Store using Visual Studio "14" CTP or from the command line. For details on how to run the sample, please see the readme at https://github.com/aspnet/MusicStore.

Let’s get started.

Overview

The MVC Music Store is a lightweight sample store implementation which sells music albums online, and implements basic site administration, user sign-in, and shopping cart functionality.

The sample includes several projects:

  • MusicStore  Contains all the project files for the MusicStore application written for MVC 6.
  • MusicStore.Spa  Contains a single-page application (SPA) implementation of MusicStore using MVC 6.
  • MvcMusicStore  Contains the MVC 5 version of MusicStore. It’s included here for you to conveniently compare with the MVC 6 version.
  • MvcMusicStore.Spa  Contains a SPA implementation of MvcMusicStore using MVC 5.

You will also find command line scripts for running the MVC 6 application.

Project Highlights

Notice first that the folder structure looks very similar to the ASP.NET MVC Web applications that you’re used to, with controllers and views. The Views folder even has the same folder structure as seen in earlier ASP.NET MVC versions. However, the project has the following changes:

  • There is no longer Global.asax
  • .NET Framework and project dependencies are defined in project.json
  • Application configuration such as HTTP services (such as MVC) and database settings are hooked up in the Startup.cs file
  • There is also a Program.cs file for running MusicStore as a console application

When running MusicStore as a Web application, The ASP.NET vNext runtime looks for a Startup class with the following method signature to configure the Web application:

public void Configure(IApplicationBuilder app) {}

When running MusicStore as a console application, the following code in Program.cs likewise looks for the same Startup class to configure the Web application:

var engine = services.GetService<IHostingEngine>();

Code Highlights

Startup.cs

In ASP.NET vNext, Web applications are no longer dependent on System.Web namespaces. This change enables you to slim down your Web applications, so that you can add only the HTTP services you need to the application deployment, making your application as lean and fast as possible.

Open <root>\src\MusicStore\Startup.cs in a text editor or Visual Studio. In the app.UseServices method invocation, find the following line:

services.AddMvc();

This line adds MVC 6 to the application. Look up a few lines and down a few lines to see that services such as configuration, logging, Entity Framework, and ASP.NET Identity are added in the same fashion. Other than that, no other HTTP services are added to run this particular application.

Then, find the following lines of code:

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller}/{action}/{id?}",
        defaults: new { controller = "Home", action = "Index" });

    routes.MapRoute(
        name: "api",
        template: "{controller}/{id?}");
});

This is where you can add more routes to your Web application.

Coding Pattern for Multiple Environments

Go back to the top of <root>\src\MusicStore\Startup.cs and find the following code snippet:

var configuration = new Configuration();
configuration.AddJsonFile("LocalConfig.json");
configuration.AddEnvironmentVariables(); 
services.AddInstance<IConfiguration>(configuration);

This snippet demonstrates a new coding pattern possible in ASP.NET vNext that you can use to code once and deploy to multiple environments. When you develop your application locally, you can use application settings present in a local configuration file, such as LocalConfig.json in this case. But when you publish this application to an Azure website, the line

configuration.AddEnvironmentVariables();

causes the settings defined in Azure to override the previously set values (set by configuration.AddJsonFile). In this way, you can make your application work in both your development environment and your deployment environment without changing your code.

No System.Web.* Dependencies

Open <root>\src\MusicStore\Controllers\HomeController.cs. The controller code is still the same as in previous versions, except that you don’t see any reference to the namespaces System.Web and System.Web.* any more, as mentioned previously. In place of System.Web.Mvc, you find Microsoft.AspNet.Mvc.

using Microsoft.AspNet.Mvc;
using MusicStore.Models;
using System.Collections.Generic;
using System.Linq;

View Components

In MVC 6, the new way for adding reusable components is called View Components. View components are functionally equivalent to child actions in previous MVC versions, but now separates the concept from controller action invocation. Let's compare the MusicStore code between MVC 5 and MVC 6.

First, let's look at how this is done in MVC 5. In the MvcMusicStore project, which is the MusicStore application before being rewritten for ASP.NET vNext, open <root>\src\MvcMusicStore\Controllers\ShoppingCartController.cs and find the CartSummary action method. See that it is decorated with ChildActionOnly and returns the CartSummary partial view.

[ChildActionOnly]
public ActionResult CartSummary()
{
    var cart = ShoppingCart.GetCart(_storeContext, this);
 
    var cartItems = cart.GetCartItems()
        .Select(a => a.Album.Title)
        .OrderBy(x => x)
        .ToList();

    ViewBag.CartCount = cartItems.Count();
    ViewBag.CartSummary = string.Join("\n", cartItems.Distinct());
 
    return PartialView("CartSummary");
}

Reference that with Views\Shared\_Layout.cshtml where you’ll find how the child action gets invoked:

@Html.Action("CartSummary", "ShoppingCart")

Now let's look at the MVC 6 version. Open the file <root>\src\MusicStore\Components\CartSummaryComponent.cs and note that this same reusable component is now no longer part of the controller action invocation, but is now its own class, which inherits ViewComponent.

[ViewComponent(Name = "CartSummary")]
public class CartSummaryComponent : ViewComponent
{
    ...
}

Reference that with Views\Shared\_Layout.cshtml where you’ll find how the view component gets invoked:

@await Component.InvokeAsync("CartSummary")

Claims Authorization

Also new in MVC 6 is a claims-enabled authorization filter. Open <root>\src\MusicStore\Controllers\StoreManagerController.cs and see the following decoration for the StoreManagerController class:

[Authorize("ManageStore", "Allowed")]

This decoration authorizes any claims principal that has a claim with the type of ManageStore and the value of Allowed.

To see how the site administrator acquires this claim, open Startup.cs and find the following line in the CreateAdminUser method:

await userManager.AddClaimAsync(user, new Claim("ManageStore", "Allowed"));

Additional Resources

This article was originally created on June 3, 2014

Author Information

Cephas Lin

Cephas Lin – Cephas Lin is a senior programming writer at Microsoft and writes content for ASP.NET technologies. He has previously written solutions content for Microsoft data and cloud platforms, including SQL Server, SharePoint, and Windows Azure.