Two ways to set a conditional breakpoint in JavaScript

On February 19, 2013, in Uncategorized, by jonathancreamer

Debugging JavaScript can be a tedious process. Especially when debugging a function that is called many times in an application. There may be some kind of utility function in an app that processes data, but there’s a bug with one of the values.

In order to debug the function you’d open up Chrome or IE’s Dev Tools and throw in a breakpoint. If the function being debugged is used in many areas, you’ll have to hit continue multiple times to get to the specific case needed.

There are two different ways to avoid this problem.

Say you have the following code.

var process = function( obj ) {
  var type = Object.prototype.toString.call( obj );
  return type;
};

console.log( process({}) );
console.log( process([]) );
console.log( process("something") );
console.log( process(2) );

The process function gets called 4 times here. What if while debugging, only the case in which the object is of the type String is needing to be debugged?

The first way to do this is with just code. The debugger; is a statement in JavaScript that will trigger a breakpoint in the code. By putting debugger into the code, the execution will pause at that line. The debugger can also be wrapped with a conditional statement that only runs when the condition is true.

var process = function( obj ) {
  var type = Object.prototype.toString.call( obj );
  if ( ~type.indexOf( "Str" ) ) {
    debugger;
  }
  return type;
};

Now the debugger will only be hit when the type is of “String”.

The other way to set a conditional breakpoint is with the browser’s development tools.

In Chrome…

chormemenu

chromeconditional

And in IE10, and I’m pretty sure 9 also.

iemenu

ieconditional

UPDATE 2/25/2013 several readers asked me to point out that Firefox also supports this feature…

firefox

That can definitely be a time saver!

 

Reset npm user account

On September 11, 2012, in Uncategorized, by jonathancreamer

Today I was publishing stuff to npm and came across a situation in which I typed the wrong user account for my local mahcine’s npm.

I typed npm adduser jcreamer898 and then realized it was supposed to be “jcreamer”.

After a few minutes of digging I figured out that there’s a file in my home directory called .npmrc that gets created when you run adduser.

So I renamed that file, to old.npmrc then ran npm adduser jcreamer and voila!

 

A couple of useful JavaScript Sublime Text 2 snippets

On July 13, 2012, in Uncategorized, by jonathancreamer

I wrote a few Sublime Text 2 snippets the other day that I thought I would share with the world, I’ll probably add some more to this post over time as snippets are super easy to create, and super helpful!

First one is for jQuery plugins, and is based on http://coding.smashingmagazine.com/2011/10/11/essential-jquery-plugin-patterns/ thanks to Addy Osmani.

<snippet>
    <content><![CDATA[
(function ( \$, window, document, undefined ) {

    // Create the defaults once
	var pluginName = "${1:name}",
        defaults = {
            propertyName: "value"
        };

    // The actual plugin constructor
    function ${2:snippet}( element, options ) {
		this.element = element;

        this.options = \$.extend( {}, defaults, options) ;

        this._defaults = defaults;
        this._name = pluginName;

        this.init();
    }

    \$.extend(${2:snippet}.prototype, {
        init: function () {

        }
    });

    \$.fn[pluginName] = function ( options ) {
        return this.each(function () {
            if (!\$.data(this, pluginName)) {
                \$.data(this, pluginName,
                new ${2:snippet}( this, options ));
            }
        });
    };

    \$.fn[ pluginName ].defaults = defaults;

})( jQuery, window, document );
]]></content>
    <!-- Optional: Set a tabTrigger to define how to trigger the snippet -->
    <tabTrigger>jqplug</tabTrigger>
    <!-- Optional: Set a scope to limit where the snippet will trigger -->
    <scope>source.js</scope>
</snippet>

And here’s another for RequireJS plugins.

<snippet>
    <content><![CDATA[
define(['${1:deps}'], function (${2:args}) {

});
]]></content>
    <!-- Optional: Set a tabTrigger to define how to trigger the snippet -->
    <tabTrigger>def</tabTrigger>
    <!-- Optional: Set a scope to limit where the snippet will trigger -->
    <scope>source.js</scope>
</snippet>

There ya go! More to come hopefully…

Console.log

<snippet>
    <content><![CDATA[
console.log("${1:message}")
]]></content>
    <!-- Optional: Set a tabTrigger to define how to trigger the snippet -->
    <tabTrigger>log</tabTrigger>
    <!-- Optional: Set a scope to limit where the snippet will trigger -->
    <scope>source.js</scope>
</snippet>

New HTML Page

<snippet>
	<content><![CDATA[
<!DOCTYPE html>
<html>
<head>
  <title></title>
  <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;">
  <link rel="shortcut icon" href="/favicon.ico">
  <link rel="apple-touch-icon" href="/apple-touch-icon.png">
  <link rel="stylesheet" href="style.css">
</head>
<body>
</body>
</html>
]]></content>
	<!-- Optional: Set a tabTrigger to define how to trigger the snippet -->
	<tabTrigger>htmlp</tabTrigger>
	<!-- Optional: Set a scope to limit where the snippet will trigger -->
	<--<scope>source.html</scope>-->
</snippet>
Tagged with:  

This is a really quick post, just thought it was useful enough to post.

There are times with jQuery where I find myself needing to get the html of an entire item.

For example…

    // somehtml.html
<div class="whatever">I want more than this html</div>

// somejs.js
// Gives me only "I want more than this html", but I want more...
$('.whatever').html(); 

Use the following quick function and you’ll have a string representing not only the innerHTML, but also the html of the actual selected element(s).

jQuery.fn.toHtmlString = function () {
    return $('<div></div>').html($(this).clone()).html();
};
// Now I have"<div class="whatever">I want more than this html</div>"...
$('.whatever').toHtmlString();

Espresso tip of the day!

Tagged with:  

There are many packages for minifying assets in web applications. A new one written by Andrew Davey (@andrewdavey) called Cassette offers some great features that help deliver not only CSS and JS bundling and minifcation, but also Coffee, SASS, LESS, as well as Html templates. The Html templates can also be pre-compiled if using jQuery Templates or KnockoutJS.

To get started with Cassette, run the following in the package manger in Visual Studio…

PM> Install-Package Cassette.Web

That command drops a file into your project directory called CassetteConfiguration. This file is used to add bundles. A bundle in cassette represents a group of assets, assets being the files to be used by your project.

    public class CassetteConfiguration : ICassetteConfiguration
    {
        public void Configure(BundleCollection bundles, CassetteSettings settings)
        {
            bundles.AddPerIndividualFile
("public/css");
            bundles.AddPerIndividualFile("public/javascripts");
            bundles.Add("public/templates");
        }
    }

This tells Cassette which folders your assets are in.

Next in your layout you can reference the files by adding references to your bundles.

@{
    Bundles.Reference("public/css/site.css");
    Bundles.Reference("public/javascripts/libs/jquery-1.7.1.js");
    Bundles.Reference("public/javascripts/libs/handlebars.js");
}

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title</title>

    @Bundles.RenderStylesheets()
</head>

<body>
    @RenderBody()
    @Bundles.RenderScripts()
</body>
</html>

The @Bundles.RenderScripts() actually renders your scripts, and the @Bundles.RenderStylesheets() renders the Css files.

One of the nice features that Cassette offers is Html Template rendering as well. Add this to your configuration…

bundles.Add("public/templates");

And this somewhere to your page…

@Bundles.RenderHtmlTemplates()

This will add script tags containing your Html code and wrap them in script tags with an id set to the filename.

Another great feature of Cassette is the ability to compile coffeescript! Simply add a .coffee file in your project and reference it with…

@{
    Bundles.Reference("public/javascripts/app.coffee");
}

The CoffeeScript I wrote for my app is…

#@reference libs/jquery-1.7.1.js
movies = [
	name:'Star Wars'
	id: 1
,
	name:'The Matrix'
	id: 2
,
	name:'Bourne Identity'
	id: 3
	]

$ ->
	movieTmpl = Handlebars.compile $('#movie').html()
	html = movieTmpl
		movies: movies
	$('#movieList').append html

And Cassette will automatically compile the CoffeeScript and place the JavaScript on the page. Note the #@reference libs/jquery-1.7.1.js tells Cassette that this file requires jQuery to be loaded first. You can do this in any JavaScript file in a similar fashion by having a reference comment in the top of the file. For example if a file needed both jQuery and Backbone to be loaded before it…

/// <reference path="jquery-1.7.1.js" />
/// <reference path="underscore.js" />

/*
    Now you can safely use code that requires the above libraries
*/

The following is the output of this page so far…

<!DOCTYPE html>
<html>
<head>

    <meta charset="utf-8" />
    <title></title>

</head>
<body>

<table id="movieList">

</table>    

<script src="/_cassette/asset/public/javascripts/libs/jquery-1.7.1.js?b47730ffaec4272a8a01756af2ef13ecea1c4e92" type="text/javascript"></script>

<script src="/_cassette/asset/public/javascripts/app.coffee?e8229d2c97b44b2722c0b3b6fd7c69ca967bdced" type="text/javascript"></script>

<script src="/_cassette/asset/public/javascripts/libs/handlebars.js?ec02162bf8cc6692ac06361e1c2e8b24aa2f66bf" type="text/javascript"></script>

<script id="movie" type="text/html">{{#each movies}}
<tr>
    <td>
        {{name}}
    </td>
    <td>
        <a href="#/movies/{{id}}">Edit</a>
    </td>
</tr>
{{/each}}
</script>
</body>
</html>

In order to have all of the scripts minify, simply change debug=”true” to false in the web.config under compilation. All your scripts will be nicely minified by AjaxMin and cached.

There are more features with Cassette, so be sure and check them out at http://getcassette.net/documentation/

Tagged with:  


Backbone.js
has quickly become one of JavaScript’s premier MV* frameworks. It offers simple flexibility, and language features that just make sense.

ASP.net MVC has also become one of the web’s most popular server side frameworks and the latest iteration, MVC4 was recently released into beta. One of it’s newer features is called, Web API and is a way of creating a REST service inside of an MVC application.

Along with the release of MVC4 is a new feature in Entity Framework Code First called Migrations. This offers a way of keeping track of all the changes to the data model over time.

And yet another popular web feature is CoffeeScript. Written by the same guy that created Backbone, and Underscore, CoffeeScript adds Ruby-esque language features to JavaScript, and also “transpiles” down into JavaScript. It can be compiled in a number of different ways including a coffee.exe, inside of Node.js, or directly in Visual Studio with Mindscape Web Workbench.

This post combines all of these exciting new things into one app for managing contacts.

First off, download and install the ASP.net MVC4 Beta.

Then go ahead and either get Mindscape, or get Node.js, and run

npm install -g coffee-script

in a command prompt or terminal window.

Next, open up Visual Studio and File –> New Project.

There should be a new option for ASP.NET MVC 4 Web Application. Hit ok, and then choose Empty from the next window.

This will give you a brand spankin’ new MVC4 application. Let’s begin with creating the data model.

Please note: All the code below is online at…

https://github.com/jcreamer898/BackboneCoffeeWebApi

The code below is broken down into Entity Framework, Web API, and CoffeeScript/Backbone.

Entity Framework

First off we’ll create a Customer class, and a DbContext.

    public class Customer
    {
        public int Id { get; set; }

        [Required]
        public string FirstName { get; set; }

        [Required]
        public string LastName { get; set; }

        [Required]
        [Email]
        public string Email { get; set; }

        public string Phone { get; set; }

        public string Description { get; set; }
    }
    public class ManagerContext : DbContext
    {
        public DbSet Customers { get; set; }
    }

The extra DataAnnotation of Email is from the NuGet package DataAnnotationsExtensions.MVC3.
Next is upgrading Entity Framework and Enabling migrations. This is accomplished by the following three commands in the Package Manager Console…

 

    >Update-Package EntityFramework
    >Enable-Migrations
    >Add-Migration FirstDatabaseCreate
    >Update-Database

A new folder called Migrations will be added to your solution and in it will be to files, Configuration, and TIMESTAMP_FirstDatabaseCreate.cs. The FirstDatabaseCreate.cs provides an up and down for moving through different versions of your database. Update-Database will go ahead and create the database for you.

The configuration file also has a seed method for seeding the database…

    internal sealed class Configuration : DbMigrationsConfiguration
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
        }

        protected override void Seed(CustomerManager.Models.ManagerContext context)
        {
            //  This method will be called after migrating to the latest version.

            //  You can use the DbSet.AddOrUpdate() helper extension method
            //  to avoid creating duplicate seed data. E.g.
            //
            //    context.People.AddOrUpdate(
            //      p => p.FullName,
            //      new Person { FullName = "Andrew Peters" },
            //      new Person { FullName = "Brice Lambson" },
            //      new Person { FullName = "Rowan Miller" }
            //    );
            //
            context.Customers.Add(new Customer
                                      {
                                          FirstName = "Joe",
                                          LastName = "Schmoe",
                                          Description = "Awesome",
                                          Email = "joe@schmoe.com",
                                          Phone = "6155551234"
                                      });
        }
    }

That’s it for the data model, now onto the Web API stuff. Web API is still currently in Beta, but it is in pretty darn good shape already as Scott Gu lists some of its awesome features. Most notable are Automatic Content Negotiation, built in IoC support, and a Modern HTTP model.

Web API

You’ll notice in a new MVC4 application, in the global.asax a new route will be added…

routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

This allows you to begin adding Api controllers which inherit from a new class called ApiController. Go ahead and right click on Controllers and create a new controller. In the drop down box choose API Controller.

apicontroller

This will generate a new controller that looks something like…

    public class CustomersController : ApiController
    {
        // GET /api/customers
        public IEnumerable Get()
        {
            return new string[] { "value1", "value2" };
        }

        // GET /api/customers/5
        public string Get(int id)
        {
            return "value";
        }

        // POST /api/customers
        public void Post(string value)
        {
        }

        // PUT /api/customers/5
        public void Put(int id, string value)
        {
        }

        // DELETE /api/customers/5
        public void Delete(int id)
        {
        }
    }

By convention the name of the Http method becomes the name of the Action in the Controller. Fast forward a little bit, adding in all of the retrieval methods for the the methods, and…

 

public class CustomersController : ApiController
    {
        private ManagerContext _managerContext;

        public CustomersController()
        {
            _managerContext = new ManagerContext();
        }

        // GET /api/customers
        public IEnumerable Get()
        {
            return _managerContext.Customers;
        }

        // GET /api/customers/5
        public Customer Get(int id)
        {
            return _managerContext.Customers.SingleOrDefault(c => c.Id == id);
        }

        // POST /api/customers
        public HttpResponseMessage Post(Customer customer)
        {
            JsonArray errors = ParseErrors();
            if (errors.Count > 0)
            {
                return new HttpResponseMessage(errors, HttpStatusCode.Forbidden);
            }
            _managerContext.Customers.Add(customer);
            _managerContext.SaveChanges();
            return new HttpResponseMessage(customer);
        }

        // PUT /api/customers/5
        public HttpResponseMessage Put(int id, Customer customer)
        {
            JsonArray errors = ParseErrors();
            if(errors.Count > 0)
            {
                return new HttpResponseMessage(errors, HttpStatusCode.Forbidden);
            }
            _managerContext.Entry(customer).State = EntityState.Modified;
            _managerContext.SaveChanges();
            return new HttpResponseMessage(customer);
        }

        // DELETE /api/customers/5
        public void Delete(int id)
        {
            var customer = _managerContext.Customers.SingleOrDefault(c => c.Id == id);
            _managerContext.Customers.Remove(customer);
            _managerContext.SaveChanges();
        }

        private JsonArray ParseErrors()
        {
            var errors = new JsonArray();
            // Validate movie
            if (!ModelState.IsValid)
            {

                foreach (var prop in ModelState.Values)
                {
                    if (prop.Errors.Any())
                    {
                        errors.Add(prop.Errors.First().ErrorMessage);
                    }
                }
            }
            return errors;
        }
    }

Whew, a lot going on there, but not too much. It’s pretty much routine in terms of retrieving things from a DbContext in EF. The newer-ish things are in the Put and Post you can see the return type is HttpResponseMessage. This class is used to wrap a response and return specific error codes. The other is a private method called ParseErrors. This method loops over all of the Values in the ModelState and determines if there are any errors. If so, it will gather them into an array and return them with a 403 error to the client.

That takes care of the Web API stuff for now. You can test that the API is working by firing up a debugger and hitting /Api/Customers. For further info on the Web API, checkout Jon Galloway’s series of 6 posts.

Next, create a HomeController, layout, and an index view just like in MVC3. Then go ahead and either add Backbone, Underscore, and Handlebars to the application. Handlebars.js is a very good templating framework for JavaScript.

CoffeeScript/Backbone

Enter CoffeeScript. Using the Mindscape Web Workbench extension, you can add CoffeeScript files to your application.

coffeescript

coffeescriptfile

Every time you write CoffeeScript and save it, it will automatically, “transpile” your CoffeeScript into JavaScript. Then you can reference app.js in the layout.

Now begin the Backbone CoffeeScript fun! I’ll start with the models.

class Customer extends Backbone.Model
	urlRoot: '/api/customers/'
	idAttribute: 'Id'
	validate: (attr) =>
		if !attr.FirstName
			return "First Name is required"
		if !attr.LastName
			return "Last Name is required"
		if !attr.Email
			return "Email Address is required"

class Customers extends Backbone.Collection
    url: '/api/customers/'
    model: Customer

This code creates a Customer Model as well as a Customer Collection. The Customer model has some validation that will come into play whenever the Customer’s attributes are set, or the model is saved. The urlRoot is the main Url from our Web API. Backbone.Sync will use GET on model.fetch POST on model.save when the Id of the model hasn’t been set, PUT on model.save when the Id IS set, and DELETE on model.destroy.

Next we’ll create some Customer Views.

class CustomerList extends Backbone.View
	initialize: =>
        @collection.on 'reset', @renderAll
        @collection.on 'add', @render
        @collection.fetch()
        _.bindAll @,'renderAll'
        return this
    renderAll: () =>
        @collection.each @render
        return this
    render: (model) =>
        item = new CustomerItem
            model: model
        @$el.append item.el
        return this

class CustomerItem extends Backbone.View
	tagName: 'tr'
	initialize: =>
        @template = Handlebars.compile($('#customer').html())
        @model.on('change', @render)
        @render()
        return this
    events:
        'click .remove': 'deleteItem',
        'click .edit': 'showEdit'
    render: =>
        html = @template @model.toJSON()
        @$el.html('').append(html)
        return this
	showEdit: (event) =>
		event.preventDefault()
		Vent.trigger 'edit', @model
		return this
	deleteItem: =>
		@model.destroy()
		@$.fadeOut 'fast'
		@remove()
		messages.success 'Deleted!'
		return this

class CustomerEdit extends Backbone.View
	el: '#customerEdit'
	events:
		'click #save': 'save'
		'click #cancel': 'cancel'
	initialize: =>
		Vent.on 'edit', @render
		@template = Handlebars.compile $('#customerEditTemplate').html()
	render: (model) =>
		if model
			@model = model
		else
			@model = new Customer()
		data = @model.toJSON()
		html = @template data
		@$el.html(html).show()
			.find('#first').focus()

		@model.on 'error', @showError
		return this;
	save: (event) =>
		@model.save
			'FirstName': @$el.find('#first').val()
			'LastName': @$el.find('#last').val()
			'Email': @$el.find('#email').val()
			'Phone': @$el.find('#phone').val()
			'Birthday': @$el.find('#birthday').val()
			'Description': @$el.find('#description').val()
		,
			wait: true
			success: =>
				messages.success 'Saved!'
				window.customers.add @model unless window.customers.any( (customer) =>
					return customer.get('Id') is @model.get('Id');
				)

				@$el.hide()
		return this
	cancel: =>
		@$el.hide()
	showError: (model, error) =>
		error = JSON.parse(error.responseText).join '<br   \ />' if (typeof error is 'object')
		messages.error error

The CustomerList is responsible for managing the entire list of customers. And anytime the collection is retrieved from the server or added to, it will create a new CustomerItem view and append it to the CustomerList. The CustomerItem uses a customer template found in the following HTML code, and is compiled with Handlebars.js.

The CustomerEdit view is used to edit, no surprise there! The initialize method stores a compiled Handlebars template for editing a customer. The save method grabs all of the values off of the inputs, and then calls model.save(). This of course causes the server to either PUT or POST depending on the result of model.isNew().

<script id="customer" type="text/html">
    <td>{{ FirstName }}</td>
    <td>{{ LastName }}</td>
    <td>{{ Email }}</td>
    <td colspan="2">
        <a href="#edit" class="edit" data-id="{{Id}}"><i class="icon-pencil"></i></a>
        <a href="#remove" class="remove" data-id="{{Id}}"><i class="icon-remove"></i></a>
    </td>
</script>

<script id="customerEditTemplate" type="text/html">
    <input type="hidden" name="id" id="id" value="{{Id}}"/>
    <input type="text" name="first" id="first" value="{{FirstName}}" placeholder="First Name"/>
    <input type="text" name="last" id="last" value="{{LastName}}" placeholder="Last Name"/>
    <input type="email" name="email" id="email" value="{{Email}}" placeholder="Email"/>
    <input type="text" name="phone" id="phone" value="{{Phone}}" placeholder="Phone"/>
    <textarea name="description" id="description">{{Description}}</textarea>
    <a class="btn btn-primary btn-large" id="save">Save</a>
    <a class="btn btn-primary btn-large" id="cancel">Cancel</a>
</script>

One of the interesting things in the CustomerItem view is the concept of a Vent. I saw Derick Bailey use this technique. It combines a few patterns, one called Pub/Sub or Observer, and another called the Mediator pattern.

The Observer pattern basically allows objects to publish or subscribe to events. Much the same way that when working with browsers, when a user clicks in the browser, the browser publishes a click event, and some JavaScript or jQuery code listens to the event.

The Mediator pattern assigns an object the responsibility of handling all pub/sub requests.

The Observer pattern is implemented through Backbone.Events, and can be used with the Mediator pattern by…

    class Vent extends Backbone.Events
    window.Vent = Vent

Now you have a global Vent object that is responsible for managing pub/sub events. In the CustomerItem view above you can see the line of code, Vent.trigger ‘edit’, @model

In CustomerEdit there is some code that listens to the edit event Vent.on ‘edit’, @render and fires the render method when it is triggered.

Also in CustomerEdit I used a view called MessageManager in order to display messages to the users.

class MessageManager extends Backbone.View
    el: '.alert'
    render: (type, message, opts) =>
        defaults =
            fade: 3000
        _.extend defaults, opts
        typeClass = "alert alert-#{type}";
        @$el.empty().prepend(message).removeClass().addClass(typeClass).fadeIn 'fast'
        setTimeout (=> @$el.fadeOut()), defaults.fade
    error: (message, opts) =>
        @render 'error', message, opts unless !message
    success: (message, opts) =>
        @render 'success', message, opts unless !message

Pretty basic stuff here, just a few methods for triggering different types of messages.

The last piece needed in the JavaScript code is the initialization of the different views.

$ ->
    window.customers = new Customers
    edit = new CustomerEdit()
    list = new CustomerList
        collection: customers
        el: '#customerList'

    $('#add').click ->
        Vent.trigger 'edit'
    $(".alert").alert()
    window.messages = new MessageManager()

This code here wraps the initialization in a jQuery ready, and then starts newing stuff up. An instance of the Customers collection, and an instance of the messages view are stored in the window so that they can be accessed anywhere in the app, and the edit and list views are also initialized.

Last is the simple attaching of a click handler to my add button which triggers the Edit event and allows for adding a new customer.

Again all of the above code is available at

https://github.com/jcreamer898/BackboneCoffeeWebApi/

And in the /Scripts/ directory there is an app.coffee, and it’s code behind app.js, as well as an actual representation of the JS at app.javascript.js

Hope you enjoy!

Tagged with:  

Espresso Tip: Find and replace Regex in Visual Studio

On March 22, 2012, in Uncategorized, by jonathancreamer

Every now and again you come across something really useful that you just have to share.

A few minutes ago that happened to me…

I had a bunch of code that looked like…

    var js = @Bundle.Javascript()
        .Add("script1.js")
        .Add("script2.js")
        .Add("script3.js")
        .Add("script4.js");
        // .... many more ....

And I needed to remove the .Add in place of actual script tags.

Of course I could have just manually done it, but I figured… I am smarter then all that!

So I hit Ctrl + h in Visual Studio to pull of Quick Replace and punched in a regex to find all of my .Adds.

Next, in VS Quick Replace you can use curly braces in your regex to capture stuff. So, my regex became…

\.Add\({.*}\)

Then you can use a \1 in the replace with to place the captured expression in the replace string.

That’s it! Thought that was worth sharing…

 

 

 

 

 

 

Using JSON.net to consume the JSON Stack Overflow API

On February 7, 2012, in ASP.net, MVC3, by jonathancreamer

JSON has rapidly grown arguably the most popular way to transfer data via API’s. It’s fast, simple, and most every language supports it. ASP.net has a few things like the JavaScript Deserializer Class that do a decent job, but one of the better tools available is JSON.net.

What a better way to test it than to use a real world example. StackOverflow has a public facing JSON api available at http://api.stackoverflow.com/1.1/ so I’ll show how to consume that one.

First, fire up whatever sort of app you want and then head to the Tools –> Library Package Manager –> Package Manager Console (aka. NuGet) and type in Install-Package Newtonsoft.Json

After some NuGet-y magic you’ll have JSON.net at your finger tips.

For starters we’ll consume the Users method of the API. Hitting the Url, http://api.stackoverflow.com/1.1/users/558672  It looks like…

The fastest way to consume it with JSON.net is by using the JsonConvert.DeserializeAnonymousType method.

var client = new WebClient();
byte[] response = client.DownloadData("http://api.stackoverflow.com/1.1/users/558672");
var decompress = new GZipStream(new MemoryStream(response), CompressionMode.Decompress);
var reader = new StreamReader(decompress);
string ret = reader.ReadToEnd();

var stackResponse = new
{
    total = 0,
    page = 0,
    pagesize = 0,
    users = new[]
    {
        new {
            user_id = 0,
            user_type = "",
            creation_date = "",
            display_name = "",
            reputation = 0,
            email_hash = "",
            age = 0,
            last_access_date = 0,
            website_url = "",
            location = "",
            about_me = "",
            question_count = 0,
            answer_count = 0,
            view_count = 0,
            up_vote_count = 0,
            accept_rate = 0,
            bagde_counts = new {
                gold = 0,
                silver = 2,
                bronze = 9
            }
        }
    }
};

var stackUser = JsonConvert.DeserializeAnonymousType(ret, stackResponse);

One thing to note is that StackOverflow Gzips all of their API responses, that’s what all that decompress stuff is about. So, THAT is it as far as the quickest way to consume a JSON Api with JSON.net.

The next more involved way to consume the API is to create your own classes that mirror the structure of the API and deserialize the response into them. This can look a variety of ways potentially, but here is my implementation.

public class StackUser : StackBase
{
    [JsonProperty("user_id")]
    public int UserId { get; set; }

    [JsonProperty("user_type")]
    public string UserType { get; set; }

    [JsonProperty("display_name")]
    public string DisplayName { get; set; }

    [JsonProperty("reputation")]
    public int Reputation { get; set; }

    [JsonProperty("email_hash")]
    public string Email { get; set; }

    [JsonProperty("age")]
    public int Age { get; set; }

    [JsonProperty("last_access_date")]
    public int LastAccessDateInt { get; set; }

    [JsonProperty("website_url")]
    public string Website { get; set; }

    [JsonProperty("location")]
    public string Location { get; set; }

    [JsonProperty("about_me")]
    public string AboutMe { get; set; }

    [JsonProperty("question_count")]
    public int QuesionCount { get; set; }

    [JsonProperty("answer_count")]
    public int AnswerCount { get; set; }

    [JsonProperty("view_count")]
    public int ViewCount { get; set; }

    [JsonProperty("up_vote_count")]
    public int UpVoteCount { get; set; }

    [JsonProperty("down_vote_count")]
    public int DownVoteCount { get; set; }

    [JsonProperty("accept_rate")]
    public int AccpetRate { get; set; }

    [JsonProperty("association_id")]
    public Guid AssociationId { get; set; }

   [JsonProperty("badge_counts")]
    public Dictionary Badges { get; set; }
}


This class represents all of the properties for a User. The JsonProperty attribute specifies what the actual property looks like in the JSON response.

public interface IUserRepository
{
    StackUser GetUserById(params string[] ids);
}

public class Users : StackRepository<UserResponse>, IUserRepository
{
    public Users()
    {
        Method = "users";
    }

    public StackUser GetUserById(params string[] ids)
    {
        var userResponse = Get(ids);
        return userResponse.Users.FirstOrDefault();
    }
}

public class StackResponse : IStackResponse
{
    public int Total { get; set; }
    public int Page { get; set; }
    public int PageSize { get; set; }
}

public class UserResponse : StackResponse
{
    public List Users { get; set; }
}


Here I created a UsersRepository to consume all of the methods available for users and declared UsersResponse and a base StackResponse for the paging information that comes back on every request. Then within the UserResponse I get back the StackUser object off of UserResponse.Users

public abstract class StackRepository : IStackRepository
{
    public string Method { get; set; }
    public RequestOptions Options { get; set; }
    private const string ApiUrl = "http://api.stackoverflow.com/1.1/";

    public string Request(string request, RequestOptions options = null)
    {
        var client = new WebClient();
        var stackRequest = new StringBuilder(ApiUrl + request);        

        byte[] response = client.DownloadData(stackRequest.ToString());

        if(response == null)
        {
            throw new Exception(string.Format("No response from request {0}", request));
        }

        var decompress = new GZipStream(new MemoryStream(response), CompressionMode.Decompress);
        var reader = new StreamReader(decompress);
        string ret = reader.ReadToEnd();
        return ret;
    }

    public T Get(params string[] ids)
    {
        var response = Request(Method + string.Join(",", strings);
        return Deserialize(response);
    }

    public T Deserialize(string response)
    {
        return JsonConvert.DeserializeObject(response);
    }
}

public class StackOverflow : IStackOverflow
{
    IUserRepository _userRepo;

    public StackOverflow(IUserRepository userRepository)
    {
        _userRepo = userRepository;
    }

    public StackUser GetUserById(params string[] ids)
    {
        var users = _userRepo.GetUserById(ids);
        return users;
    }
}


The StackRepository class here takes in a Generic class that will represent the type of Response that will be returned from the Api, such as the UserResponse that I created above. To use the StackOverflow object, just do this…

var stackOverflow = new StackOverflow();
var user = stackOverflow.GetUserById("558672");

 

So that is the slightly more complicated way to do it. It takes a little bit more setup, but it makes it a little bit easier to work with and makes the objects re-usable.

Have fun with JSON.net!

UPDATE 2/8/2012

As per a guest recommendation in the comments, there actually is a third way to deserialize the data.

var client = new WebClient();
var stackRequest = new StringBuilder(ApiUrl + request);        

byte[] response = client.DownloadData(stackRequest.ToString());

if(response == null)
{
    throw new Exception(string.Format("No response from request {0}", request));
}

var decompress = new GZipStream(new MemoryStream(response), CompressionMode.Decompress);
var reader = new StreamReader(decompress);
string ret = reader.ReadToEnd();
dynamic userResponse = JObject.Parse(ret);
var displayName = userResponse.users[0].display_name;
Console.Write(displayName); 

So there you go, 3 ways to use JSON.net to work with a JSON Api!

Minify JavaScript using UglifyJS and NodeJS

On January 10, 2012, in NodeJS, by jonathancreamer

Minifying JavaScripts has many benefits. A few advantages are it reduces the amount of code the user has to download, removes unnecessary comments, and reduces the number of Http requests. There are many minify-ers out there, things such as YUI Compressor, JSMin, Google Closure Compiler, and UglifyJS.

I recently started using the standalone UglifyJS tool that can run in NodeJS. This makes the tool available via command prompt as well as accessing it inside of Node applications with require.

To use Uglify in Windows. First, download and install NodeJS. Once it is installed, you can then run applications in Command Prompt simply by typing node. It installs by default into C:\Program Files\NodeJS or C:\Program Files(x86)\NodeJS on a 64-bit machine.

It drops the node.exe, and the npm.bat file into that directory and makes it available in CMD by adding it to your %PATH%.

NPM is the Node Package Manager that was just recently made available for Windows. It allows you to download Node packages to be easily used in your projects.

The next step is to install UglifyJS and make it global so it’s available everywhere.

Open Command Prompt and run…

npm -g install uglify-js

This put’s the files for Uglify in the %AppData% file, usually around C:\Users\{username}\AppData\Roaming\npm\

As of 1/9/2012, there is a slight bug in the command to actually run Uglify, so in order to fix it, navigate to the folder just mentioned and find uglifyjs.cmd and replace it with…

:: Created by npm, please don't edit manually.
@IF EXIST "%~dp0"\"node.exe" (
  "%~dp0"\"node.exe"  "%~dp0\.\node_modules\uglify-js\bin\uglifyjs" %*
) ELSE (
  node  "%~dp0\.\node_modules\uglify-js\bin\uglifyjs" %*
)

Now, you will be able to just run Uglify by…

cd c:\place\where\files\are\
uglifyjs -o myFile.build.js myFile.js

And wham bam, you’ll find a nicely compressed file. NOTE: You also may need to restart the computer. Sometimes the changes to the path don’t kick in right away. You can string along as many files as you need to compress; the –o flag tells Uglify where to place the built file. Then you could save the commands out to some build.bat file and run it at your plessure.

Tagged with:  

When working with Entity Framework Code First, the database get’s generated for you… Duh!

You have control over several aspects of how this database get’s created.

First off are Data Annotations, such as Required, DefaultValue, ForeignKey, Key, etc.

Second is the Fluent Api which allows you to tap into the creation of the Database and remove all of those attributes off of your data classes.

You can specify the name of the database by passing a Name, or even a connectionString into the base constructor of your DbContext.

 

public class MyContext : DbContext
{
    public MyContext()
        base: ("MyDbName")
    {}
}

Lot’s of different control over the DB.

However, one thing that seems to be left out for now is explicitly naming your Primary Key constraints. By default, they come out looking something like… PK_USERS_FBC301?!?!?!? 

I think this is a default of SQL more than Code First’s fault or anything, but none the less it is kinda nasty.

The only way I have found to fix this problem is to tap into the Initialize method of the Context using either DropCreateDatabaseAlways, DropCreateDatabaseIfModelChanges, or by implementing your own version of IDatabaseInitializer. I did it like this…

 

// Somewhere in Global.asax
Database.SetInitializer(new DbInitializer());

// DbInitializer
public class DbInitializer : IDatabaseInitializer<MyContext>
{
    public void InitializeDatabase(MyDbcontext context)
        {
            if (context.Database.Exists())
            {
                if (!context.Database.CompatibleWithModel(true))
                {
                    string singleUserModeCommand =
                    string.Format("ALTER DATABASE [{0}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE",
                              context.Database.Connection.Database);
                    if (context.Database.Exists())
                    {
                        context.Database.ExecuteSqlCommand(singleUserModeCommand);
                        context.Database.Delete();
                    }
                    context.Database.Create();
                    Seed(context);
                }

            }
            else
            {
                context.Database.Create();
                Seed(context);
            }
        }

        protected void Seed(MyDbContext context)
        {
            FixPrimaryKeyConstraints(context);
        }

        private void FixPrimaryKeyConstraints(MyDbContext context)
        {
            const string sql =
                @"  SET NOCOUNT on 
                    DECLARE @cnt int
                    DECLARE @table varchar(128)
                    DECLARE @cmd varchar(500) 
                    --create table #rowcount (tablename varchar(128), rowcnt int)
                    DECLARE tables cursor for
                    SELECT table_name from information_schema.tables
	                    WHERE table_type = 'base table'
	                    ORDER BY table_name
                    OPEN tables
                    FETCH NEXT FROM tables into @table
                    WHILE @@fetch_status = 0
                    BEGIN
	                    DECLARE @TableName NVARCHAR(128)
	                    DECLARE @IndexName NVARCHAR(128)
	                    DECLARE @OldName NVARCHAR(128)
	                    DECLARE @NewName NVARCHAR(128)
	                    SELECT  @TableName = @table

	                    SELECT  @IndexName = C.CONSTRAINT_NAME
	                    FROM    INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK ,INFORMATION_SCHEMA.KEY_COLUMN_USAGE C
	                    WHERE   pk.TABLE_NAME = @TableName
		                    AND   CONSTRAINT_TYPE = 'PRIMARY KEY'
		                    AND   C.TABLE_NAME = PK.TABLE_NAME
		                    AND   C.CONSTRAINT_NAME = PK.CONSTRAINT_NAME

	                    SELECT  @OldName = @TableName + '.' + @IndexName
	                    SELECT  @NewName = 'PK_' + @TableName
	                    exec sp_rename @OldName, @NewName, 'INDEX'
                      FETCH NEXT FROM tables into @table
                    END
                    CLOSE tables 
                    DEALLOCATE tables";

            context.Database.ExecuteSqlCommand(sql);
        }
}

This file does a few things. First it detects changes to the DB, forces a drop if neccessary, then runs the seed.
The seed then calls the FixPrimaryKeyConstraints which loops over all of the tables in the Database and renames them PK_TableName.

Hope you enjoyed this Espresso Tip!