ASP.NET MVC 6 with JSPM and Material Design Lite

This article has already published at codeproject.

Introduction

ASP.NET MVC 6.0 just released in couples of months and brought to us a lot of new things. The front-end development is also improved by the time until Visual Studio 2015 released. I have been working on NodeJs for some of projects, and finding that NodeJs really good for front-end side (some cases, it is also good for back-end with MEAN stack). It makes us develop new projects very quick and ton of plugins in NodeJs community also amazing. When I come back to .NET world, a lot of cool things make me feel very comfortable when writing code. ASP.NET MVC 6.0 supported NPM and Bower build-in packages when we created a solution. It is good, all of us know that.

Besides that ES 2015 (ES6) is using by many companies at the moment. So that makes me feel excited to use it in ASP.NET MVC 6.0 solution. Up to now, everyone usually use Babel or Traceur to make it works like a charm (polyfill), and with JSPM you can do event more.

By default ASP.NET MVC 6.0 will let you use Twitter Bootstrap to layout and develop the UI very easy. But Material Design methodology from Google is just awesome.

So talk too much, I will show you how can we make it in one solution.

Prepare software and tools

  • Visual Studio 2015 Community
  • .NET 4.6 (1.0.0-beta5)
  • ASP.NET MVC 6.0
  • NodeJS v0.12.7
  • JSPM v0.15.7
  • Gulp v3.8.11

Source code

You can find out all of the source codes in my github.

Create solution

Open Visual Studio 2015 Community, then create a File -> New -> Project, and choose Web -> .NET 4.6 and then just create a web solution. After the solution created, we are just simple removing the bower.json file, because we don't want to use bower anymore.

Init JSPM

Open command line and change path to the project you just created. Then we type

jspm init

and we will let the JSPM guide us to create a JSPM config, but make sure we point the JSPM path into

wwwroot\lib

The whole package.json file will be like this

{
  "name": "MazWebApp",
  "version": "0.0.0",
  "devDependencies": {
    "gulp": "3.8.11",
    "gulp-concat": "2.5.2",
    "gulp-cssmin": "0.1.7",
    "gulp-uglify": "1.2.0",
    "rimraf": "2.2.8"
  },
  "jspm": {
    "directories": {
      "baseURL": "wwwroot",
      "packages": "wwwroot/lib"
    },
    "dependencies": {
      "hammer": "github:hammerjs/hammer.js@^2.0.4",
      "ixisio/bootstrap-touch-carousel": "github:ixisio/bootstrap-touch-carousel@^0.8.0",
      "jquery": "github:components/jquery@^2.1.4",
      "jquery-validation": "github:jzaefferer/jquery-validation@^1.14.0",
      "jquery-validation-unobtrusive": "github:aspnet/jquery-validation-unobtrusive@^3.2.2"
    },
    "devDependencies": {
      "babel": "npm:babel-core@^5.1.13",
      "babel-runtime": "npm:babel-runtime@^5.1.13",
      "core-js": "npm:core-js@^0.9.4"
    }
  }
}

JSPM also create a config.js file inside ./wwwrooot folder.

If you don't know how to install the JSPM package, please starting at here.

Put Material Design Lite (MDL) into our solution

This is a step that we will bring MDL into our world. Open the \Views\Shared\_Layout.cshtml file, and put

<!-- Material Design Lite -->
<script src="https://storage.googleapis.com/code.getmdl.io/1.0.4/material.min.js"></script>
<link rel="stylesheet" href="https://storage.googleapis.com/code.getmdl.io/1.0.4/material.indigo-pink.min.css">
<!-- Material Design icon font -->
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">

I don't use JSPM to install MDL because I want to point directly to Google CDN, but if you want you can install by using JSPM and another things are the same.

At the bottom of this file, we need to put some scripts like

<script src="~/lib/system.js" type="text/javascript"></script>
<script src="~/config.js" type="text/javascript"></script>
<script>
    System.import("js/site").catch(console.log.bind(console));
</script>

That is it. Now we can layout our UI using MDL. The layout should be

<!DOCTYPE html>

<html>
<head>
    <meta charset="utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="description" content="Magazine Website, a simple website about magazines.">
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>@ViewData["Title"] - Magazine Website</title>

    <!-- Material Design Lite -->
    <script src="https://storage.googleapis.com/code.getmdl.io/1.0.4/material.min.js"></script>
    <link rel="stylesheet" href="https://storage.googleapis.com/code.getmdl.io/1.0.4/material.indigo-pink.min.css">
    <!-- Material Design icon font -->
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">

    <link rel="stylesheet" href="~/css/site.css"/>
</head>
<body>
<div class="mdl-layout mdl-js-layout">
    <header class="mdl-layout__header mdl-layout__header--waterfall">
        <!-- Top row, always visible -->
        <div class="mdl-layout__header-row">
            <!-- Title -->
            <span class="mdl-layout-title">Magazine Website</span>
            <div class="mdl-layout-spacer"></div>
            <div class="mdl-textfield mdl-js-textfield mdl-textfield--expandable
                mdl-textfield--floating-label mdl-textfield--align-right">
                <label class="mdl-button mdl-js-button mdl-button--icon"
                       for="waterfall-exp">
                    <i class="material-icons">search</i>
                </label>
                <div class="mdl-textfield__expandable-holder">
                    <input class="mdl-textfield__input" type="text" name="sample"
                           id="waterfall-exp"/>
                </div>
            </div>
        </div>

    </header>

    <div class="mdl-layout__drawer">
        <span class="mdl-layout-title">Magazine Website</span>
        <nav class="mdl-navigation">
            <a asp-controller="Home" asp-action="Index" class="mdl-navigation__link">Home</a>
            <a asp-controller="Home" asp-action="About" class="mdl-navigation__link">About</a>
            <a asp-controller="Home" asp-action="Contact" class="mdl-navigation__link">Contact</a>
            <hr/>
            @await Html.PartialAsync("_LoginPartial")
        </nav>
    </div>

    <main class="mdl-layout__content">
        <div class="mdl-grid page-content">
            @RenderBody()
        </div>
    </main>

    <footer class="mdl-mini-footer">
        <div class="mdl-mini-footer--left-section">
            <p>&copy; 2015 - MazWebApp</p>
        </div>
    </footer>
</div>

<script src="~/lib/system.js" type="text/javascript"></script>
<script src="~/config.js" type="text/javascript"></script>
<script>
    System.import("js/site").catch(console.log.bind(console));
</script>
@RenderSection("scripts", false)
</body>
</html>

The code above is only for main layout in this website (looks like Master Page in web form). 

Register page marks up like below

<div class="mdl-cell mdl-cell--12-col">
    <form asp-controller="Account"
          asp-action="Register"
          method="post" 
          role="form">
        <div class="mdl-grid page-container">
            <div class="mdl-cell mdl-cell--12-col page-row">
                <h3 class="page-title">Create a new account</h3>
                <hr>
                <div asp-validation-summary="ValidationSummary.All"></div>
            </div>
            <div class="mdl-cell mdl-cell--6-col page-row">
                <div class="mdl-grid page-container">
                    <div class="mdl-cell mdl-cell--12-col page-row">
                        <div class="mdl-textfield mdl-js-textfield mdl-cell mdl-cell--12-col">
                            <label asp-for="Email" class="mdl-textfield__label"></label>
                            <input asp-for="Email" class="mdl-textfield__input"/>
                            <span asp-validation-for="Email" class="mdl-textfield__error"></span>
                        </div>
                    </div>
                    <div class="mdl-cell mdl-cell--12-col page-row">
                        <div class="mdl-textfield mdl-js-textfield mdl-cell mdl-cell--12-col">
                            <label asp-for="Password" class="mdl-textfield__label"></label>
                            <input asp-for="Password" class="mdl-textfield__input"/>
                            <span asp-validation-for="Password" class="mdl-textfield__error"></span>
                        </div>
                    </div>
                    <div class="mdl-cell mdl-cell--12-col page-row">
                        <div class="mdl-textfield mdl-js-textfield mdl-cell mdl-cell--12-col">
                            <label asp-for="ConfirmPassword" class="mdl-textfield__label"></label>
                            <input asp-for="ConfirmPassword" class="mdl-textfield__input" />
                            <span asp-validation-for="ConfirmPassword" class="mdl-textfield__error"></span>
                        </div>
                    </div>
                </div>
            </div>
            <div class="mdl-cell mdl-cell--12-col page-row">
                <button type="submit"
                        class="mdl-button mdl-js-button 
                            mdl-button--raised mdl-button--colored
                            mdl-js-ripple-effect">
                    Register
                </button>
            </div>
        </div>
    </form>
</div>

As you can see, the marked up HTMLs only use the style sheet in the MDL library. At the monent, the MDL team is developing a lot of components (like Dialog...), but those components are still for future release. 

Please go to my github to see more pages.

Our solution structure will be 

Write some ES6 Javascript code

Now we can write any ES6 Javascript code in our solution. I put some sample codes as below

(($) => {
    $(document).ready(() => {
        
        console.log("It works");

        $(".delete-product").on("click", (e) => {
            const DELETE_URL = "/product/delete";

            let $delBtn = $(e.target)
                , productId = $delBtn.data("id");

            $.ajax({
                url: DELETE_URL,
                data: {
                    id: productId
                },
                method: "POST"
            }).done((result) => {
                if (result.reload === true) {
                    window.location =  "/product";
                }
            });
        });
    });
})(jQuery);

The Layout 

Home Page

Login Page

Register Page

That is all things I want to share to you today.

All suggestions are welcome.

Thank you for your reading. 

Happy coding :)

References

No Comments