<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://devlicio.us/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Christopher Bennage : web</title><link>http://devlicio.us/blogs/christopher_bennage/archive/tags/web/default.aspx</link><description>Tags: web</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>Render Action</title><link>http://devlicio.us/blogs/christopher_bennage/archive/2012/04/30/render-action.aspx</link><pubDate>Mon, 30 Apr 2012 17:55:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:69726</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;It&amp;#8217;s common for a single web page to include data from many sources. Consider this screen shot from &lt;a href="http://silk.codeplex.com/"&gt;Project Silk&lt;/a&gt;. There are four separate items displayed.&lt;/p&gt;

&lt;p&gt;&lt;img class="right" src="http://dev.bennage.com/images/posts/many-concerns.png" alt="" /&gt;&lt;/p&gt;

&lt;p&gt;The primary concern of the page is displaying a list of vehicles. However it also displays some statistics and a set of reminders. I labeled the stats and reminders as orthogonal because they are (in a sense) independent of the primary concern. Finally, there is the ambient data of the currently logged in user. I call this data ambient because we expect it to be present on all the pages in the application.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s a common practice in MVC-style applications to map a single controller action to a view. That is, it is the responsibility of a single action to produce everything that is needed to render a particular web page.&lt;/p&gt;

&lt;p&gt;The difficulty with this approach is that &lt;em&gt;other pages&lt;/em&gt; often need to render the same orthogonal data. Let&amp;#8217;s examine the code for the action invoked by &lt;code&gt;\vehicle\list&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public ActionResult List()
{
    AddCountryListToViewBag();

    var vehicles = Using&amp;lt;GetVehicleListForUser&amp;gt;()
        .Execute(CurrentUserId);

    var imminentReminders = Using&amp;lt;GetImminentRemindersForUser&amp;gt;()
        .Execute(CurrentUserId, DateTime.UtcNow);

    var statistics = Using&amp;lt;GetFleetSummaryStatistics&amp;gt;()
        .Execute(CurrentUserId);

    var model = new DashboardViewModel
                    {
                        User = CurrentUser,
                        VehicleListViewModel = new VehicleListViewModel(vehicles),
                        ImminentReminders = imminentReminders,
                        FleetSummaryStatistics = statistics
                    };

    return View(model);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Disregarding how you might feel about the &lt;code&gt;Using&amp;lt;T&amp;gt;&lt;/code&gt; method to invoke commands and other such details, I want you to focus on the fact that the controller is &lt;em&gt;composing&lt;/em&gt; a model. We generate a number of smaller viewmodels and then compose them into an instance of &lt;code&gt;DashboardViewModel&lt;/code&gt;. The class &lt;code&gt;DashboardViewModel&lt;/code&gt; only exists to tie together the four, otherwise independent data.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Personally, I prefer to avoid classes like &lt;code&gt;DashboardViewModel&lt;/code&gt; and simply rely on dynamic typing in the view. However, others feel strongly about having IntelliSense support in the view.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Project Silk had separate actions just to serve up JSON:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public JsonResult JsonList()
    {
        var list = Using&amp;lt;GetVehicleListForUser&amp;gt;()
            .Execute(CurrentUserId)
            .Select(x =&amp;gt; ToJsonVehicleViewModel(x))
            .ToList();

        return Json(list);
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You&amp;#8217;ll notice that both &lt;code&gt;JsonList&lt;/code&gt; and &lt;code&gt;List&lt;/code&gt; use the same &lt;code&gt;GetVehicleListForUser&lt;/code&gt; command for retrieving their data. &lt;code&gt;JsonList&lt;/code&gt; also projected the data to a slightly different viewmodel.&lt;/p&gt;

&lt;h2&gt;Reducing the Code&lt;/h2&gt;

&lt;p&gt;While reevaluating this code for &lt;a href="https://github.com/liike/"&gt;Project Liike&lt;/a&gt;, we decided to employ &lt;a href="http://en.wikipedia.org/wiki/Content_negotiation"&gt;content negotiation&lt;/a&gt;. That is, we wanted a single endpoint, such as &lt;code&gt;\vehicle\list&lt;/code&gt;, to return different representations of the data based upon a requested format. If the browser requested JSON, then &lt;code&gt;\vehicle\list&lt;/code&gt; should return a list of the vehicles in JSON. If the browser requested markup, then the same endpoint should return HTML.&lt;/p&gt;

&lt;p&gt;First, we needed to eliminate the differences between the JSON viewmodel and the HTML viewmodel. Without going deep into details, this wasn&amp;#8217;t hard to do. In fact, it revealed that we had some presentation logic in the view that should not have been there. The real problem was that I wanted the action to look more like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public ActionResult List()
{
    var vehicles = Using&amp;lt;GetVehicleListForUser&amp;gt;()
        .Execute(CurrentUserId);

    return new ContentTypeAwareResult(vehicles);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Only, the view still needed the additional data of statistics and reminders. How should the view get it?&lt;/p&gt;

&lt;p&gt;We decided to use &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.html.childactionextensions.renderaction.aspx"&gt;RenderAction&lt;/a&gt;. RenderAction allows a view to invoke another action and render the results into the current view.&lt;/p&gt;

&lt;p&gt;We needed to break out the other concerns into their own actions. For the sake of example, we&amp;#8217;ll assume they are both on the &lt;code&gt;VehicleController&lt;/code&gt; and named &lt;code&gt;Reminders&lt;/code&gt; and &lt;code&gt;Statistics&lt;/code&gt;. Each of these action would be responsible for getting a focused set of data. Then in the (imaginary) view for &lt;code&gt;List&lt;/code&gt; we could invoke the actions like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// List.cshtml 
&amp;lt;ul&amp;gt;
@foreach (var vehicle in Model)
{
    &amp;lt;li&amp;gt;@vehicle.Name&amp;lt;/li&amp;gt;
}
&amp;lt;/ul&amp;gt;

&amp;lt;section role=&amp;quot;reminders&amp;quot;&amp;gt;
@{ Html.RenderAction( &amp;quot;Reminders&amp;quot;, &amp;quot;Vehicle&amp;quot;) }
&amp;lt;/section&amp;gt;

&amp;lt;section role=&amp;quot;statistics&amp;quot;&amp;gt;
@{ Html.RenderAction( &amp;quot;Statistics&amp;quot;, &amp;quot;Vehicle&amp;quot;) }
&amp;lt;/section&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;Note that each action has it&amp;#8217;s on associated view.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;The value of using RenderAction is that we where able to create very simple actions on our controllers. We were also able to reuse the actions for rendering both markup and JSON.&lt;/p&gt;

&lt;p&gt;A secondary benefit is the separation of concerns. For example, because we moved the responsibility of composition from the controller into the view, a designer could now revise the view for the &lt;code&gt;\vehicle\list&lt;/code&gt; without needing to touch the code. They could remove any of the orthogonal concerns or even add new ones without introducing any breaking changes.&lt;/p&gt;

&lt;h2&gt;The Downside&lt;/h2&gt;

&lt;p&gt;There are a few caveats with this approach.&lt;/p&gt;

&lt;p&gt;First, don&amp;#8217;t confuse RenderAction with &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.html.renderpartialextensions.renderpartial.aspx"&gt;RenderPartial&lt;/a&gt;. RenderAction is for invoking a completely independent action, with its own view and model. RenderPartial is simply for renders a view based on a model passed to it (generally derived from the main viewmodel).&lt;/p&gt;

&lt;p&gt;Secondly, avoid using RenderAction to render a form. It&amp;#8217;s likely won&amp;#8217;t work the way you&amp;#8217;d expect.This means that any form rendering will need to occur in your primary view.&lt;/p&gt;

&lt;p&gt;Thirdly, using RenderAction breaks the &lt;a href="http://en.wikipedia.org/wiki/Model-view-controller#Overview"&gt;model-view-controller&lt;/a&gt; pattern. What I mean is that, in MVC, it&amp;#8217;s assumed that the view does nothing more than render a model. Controllers invoke a view, and not vice versa. Using RenderAction breaks this rule. Personally, I have no problem breaking the rule when it results in code that is more simple and more easily maintained. Isn&amp;#8217;t that the whole &lt;a href="http://dev.bennage.com/blog/2008/03/30/the-roots-of-best-practices/"&gt;point of best practices&lt;/a&gt; anyway?&lt;/p&gt;


&lt;em&gt;Comment on this post at &lt;a href="http://dev.bennage.com/blog/2012/04/27/render-action/"&gt;dev.bennage.com&lt;/a&gt;&lt;/em&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=69726" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/web/default.aspx">web</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/asp.net+mvc/default.aspx">asp.net mvc</category></item><item><title>Mobile Development: Detecting Devices &amp; Features</title><link>http://devlicio.us/blogs/christopher_bennage/archive/2011/10/20/mobile-development-detecting-devices-amp-features.aspx</link><pubDate>Thu, 20 Oct 2011 17:50:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:68307</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;&lt;em&gt;Take this post cum granlis salis. I&amp;#8217;m trying to figure this stuff out and I&amp;#8217;m thinking out loud.&lt;/em&gt;&lt;/p&gt; &lt;h2&gt;Background&lt;/h2&gt; &lt;p&gt;Whenever a browser makes a request, it includes a string identifying itself to the server. We commonly refer to this as the &lt;em&gt;user agent string&lt;/em&gt;. This string identifies the browser and the platform and the version and a great deal more such nonsense.&lt;/p&gt; &lt;p&gt;&lt;img style="float:right;" src="http://dev.bennage.com/images/posts/tower-babel.jpg" alt="" /&gt;&lt;/p&gt; &lt;p&gt;This sounds great in theory. We should be able to use this data to optimize what&amp;#8217;s being sent to the (mobile) browser. However, there&amp;#8217;s been something of a &lt;a href="http://webaim.org/blog/user-agent-string-history/" title="History of the browser user-agent string by Aaron Andersen"&gt;sordid history for user agent strings&lt;/a&gt;. In retrospect, we&amp;#8217;ve realized that &lt;a href="http://en.wikipedia.org/wiki/User_agent#User_agent_sniffing"&gt;user agent sniffing&lt;/a&gt; is a tool that has often hurt more than it has helped.&lt;/p&gt; &lt;p&gt;We&amp;#8217;ve learned to &lt;em&gt;favor feature detection over browser detection&lt;/em&gt; (or device detection). Take a look at &lt;a href="http://www.modernizr.com/"&gt;modernizr&lt;/a&gt; and &lt;a href="http://haz.io/"&gt;haz.io&lt;/a&gt; for more on the that front. The success of feature detection has also resulted in a shift from server logic to client logic. We detect features on the client but we detect user agent strings on the server, before we send anything to the client.&lt;/p&gt; &lt;p&gt;How does all this play into the mobile web? One of the key mobile features we are interested in is &lt;em&gt;screen size&lt;/em&gt;. Luckily for us, the W3C has blessed us with &lt;a href="http://www.w3.org/TR/css3-mediaqueries/"&gt;media queries&lt;/a&gt;. In a nutshell, media queries allow you to conditionally apply CSS based properties of the display device. This has given rise to something known as &lt;a href="http://www.alistapart.com/articles/responsive-web-design/"&gt;Responsive Web Design&lt;/a&gt;. Responsive Web Design is about having a single set of markup whose layout can &lt;em&gt;respond&lt;/em&gt; to the device&amp;#8217;s display capabilities. Unfortunately, there are a few &lt;a href="http://www.webdesignshock.com/responsive-design-problems/"&gt;rough edges&lt;/a&gt; with this approach.&lt;/p&gt; &lt;h2&gt;Moving Backwards…&lt;/h2&gt; &lt;p&gt;In the mobile world, client-side feature detection has a few drawbacks. It requires extra code to be sent to the browsers and it takes additional processing on the client. It&amp;#8217;s also likely that you&amp;#8217;ll end up sending more than is really needed (or that you&amp;#8217;ll need to make additional requests).&lt;/p&gt; &lt;p&gt;One solution to this conundrum is to use the open source &amp;#8220;database&amp;#8221; called &lt;a href="http://wurfl.sourceforge.net/"&gt;WURLF&lt;/a&gt;. You can query WURL with a user agent string and it will return a set of capabilities. I think of it as &lt;em&gt;feature detection&lt;/em&gt; on the server. Though admittedly it&amp;#8217;s a bit misleading to call it that.&lt;/p&gt; &lt;p&gt;This means your server can ask questions like &amp;#8220;Does this client support HTML5? If no, what do they support?&amp;#8221; before the first response is even sent.&lt;/p&gt; &lt;p&gt;WURLF has &lt;a href="http://scientiamobile.com/"&gt;commercial support&lt;/a&gt; and a &lt;a href="http://wurfl.sourceforge.net/dotNet/"&gt;C# API&lt;/a&gt;. For ASP.NET developers, &lt;a href="http://51degrees.mobi/"&gt;51Degrees&lt;/a&gt; has an open source project called &lt;a href="http://51degrees.codeplex.com/"&gt;Foundation&lt;/a&gt; that is built on top of WURL. It uses an HttpModule to automatically query WURL and populate the &lt;a href="http://msdn.microsoft.com/en-us/library/system.web.httprequest"&gt;Request.Browser&lt;/a&gt;. Setting up WURLF without Foundation takes a little bit more work, but not too much. Both are available on Nuget: &lt;a href="http://www.nuget.org/List/Packages/WURFL_Official_API"&gt;WURL&lt;/a&gt; and &lt;a href="http://nuget.org/List/Packages/51Degrees.mobi"&gt;51Degrees&lt;/a&gt;.&lt;/p&gt; &lt;h2&gt;What should you do?&lt;/h2&gt; &lt;p&gt;I don&amp;#8217;t think that there is a cut and dry answer &lt;em&gt;at the moment&lt;/em&gt;. What you do depends heavily on your target audience. If you are targeting the &lt;a href="http://gs.statcounter.com/#mobile_browser-na-monthly-201009-201109"&gt;North American market&lt;/a&gt; there&amp;#8217;s a good chance you&amp;#8217;ll be okay with a single set of markup, going with a responsive &lt;a href="http://www.lukew.com/ff/entry.asp?933"&gt;mobile-first&lt;/a&gt; design. In other words, there would be no need for something like WURLF.&lt;/p&gt; &lt;p&gt;However, you might need a &lt;em&gt;very broad reach&lt;/em&gt; or you might be targeting a market heavy in &lt;a href="http://en.wikipedia.org/wiki/Feature_phone"&gt;feature phones&lt;/a&gt; or something else that&amp;#8217;s &lt;a href="http://gs.statcounter.com/#mobile_browser-sa-monthly-201009-201109"&gt;very different from North America&lt;/a&gt;. In those cases, it is good to understand your options.&lt;/p&gt;

&lt;em&gt;Comment on this post at &lt;a href="http://dev.bennage.com/blog/2011/10/19/mobile-developent-and-device-detection/"&gt;dev.bennage.com&lt;/a&gt;&lt;/em&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=68307" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/web/default.aspx">web</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/mobile/default.aspx">mobile</category></item><item><title>Being a New Kid on the Mobile Block</title><link>http://devlicio.us/blogs/christopher_bennage/archive/2011/10/10/being-a-new-kid-on-the-mobile-block.aspx</link><pubDate>Mon, 10 Oct 2011 23:38:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:68278</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;The last few weeks I&amp;#8217;ve been trying get a finger on the pulse of &lt;em&gt;mobile web development&lt;/em&gt;. I wanted to identify the thought leaders, understand the big questions, and (perhaps mostly importantly) begin cataloging the practical considerations for building mobile experiences today.&lt;/p&gt; &lt;p&gt;Here&amp;#8217;s where I&amp;#8217;m at so far&amp;#8230;&lt;/p&gt;  &lt;h2&gt;What is &amp;#8216;the mobile web&amp;#8217;?&lt;/h2&gt; &lt;p&gt;&lt;span class="’has-pullquote’"&gt; The definition of &lt;em&gt;mobile web&lt;/em&gt; is quickly evolving. Devices are varied and the distinctions are blurring. If you think it&amp;#8217;s as simple as iOS, Android, &lt;em&gt;and Windows&lt;/em&gt; then you&amp;#8217;ll be surprised. (I do genuinely love my WP7). Personally, I think the distinction between mobile and desktop is fading more and more everyday. When I say &lt;em&gt;mobile web&lt;/em&gt; I am talking about HTML-based applications and not applications that are built natively for their respective platforms. Of course, there is debate over native apps versus web apps: when is one appropriate over the over? etc, etc. This is a question when intend to address in &lt;a href="http://liike.github.com/"&gt;Project Liike&lt;/a&gt;. &lt;/span&gt;&lt;/p&gt; &lt;h2&gt;Who to follow?&lt;/h2&gt; &lt;p&gt;I&amp;#8217;ve been following a mishmash of people, and I must confess that my process of qualifying them has been some haphazard. I&amp;#8217;m compiling a &lt;a href="http://twitter.com/#!/bennage/mobile-web" title="membership subject to change"&gt;list on twitter&lt;/a&gt;. A number of folks on this list are signatories of &lt;a href="http://futurefriend.ly/" title="advocates of standards based mobile web development"&gt;future friend.ly&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Other sources I&amp;#8217;ve been paying attention to are:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://www.alistapart.com/"&gt;A List Apart&lt;/a&gt; – &amp;#8220;For people who make websites.&amp;#8221;&lt;/li&gt; &lt;li&gt;&lt;a href="http://www.smashingmagazine.com/"&gt;Smashing Magainze&lt;/a&gt; – Lots of articles on design, web, and of course mobile.&lt;/li&gt; &lt;li&gt;&lt;a href="http://www.cloudfour.com/blog/"&gt;Cloud Four&lt;/a&gt; – Many recent and thorough posts exploring some of the big questions in mobile.&lt;/li&gt; &lt;li&gt;&lt;a href="http://www.yiibu.com/"&gt;Yiibu&lt;/a&gt; – They have a lot of interesting ideas, and they&amp;#8217;ve done some &lt;a href="http://www.yiibu.com/articles/practical-guide-to-nokia-browsers/"&gt;impressive work&lt;/a&gt; for Nokia.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;I&amp;#8217;ve also been reading through &lt;a href="http://shop.oreilly.com/product/9780596807795.do"&gt;&lt;em&gt;Programming the Mobile Web&lt;/em&gt;&lt;/a&gt; by &lt;a href="http://twitter.com/#!/firt"&gt;Maximiliano Firtman&lt;/a&gt;. The first few chapters are pretty scary for someone like myself who did not understand how diverse and scattered the mobile world is. (It&amp;#8217;s also funny to see how much has changed since the book was published in 2010.)&lt;/p&gt; &lt;p&gt;Anything you&amp;#8217;d recommend?&lt;/p&gt; &lt;h2&gt;The state of things&lt;/h2&gt; &lt;p&gt;&lt;em&gt;Caveat&lt;/em&gt;: &lt;em&gt;This is just Christopher&amp;#8217;s brain dump. Consider it merely food for thought.&lt;/em&gt;&lt;/p&gt; &lt;ul&gt; &lt;li&gt;There are many &lt;a href="http://techcrunch.com/2011/02/09/html5-versus-native-apps/"&gt;compeling&lt;/a&gt; &lt;a href="http://www.html5rocks.com/en/mobile/nativedebate.html"&gt;reasons&lt;/a&gt; for developing mobile web apps. Not to the complete exclusion of &lt;a href="http://www.webmonkey.com/2010/08/how-do-native-apps-and-web-apps-compare/"&gt;native apps&lt;/a&gt;, but &lt;a href="http://www.phonegap.com/"&gt;maybe?&lt;/a&gt;&lt;/li&gt; &lt;li&gt;You need to understand your target market and the devices that it uses. Don&amp;#8217;t make assumptions. You might be &lt;a href="http://gs.statcounter.com/#mobile_os-ww-monthly-201009-201109"&gt;surprised&lt;/a&gt;.&lt;/li&gt; &lt;li&gt;The space is changing, standards are evolving, solutions are being formulated. However, if you need to you need build an app today, there is still plently of &lt;a href="http://www.w3.org/TR/mobile-bp/" title="Yes, it’s a little old but still mostly good."&gt;pragmatic&lt;/a&gt; &lt;a href="http://mobilewebbestpractices.com/"&gt;advice&lt;/a&gt;.&lt;/li&gt; &lt;/ul&gt; &lt;p&gt;One more thought: don&amp;#8217;t jump to conclusions. You might read about something cool like &lt;a href="http://www.alistapart.com/articles/responsive-web-design/"&gt;&lt;em&gt;Responsive Web Design&lt;/em&gt;&lt;/a&gt;, but such cool and innovative techniques can be &lt;a href="http://www.cloudfour.com/css-media-query-for-mobile-is-fools-gold/" title="CSS Media Query for Mobile is Fool’s Gold"&gt;deceptive&lt;/a&gt;. Research and testing is your friend.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Comment on this post at &lt;a href="http://dev.bennage.com/blog/2011/10/10/being-a-new-kid-on-the-mobile-block/"&gt;dev.bennage.com.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=68278" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/web/default.aspx">web</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/html5/default.aspx">html5</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/mobile/default.aspx">mobile</category></item><item><title>Restarting Node.js When Your Source Changes</title><link>http://devlicio.us/blogs/christopher_bennage/archive/2011/08/09/restarting-node-js-when-your-source-changes.aspx</link><pubDate>Tue, 09 Aug 2011 08:47:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:68080</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>7</slash:comments><description>&lt;p&gt;I’m lazy. I remember reading somewhere that that was a desirable trait to have in a developer. I’m not sure where though, and honestly it’s just too much effort to &lt;span title="Bing + Google = Bingle!"&gt;bingle&lt;/span&gt; it. This laziness came to the forefront recently as I was playing with Node. &lt;/p&gt;  &lt;p&gt;In my &lt;a href="http://devlicio.us/blogs/christopher_bennage/archive/2011/07/28/node-js-on-windows.aspx" target="_blank"&gt;last post&lt;/a&gt;, I showed you how to spin up a quick web app using Node. As I was playing with this app, I found that I had to restart Node every time I made a change to the source. This meant I had to switch to the console, stop the process, start the process and THEN refresh my page to see the effect of my change. Too much work I say.&lt;/p&gt;  &lt;p&gt;So I wondered if Node had something built-in for monitoring changes to the file. I didn’t see anything useful from &lt;strong&gt;node.exe –help&lt;/strong&gt; and researching it on the Web is just &lt;em&gt;so&lt;/em&gt; tedious, so I decided to write my own solution.&lt;/p&gt;  &lt;h3&gt;Looking for Some Change&lt;/h3&gt;  &lt;p&gt;In .NET, there is a class &lt;a href="http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx" target="_blank"&gt;System.IO.FileSystemWatcher&lt;/a&gt;. With an instance of this class you can monitor the files in a directory for changes. I set it up like this:&lt;/p&gt;  &lt;p&gt;var watcher = new FileSystemWatcher();    &lt;br /&gt;watcher.Path = @&amp;quot;C:\node.js\stuff&amp;quot;;     &lt;br /&gt;watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName;     &lt;br /&gt;watcher.Filter = &amp;quot;*.js&amp;quot;;     &lt;br /&gt;    &lt;br /&gt;watcher.Changed += Changed;     &lt;br /&gt;watcher.Created += Changed;     &lt;br /&gt;watcher.Deleted += Changed;     &lt;br /&gt;watcher.Renamed += Renamed;     &lt;br /&gt;    &lt;br /&gt;// Begin watching     &lt;br /&gt;watcher.EnableRaisingEvents = true;&lt;/p&gt;  &lt;p&gt;The NotifyFilter property allows you to specify the sort of changes you are interested in. You can check out the full list &lt;a href="http://msdn.microsoft.com/en-us/library/system.io.notifyfilters.aspx" target="_blank"&gt;here&lt;/a&gt;. You’ll also notice that I used the Filter property to narrow it down just to js files.&lt;/p&gt;  &lt;p&gt;Next, there are a number of events to wire to respond to changes. I reused the same handler as much as I could because I always want to do the same thing: restart Node. It’s also not entirely obvious how these events relate to NotifyFilter, but I didn’t dig too deep into that. (I’m lazy remember.)&lt;/p&gt;  &lt;p&gt;It’s also important to set EnableRaisingEvents. If you don’t, then the (guess what) no event are raised.&lt;/p&gt;  &lt;h3&gt;Kill, Kill, Kill&lt;/h3&gt;  &lt;p&gt;Now whenever a significant change occurs, it’ll be time to restart Node. For this I used &lt;a href="http://msdn.microsoft.com/en-us/library/system.diagnostics.process.aspx" target="_blank"&gt;System.Diagnostics.Process&lt;/a&gt;. This is a bit of a tricky classs, with a number of not-so-obvious knobs to turn.&lt;/p&gt;  &lt;p&gt;First, I’ll need to get a reference to the Node process. I noticed in Task Manager that the process name was “node”. So I used &lt;/p&gt;  &lt;pre class="c#:nogutter:nocontrols" name="code"&gt;Process.GetProcessesByName(&amp;quot;node&amp;quot;)&lt;/pre&gt;

&lt;p&gt;This returns an array of processes, and so I did this:&lt;/p&gt;

&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;var matches = Process.GetProcessesByName(&amp;quot;node&amp;quot;);

matches.ToList().ForEach(match =&amp;gt; {
    Console.WriteLine(&amp;quot;attempting to close node.js [&amp;quot; + match.Id + &amp;quot;]&amp;quot;);
    match.Kill();
    match.WaitForExit(300); // it shouldn’t take this long, we’re just being cautious
    Console.WriteLine(&amp;quot;successfully closed&amp;quot;);&lt;/pre&gt;
Admittedly, this is hitting it with a hammer. It’s okay, because this is just a &lt;strong&gt;quick&lt;/strong&gt; and &lt;strong&gt;dirty&lt;/strong&gt; helper tool for me and not a production application. 

&lt;p&gt;After killing the process, I’ll want to start another one. Now, I don’t care for another console window to pop up each time I restart, instead I’d like to simply redirect the input and output to my little helper app. This can be a little tricky, and I had to do some experimentation to find the right combination in order keep things from hanging. If you find it misbehaving, I recommend &lt;a href="http://stackoverflow.com/search?q=processstartinfo" target="_blank"&gt;searching StackOverflow&lt;/a&gt;. I found several useful questions there. One of the keys that came up more than once was capturing &lt;em&gt;and&lt;/em&gt; closing the stream for the standard input.&lt;/p&gt;

&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;var start = new ProcessStartInfo();
start.FileName = @&amp;quot;C:\node.js\node.exe&amp;quot;;
start.UseShellExecute = false; // the starts the process directly, as opposed to going thu the shell
start.CreateNoWindow = true; // we don’t want a new window
start.RedirectStandardOutput = true;
start.RedirectStandardInput = true;
start.Arguments = Path.Combine(@&amp;quot;C:\node.js\stuff&amp;quot;, @&amp;quot;server.js&amp;quot;);

var node = new Process();
node.EnableRaisingEvents = true;
node.OutputDataReceived += OutputHandler;
node.StartInfo = start;
node.Start();

node.Refresh(); // refreshing the metadata stored in the instance of Process 
Console.WriteLine(node.ProcessName);
Console.WriteLine(&amp;quot;[&amp;quot; + node.Id + &amp;quot;] node.exe started&amp;quot;);

// close the input, we won&amp;#39;t use it
var input = node.StandardInput;
input.Close();

// and now for the output
node.BeginOutputReadLine();&lt;/pre&gt;

&lt;p&gt;First we create an object that contains the configuration for starting an instance of Node. Notice that we are passing in the server.js file as an argument. &lt;/p&gt;

&lt;p&gt;Also note that after starting the process, I call Refresh. I need to do this so that I’ll have the correct info to write out to the console. This data is not captured automatically.&lt;/p&gt;

&lt;p&gt;Finally, I handled the redirection of the input and output.&lt;/p&gt;

&lt;p&gt;The complete code for the app is available at &lt;a href="https://gist.github.com/1108727"&gt;https://gist.github.com/1108727&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Epilogue&lt;/h3&gt;

&lt;p&gt;This is very much a hack and I am not an expert on the proper usage of these classes. Please feel free to offer improvements.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=68080" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/development+tools/default.aspx">development tools</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/web/default.aspx">web</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/javascript/default.aspx">javascript</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/.NET/default.aspx">.NET</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/Tips+_2600_amp_3B00_+Tricks/default.aspx">Tips &amp;amp; Tricks</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/nodejs/default.aspx">nodejs</category></item><item><title>Things I’d Like To Present</title><link>http://devlicio.us/blogs/christopher_bennage/archive/2010/01/08/things-i-d-like-to-present.aspx</link><pubDate>Fri, 08 Jan 2010 11:32:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:54940</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;In case you are not familiar with &lt;a href="http://visitmix.com/" target="_blank"&gt;MIX&lt;/a&gt;, it is a conference from Microsoft focusing on the collaboration of design and development. Admittedly, the sessions tend to favor the developer, but there is always excellent design and UX content.&lt;/p&gt;  &lt;p&gt;&lt;a title="voting for MIX sessions" href="http://visitmix.com/opencallvote/?query=Christopher%20Bennage" target="_blank"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;margin-left:0px;border-top:0px;margin-right:0px;border-right:0px;" title="Mix10_Vote_grn_240" border="0" alt="Mix10_Vote_grn_240" align="right" src="http://devlicious.com/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/christopher_5F00_bennage/Mix10_5F00_Vote_5F00_grn_5F00_240_5F00_44742D31.jpg" width="184" height="244" /&gt;&lt;/a&gt; There was an open call for presentations this year and the community gets to choose which of the proposals will be selected. There are a number of &lt;a href="http://visitmix.com/opencallvote/" target="_blank"&gt;excellent proposals&lt;/a&gt; and I encourage you to go check out the list and vote for the sessions that you are genuinely interested in. (Even if you won’t be attending, the sessions will be broadcast.)&lt;/p&gt;  &lt;p&gt;Here are some sessions that I proposed for MIX10:&lt;/p&gt;  &lt;h3&gt;Cross Compiling Games for Silverlight &amp;amp; XNA&lt;/h3&gt;  &lt;p&gt;Our friend and Silverlight MVP, &lt;a href="http://blogs.silverarcade.com/silverlight-games-101/" target="_blank"&gt;Bill Reiss&lt;/a&gt;, has created an incredible library that enables you to cross compile XNA games for Silverlight. The library is called &lt;a title="a library for cross compiling XNA and Silverlight games" href="http://silversprite.codeplex.com/" target="_blank"&gt;SilverSprite&lt;/a&gt; and we feature it on Silver Arcade. (Wow, that’s a lot of ‘silvers’ in one paragraph.)&lt;/p&gt;  &lt;p&gt;In this session, we’d write a simple game for XNA (discussing some of the basic of game dev along the way) and then port the game over to Silverlight.&lt;/p&gt;  &lt;p&gt;This is an area where I wish I could spend more time. I love game development, but it’s always taking a back burner to other projects.   &lt;br /&gt;&lt;a title="Cross Compiling Games for Silverlight &amp;amp; XNA" href="http://visitmix.com/opencallvote/Entry?entryId=CROSSC046" target="_blank"&gt;[vote for this]&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;LinqToSQL and EntityFramework Profilers: Case Study&lt;/h3&gt;  &lt;p&gt;If you aren’t already familiar with the UberProf suite of ORM profilers, you can read tales of the development on &lt;a href="http://ayende.com/Blog/category/561.aspx" target="_blank"&gt;Ayende’s blog&lt;/a&gt;. Rob and I built the UI side of the application, and we learned a lot in the process. I’d like to do a talk were we discuss the challenges of the project, how we solved them, and what we did wrong. &lt;/p&gt;  &lt;p&gt;Yes, NHProf will be included too. (I submitted a case study for it last year, and it didn’t get picked. I have to sneak it in).&amp;#160; &lt;/p&gt;  &lt;p&gt;A few interesting aspects: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;we built this using MVVM, but well before &lt;a href="http://www.codeplex.com/caliburn" target="_blank"&gt;Caliburn&lt;/a&gt; reached maturity. &lt;/li&gt;    &lt;li&gt;the four separate apps (NHProf, EFProf, L2SProf, HProf) all use a single code base.&lt;/li&gt;    &lt;li&gt;we’re about to port the project from WPF to Silverlight.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;a title="LinqToSQL and EntityFramework Profilers: Case Study" href="http://visitmix.com/opencallvote/Entry?entryId=LINQTO047" target="_blank"&gt;[vote for this]&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;Silver Arcade: Case Study&lt;/h3&gt;  &lt;p&gt;This is a presentation that Rob and I have made a couple of times. Most recently at the Orlando .NET Users Group. We walk through the actual code for &lt;a href="http://www.silverarcade.com" target="_blank"&gt;Silver Arcade&lt;/a&gt; explaining the philosophy, design choices and mistakes we made along the way.&lt;/p&gt;  &lt;p&gt;For MIX, we would focus more design and UX choices, such as the separation of the behaviors from the views. However, we like to have a lot of audience interaction and tend to follow where ever the questions led (especially those leading questions that &lt;a href="http://scottdensmore.typepad.com/" target="_blank"&gt;Scott Densmore&lt;/a&gt; tends to ask). &lt;/p&gt;  &lt;p&gt;Silver Arcade is also interesting because&amp;#160; we deliberately used a number of newer hipper technologies; including Azure, ASP.NET MVC, jQuery, MEF, NHibernate and so on.   &lt;br /&gt; &lt;a title="case study of Silver Arcade" href="http://visitmix.com/opencallvote/Entry?entryId=SILVER048" target="_blank"&gt;[vote for this]&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;Thanks!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=54940" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/WPF/default.aspx">WPF</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/Game+Development/default.aspx">Game Development</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/fun/default.aspx">fun</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/XNA/default.aspx">XNA</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/Software+Architecture/default.aspx">Software Architecture</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/web/default.aspx">web</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/MVC/default.aspx">MVC</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/Presentations/default.aspx">Presentations</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/UI/default.aspx">UI</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/UI+Patterns/default.aspx">UI Patterns</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/XAML/default.aspx">XAML</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/UX/default.aspx">UX</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/Caliburn/default.aspx">Caliburn</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/viewmodel/default.aspx">viewmodel</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/mvvm/default.aspx">mvvm</category></item><item><title>Get Firebug</title><link>http://devlicio.us/blogs/christopher_bennage/archive/2007/03/06/get-firebug.aspx</link><pubDate>Tue, 06 Mar 2007 22:23:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:14682</guid><dc:creator>Christopher Bennage</dc:creator><slash:comments>6</slash:comments><description>&lt;p&gt;If you are a Web developer, and you are not using Firebug, stop what you are doing and go &lt;a href="http://www.getfirebug.com/"&gt;install it immediately&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;I first heard about Firebug on &lt;a href="http://west-wind.com/WebLog/posts/10019.aspx"&gt;Rick Strahl's blog&lt;/a&gt; a couple of months ago, but in the flurry of work I promptly forgot it.&amp;nbsp; A couple of days ago a friend was listing the reasons that why Firefox pwns IE and Firebug was the first.&lt;br&gt;&lt;/p&gt;&lt;p&gt;Firebug is an add-on for Firefox.&amp;nbsp; It allows you to inspect the details of the currently loaded page.&amp;nbsp; You can visually inspect the DOM, execute JavaScript snippets on the fly, and more.&amp;nbsp; I'm thoroughly impressed.&lt;/p&gt;&lt;p&gt;My feature du jour is the way it displays the &lt;a href="http://www.brainjar.com/css/positioning/"&gt;CSS box model&lt;/a&gt; for the currently selected element.&lt;/p&gt;&lt;p&gt; &lt;img src="http://bluespireconsulting.com/blogPostPics/firebug.jpg" title="Firebug Screenshot" alt="Firebug Screenshot" height="384" width="442"&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;I'm not going to repeat the list of features here, you can get that from the &lt;a href="http://www.getfirebug.com/"&gt;Firebug page&lt;/a&gt;.&amp;nbsp; If you have not tried it, go check it out.&lt;br&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=14682" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/web/default.aspx">web</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/dom/default.aspx">dom</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/javascript/default.aspx">javascript</category><category domain="http://devlicio.us/blogs/christopher_bennage/archive/tags/css/default.aspx">css</category></item></channel></rss>