MJSmithDev Development Notes from Matt Smith of PA, USA

Free Git on Bitbucket with Visual Studio

gwindows_logo Today I’m sharing for my own memory banks how to add a new Visual Studio solution/project to Git source control. If you’ve heard of Git, you’ve probably heard of Github, which hosts roughly a zillion git repositories. One problem with Github (at least as of now) is that they don’t offer private repositories for free, only public ones. If you don’t want to pay for your little side projects to be hosted in a private repository, what is a poor dev to do? Simple, use Bitbucket instead. With Bitbucket you can host private repositories with a free account.

So how do we host our git repository on Bitbucket for free? I’m glad I asked, so for me here are the steps (with too many missing screenshots, because I forgot to take them).

  1. Login to Bitbucket
  2. Select Repositories…Create repository. You’ll see this screen… bitbucket-create-repo
  3. Enter the repository details and click Create repository.
  4. Back in Visual Studio, right-click on your solution and select Add solution to source control.
  5. In the window that pops up, select Git.
  6. In the Team Explorer window that comes up enter in an initial commit message.
  7. On the button below it, select Commit and Push.
  8. On the synchronization window that comes up enter in the bitbucket repository URL in this pattern… https://{username}@bitbucket.org/{username}/{repository}.git visual-studio-enter-remote-repo
  9. Click Publish.
  10. You’re done. (Had to make it a nice even 10 steps).

Now, if you check in Bitbucket, you’ll see the source control is now in the repository. A big thanks to my past self for writing this up from my future self (now present self).

ASP.NET MVC 6 and the Infinite Scroll

infinity When we have long lists of items, it’s nice to present the users with the option to page them, instead of showing them all at once. You can use your standard pager, which works great with something like a table list, or you might be able to try something called “infinite scrolling”. Infinite scrolling is that feature where you start scrolling to the bottom of the page and it automagically loads more data for you. So, it’s like paging but using the browser scroll bar. I’ve been doing a redesign of a book listing site, and instead of just providing the standard pager, I thought it would be nice to let them just keep on going.

So, where do we start? This post is written using ASP.NET 5 (MVC 6), but the code is basically the same in older versions of ASP.NET MVC. To do the infinite scrolling, we’ll be using a JQuery plugin called “jScroll” written by Philip Klauzinski. To pull down a client side library in ASP.NET 5, we open up our bower.json file and just add in the library name and version, as such…

{
  "name": "ASP.NET",
  "private": true,
  "dependencies": {
    "jquery": "*",
    "jquery-validation": "1.11.1",
    "jquery-validation-unobtrusive": "3.2.2",
    "materialize": "*",
    "jscroll": "2.3.4"
  }
}

…You can see jscroll there at the bottom. Now, if you happen to be using the “Main-Bower-Files” NodeJS package I wrote about before, you’ll just need to open up Task Runner Explorer and run the Copy command to add it to your local ‘wwwroot/lib’ directory. If not, then you’ll need to modify your gulp.js file to tell it to copy over the new file to your ‘wwwroot/lib’ directory.

Now we have the client side library available, we can add it to our razor view where you want the scrolling. (You can setup Gulp to combine and minify your javscript, which you’ll want to do for production. I’ll write about that later.) Since I will just be using this on one page, I’ll just add it to the scripts section on that page…

@section scripts{
    <script src="~/lib/jscroll/jquery.jscroll.js"></script>
    <script>
      $(function () {
        $('#booklist').jscroll({
          debug: true,
          loadingHtml: '<div class="row"><div class="col s4 center"><div class="progress"><div class="indeterminate"></div></div></div></div>'
        });
      });
    </script>
  }

…This scripts section adds the JScroll library and initializes it. In this example, it will just look for a tag with the id of booklist. I’ll show you that in a minute. The other properties turn on its debugging and changes it’s loadingHtml to show a loader image (from the MaterialCSS library).

Now, let’s create a partial view. So, create a new view under your Views and “ControllerName” directory (Views/Books, for example) and name it “_BookList”. The underscore is not necessary, it’s just convention.

Inside of “_BookList.cshtml”, we’ll put in the html that will have the infinite scroll. In this example, I’m just going to use a simple UL list…

@model IEnumerable<DFE.Models.Book>
<div id="booklist" class="scroll">
  <ul id="ullist">
    @foreach (var item in Model) {
      <li>@Html.DisplayFor(modelItem => item.Title) by @Html.DisplayFor(modelItem => item.Author)</li>
    }
    <li class="next"><a href="/booklist?page=@(ViewBag.Page+1)">Loading...</a></li>
  </ul>
</div>

…So, it will simply add another UL list on each call. The link is what JScroll calls to show the next set. It will keep calling until we do a return of EmptyResult from our controller, which will then not display any HTML and JScroll will see that as a call to end. The ViewBag.Page just keeps track of what page we’re on and what to fetch next.

Inside our controller, we now need to add a call for the ‘booklist?page=’ route you see in the link above. Here’s our controller method…

[Route("/booklist")]
public IActionResult BookList(int page) {
  var books = bc.Books.ToList();

  int rangeStart = 0;
  int rangeLength = 0;

  int pageSize = 12;
  int pageNumber = page;

  if ((pageNumber * pageSize) > books.Count)
    return new EmptyResult();

  if (((pageNumber * pageSize) + pageSize) > books.Count) {
    rangeLength = books.Count % pageSize;
    rangeStart = books.Count - rangeLength;
  } else {
    rangeStart = (pageNumber * pageSize);
    rangeLength = pageSize;
  }

  books = books.GetRange(rangeStart, rangeLength);

  ViewBag.Page = pageNumber + 1;
  return PartialView("_BookList",books);
}

…You can see this method is called by the ‘booklist’ route and accepts one parameter called ‘page’. The first thing we do is call our list of books from our EF context. After doing some initializing, we next do some checks on what range to display. Our first check is to see if given the pagenumber * the pageSize will go beyond the number of books available. If so, then we’ve reached the end and return an EmptyResult. The next if-else check will see if we have a full set of pageSize to display or just whatever is left. We then grab that range from the list. Finally we update the ViewBag.Page count and display the partial view.

If all goes well, you’ll now get another UL list displayed in the brower, just by scrolling down, something like this table example… infinite-scrolling-example

Solving 404.8 IIS Errors when Loading Your Client Side Libraries

Just ran into a problem trying to get the MaterializeCSS library working in Visual Studio 2015. It would refuse to load the CSS/JavaScript. I’m pulling in Materialize via Bower/Gulp. The main files are under ‘materialize/bin’.

If you look at your browser’s console, you’ll see it’s giving an error that it can’t load them. When you go directly to the CSS file, IIS throws up a 404.8 Hidden Namespace error. It’s not a 404.0 Not Found error, because it sees the files, it just can’t load them.

If you look at the name of the directory that the Materialize team chose to use - ‘bin’ that might give you the clue to why this is happening. To protect us from possible attacks, by default certain key directories are blocked, including any directory named ‘bin’. Now, you could add code to remove it from blocking bin, but I just found it safer to move the files outside of the ‘bin’ directory.

If you use the handy “main-bower-files” in your gulpfile.js, you might be interested in this piece…The only problem with manually moving around files is that MaterializeCSS has its ‘main’ defined in its bower.json to use the ‘bin’ directory. “main-bower-files” will just keep copying over the ‘bin’ directory. You can tell “main-bower-files” to override that, like such…

var files = mainBowerFiles({
      paths: {
          base: paths.bower
      },
      "overrides": {
          "materialize": {
              "main": "dist/**"
          }
      }
  });

That will copy the files from the ‘dist’ folder instead of what is defined under ‘main’.

You can read up on 404.8 IIS errors at your leisure.

ASP.NET 5 How to Add New Bower Libraries with Gulp

gulp-bower In Part 1 of this 2 part post we looked at how to use Bower to bring down a new client side library. In Part 2 we will focus on how to include the important bits of that library in your ASP.NET 5 web project using Gulp.

Gulp is like build rules for client side libraries. In your ASP.NET 5 web project you’ll see ‘gulpfile.js’. This defines the “build rules” used by Gulp. If you open it up, you’ll see a piece like…

gulp.task("copy", ["clean"], function () {
  var bower = {
    "bootstrap": "bootstrap/dist/**/*.{js,map,css,ttf,svg,woff,eot}",
    "bootstrap-touch-carousel": "bootstrap-touch-carousel/dist/**/*.{js,css}",
    "hammer.js": "hammer.js/hammer*.{js,map}",
    "jquery": "jquery/jquery*.{js,map}",
    "jquery-validation": "jquery-validation/jquery.validate.js",
    "jquery-validation-unobtrusive": "jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"
  }
...

This tells Gulp to perform a function when you call ‘copy’ or ‘clean’. So, this is the second piece to the puzzle of adding a client side library to your project. Bower let us bring down the package and Gulp will copy over the appropriate bits into your project.

We could simply add a line to the bower variable in the gulp copy/clean function defined above that will copy over the ‘dist’ folder contents from our materialize library. That will work just fine. Problem though is that for every library you want to add, you’ll need to remember to add it to ‘bower.json’ and ‘gulpfile.json’. I hate having to do similar things in two different places every time. To get around this enter a nice Node.js package called “Main-Bower-Files” from Christopher Knötschke.

Main-Bower-Files will look in your Bower cache directory and pull out the main pieces of each library. This will save you from having to update that bower javascript variable with every client side package you want to use. First step is to add Main-Bower-Files. You can do that by opening another file in your project, ‘package.json’. Add in “main-bower-files” like so…

{
  "name": "ASP.NET",
  "version": "0.0.0",
  "devDependencies": {
    "gulp": "3.8.11",
    "rimraf": "2.2.8",
    "main-bower-files": "2.8.0"
  }
}

The 2.8.0 just happened to be the latest version as of this write up. This will tell Node.js to pull down that Node package which provides us a nice new tool to use inside of ‘gulpfile.js’. After Visual Studio pulls down the Node.js package, open up ‘gulpfile.js’ again and in the top add a reference to the ‘main-bower-files’…

var gulp = require("gulp"),
  rimraf = require("rimraf"),
  fs = require("fs"),
  mainBowerFiles = require('main-bower-files');

Then in the copy/clean function change it to have Main-Bower-Files find the Bower main files for you…

gulp.task("copy", ["clean"], function () {
    
  var files = mainBowerFiles({
      paths: {
          base: paths.bower
      }
  });

   gulp.src(files, { base: paths.bower })
    .pipe(gulp.dest(paths.lib));
});

Finally, right-click on ‘gulpfile.js’ in Solution Explorer and select “Task Runner Explorer”. In the Task Runner Explorer window, right click on Copy and select Run… taskrunnerexplorer Your ‘lib’ directory under your ‘wwwroot’ should now have your new library… lib