Manage client-side packages with Bower in ASP.NET Core
By Rick Anderson, Noel Rice, and Scott Addie
Bower calls itself “A package manager for the web.” Within the .NET ecosystem, it fills the void left by NuGet’s inability to deliver static content files. For ASP.NET Core projects, these static files are inherent to client-side libraries like jQuery and Bootstrap. For .NET libraries, you still use NuGet package manager.
New projects created with the ASP.NET Core project templates set up the client-side build process. jQuery and Bootstrap are installed, and Bower is supported.
Client-side packages are listed in the bower.json file. The ASP.NET Core project templates configures bower.json with jQuery, jQuery validation, and Bootstrap.
In this tutorial, we’ll add support for Font Awesome. Bower packages can be installed with the Manage Bower Packages UI or manually in the bower.json file.
Installation via Manage Bower Packages UI
Create a new ASP.NET Core Web app with the ASP.NET Core Web Application (.NET Core) template. Select Web Application and No Authentication.
Right-click the project in Solution Explorer and select Manage Bower Packages (alternatively from the main menu, Project > Manage Bower Packages).
In the Bower: <project name> window, click the “Browse” tab, and then filter the packages list by entering
font-awesome
in the search box:
- Confirm that the “Save changes to bower.json” checkbox is checked. Select a version from the drop-down list and click the Install button. The Output window shows the installation details.
Manual installation in bower.json
Open the bower.json file and add “font-awesome” to the dependencies. IntelliSense shows the available packages. When a package is selected, the available versions are displayed. The images below are older and will not match what you see.
Bower uses semantic versioning to organize dependencies. Semantic versioning, also known as SemVer, identifies packages with the numbering scheme <major>.<minor>.<patch>. IntelliSense simplifies semantic versioning by showing only a few common choices. The top item in the IntelliSense list (4.6.3 in the example above) is considered the latest stable version of the package. The caret (^) symbol matches the most recent major version and the tilde (~) matches the most recent minor version.
Save the bower.json file. Visual Studio watches the bower.json file for changes. Upon saving, the bower install command is executed. See the Output window’s Bower/npm view for the exact command executed.
Open the .bowerrc file under bower.json. The directory
property is set to wwwroot/lib which indicates the location Bower will install the package assets.
You can use the search box in Solution Explorer to find and display the font-awesome package.
Open the Views_Layout.cshtml file and add the font-awesome CSS file to the environment (xref:)Tag Helper for Development
. From Solution Explorer, drag and drop font-awesome.css inside the <environment names="Development">
element.
[!code-htmlMain]
1: @inject Microsoft.ApplicationInsights.AspNetCore.JavaScriptSnippet JavaScriptSnippet
2: <!DOCTYPE html>
3: <html>
4: <head>
5: <meta charset="utf-8" />
6: <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7: <title>@ViewData["Title"] - WebBowerDemo</title>
8:
9: <environment names="Development">
10: <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
11: <link rel="stylesheet" href="~/css/site.css" />
12: <link href="~/lib/font-awesome/css/font-awesome.css" rel="stylesheet" />
13: </environment>
14: <environment names="Staging,Production">
15: <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
16: asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
17: asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
18: <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
19: <link href="~/lib/font-awesome/css/font-awesome.min.css" rel="stylesheet" />
20: </environment>
21: @Html.Raw(JavaScriptSnippet.FullScript)
22: </head>
23: <body>
24: <nav class="navbar navbar-inverse navbar-fixed-top">
25: <div class="container">
26: <div class="navbar-header">
27: <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
28: <span class="sr-only">Toggle navigation</span>
29: <span class="icon-bar"></span>
30: <span class="icon-bar"></span>
31: <span class="icon-bar"></span>
32: </button>
33: <a asp-area="" asp-controller="Home" asp-action="Index" class="navbar-brand">WebBowerDemo</a>
34: </div>
35: <div class="navbar-collapse collapse">
36: <ul class="nav navbar-nav">
37: <li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
38: <li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
39: <li><a asp-area="" asp-controller="Home" asp-action="Contact">Contact</a></li>
40: </ul>
41: </div>
42: </div>
43: </nav>
44: <div class="container body-content">
45: @RenderBody()
46: <hr />
47: <footer>
48: <p>© 2017 - WebBowerDemo</p>
49: </footer>
50: </div>
51:
52: <environment names="Development">
53: <script src="~/lib/jquery/dist/jquery.js"></script>
54: <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
55: <script src="~/js/site.js" asp-append-version="true"></script>
56: </environment>
57: <environment names="Staging,Production">
58: <script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.1.1.min.js"
59: asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
60: asp-fallback-test="window.jQuery"
61: crossorigin="anonymous"
62: integrity="sha384-K+ctZQ+LL8q6tP7I94W+qzQsfRV2a+AfHIi9k8z8l9ggpc8X+Ytst4yBo/hH+8Fk">
63: </script>
64: <script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"
65: asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
66: asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
67: crossorigin="anonymous"
68: integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa">
69: </script>
70: <script src="~/js/site.min.js" asp-append-version="true"></script>
71: </environment>
72:
73: @RenderSection("Scripts", required: false)
74: </body>
75: </html>
In a production app you would add font-awesome.min.css to the environment tag helper for Staging,Production
.
Replace the contents of the Views.cshtml Razor file with the following markup:
[!code-htmlMain]
1: @{
2: ViewData["Title"] = "About";
3: }
4:
5: <div class="list-group">
6: <a class="list-group-item" href="#"><i class="fa fa-home fa-fw" aria-hidden="true"></i> Home</a>
7: <a class="list-group-item" href="#"><i class="fa fa-book fa-fw" aria-hidden="true"></i> Library</a>
8: <a class="list-group-item" href="#"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i> Applications</a>
9: <a class="list-group-item" href="#"><i class="fa fa-cog fa-fw" aria-hidden="true"></i> Settings</a>
10: </div>
Run the app and navigate to the About view to verify the font-awesome package works.
Exploring the client-side build process
Most ASP.NET Core project templates are already configured to use Bower. This next walkthrough starts with an empty ASP.NET Core project and adds each piece manually, so you can get a feel for how Bower is used in a project. You can see what happens to the project structure and the runtime output as each configuration change is made.
The general steps to use the client-side build process with Bower are:
- Define packages used in your project.
- Reference packages from your web pages.
Define packages
Once you list packages in the bower.json file, Visual Studio will download them. The following example uses Bower to load jQuery and Bootstrap to the wwwroot folder.
Create a new ASP.NET Core Web app with the ASP.NET Core Web Application (.NET Core) template. Select the Empty project template and click OK.
In Solution Explorer, right-click the project > Add New Item and select Bower Configuration File. Note: A .bowerrc file is also added.
Open bower.json, and add jquery and bootstrap to the
dependencies
section. The resulting bower.json file will look like the following example. The versions will change over time and may not match the image below.
[!code-jsonMain]
1: {
2: "name": "asp.net",
3: "private": true,
4: "dependencies": {
5: "jquery": "3.1.1",
6: "bootstrap": "3.3.7"
7: }
8: }
- Save the bower.json file.
Verify the project includes the bootstrap and jQuery directories in wwwroot/lib. Bower uses the .bowerrc file to install the assets in wwwroot/lib.
Note: The “Manage Bower Packages” UI provides an alternative to manual file editing.
Enable static files
- Add the
Microsoft.AspNetCore.StaticFiles
NuGet package to the project. - Enable static files to be served with the Static file middleware. Add a call to UseStaticFiles to the
Configure
method ofStartup
.
[!code-csharpMain]
1: using Microsoft.AspNetCore.Builder;
2: using Microsoft.AspNetCore.Hosting;
3: using Microsoft.AspNetCore.Http;
4:
5: public class Startup
6: {
7: public void Configure(IApplicationBuilder app)
8: {
9: app.UseStaticFiles();
10:
11: app.Run(async (context) =>
12: {
13: await context.Response.WriteAsync("Hello World!");
14: });
15: }
16: }
17:
Reference packages
In this section, you will create an HTML page to verify it can access the deployed packages.
- Add a new HTML page named Index.html to the wwwroot folder. Note: You must add the HTML file to the wwwroot folder. By default, static content cannot be served outside wwwroot. See (xref:)Working with static files for more information.
Replace the contents of Index.html with the following markup:
[!code-htmlMain]
1: <!DOCTYPE html>
2: <html>
3: <head>
4: <meta charset="utf-8" />
5: <title>Bower Example</title>
6: <link href="lib/bootstrap/dist/css/bootstrap.css" rel="stylesheet" />
7: </head>
8: <body>
9: <div class="jumbotron">
10: <h1>Using the jumbotron style</h1>
11: <p>
12: <a class="btn btn-primary btn-lg" role="button">Stateful button</a>
13: </p>
14: </div>
15: <script src="lib/jquery/dist/jquery.js"></script>
16: <script src="lib/bootstrap/dist/js/bootstrap.js"></script>
17: <script>
18: $(".btn").click(function () {
19: $(this).text('loading')
20: .delay(1000)
21: .queue(function () {
22: $(this).text('reset');
23: $(this).dequeue();
24: });
25: });
26: </script>
27: </body>
28:
29: </html>
- Run the app and navigate to
http://localhost:<port>/Index.html
. Alternatively, with Index.html opened, pressCtrl+Shift+W
. Verify that the jumbotron styling is applied, the jQuery code responds when the button is clicked, and that the Bootstrap button changes state.
|