<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
 <channel>
  <title>Technical Taco</title>
  <link>https://otac0n.com/</link>
  <atom:link href="https://otac0n.com/blog/rss.xml" rel="self" type="application/rss+xml" />
  <description>I'm just some guy, you know?</description>
  <language>en-us</language>
  <copyright>John Gietzen</copyright>
  <lastBuildDate>Sat, 18 Apr 2026 00:24:36 +0000</lastBuildDate>
  <managingEditor>john@gietzen.net (John Gietzen)</managingEditor>
  <webMaster>john@gietzen.net (John Gietzen)</webMaster>
  <item>
   <title>Building a Metal Gear Mk.II-Inspired Self-Balancing Robot (Part 4: Traction and Balance)</title>
   <link>https://otac0n.com/blog/2026/04/17/building-a-metal-gear-mk.ii-inspired-self-balancing-robot-part-4-traction-and-balance.html</link>
   <pubDate>Fri, 17 Apr 2026 00:00:00 +0000</pubDate>
   <guid isPermaLink="false">https://otac0n.com/blog/2026/04/17/building-a-metal-gear-mk.ii-inspired-self-balancing-robot-part-4-traction-and-balance</guid>
   <description>
&lt;h2 id=&quot;iterating-on-a-tire-design&quot;&gt;Iterating on a Tire Design&lt;/h2&gt;

&lt;p&gt;The game designers for the Mk.II added a distinctive tread pattern to the wheels, and to me it looked both functional and visually appealing. The tread’s angular pattern resembles a circuit board which is quite fitting to the personality of the bot.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/mk.ii-tread.png&quot; alt=&quot;Tread Close-up&quot; /&gt;&lt;/p&gt;

&lt;p&gt;In order to replicate this pattern, I had to make use of the 3rd-party Curves Workbench in FreeCAD. This feature projects curved surfaces onto a flat sketch, letting you use familiar tools and constraints. Surprisingly, this turned out to be one of the easiest tasks on the bot, thanks to the simplicity of the workbench.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/mk.ii-tread-sketch.png&quot; alt=&quot;Tread Sketch&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The first version of the tire was printed with basic slicer settings in TPU. I expected TPU’s softness to aid in traction, but I immediately learned that it was simply too smooth to get anywhere. There was, however, one slicer trick I knew I could try: fuzzy walls.&lt;/p&gt;

&lt;p&gt;The first of my working prototypes used these fuzzy-walled tires. While they absolutely improved performance, they still did not have very much traction on hard surfaces (even slightly rough ones). Only on carpet did this iteration have anywhere near enough traction to balance its weight.&lt;/p&gt;

&lt;div class=&quot;embed-container&quot;&gt;
  &lt;video width=&quot;540&quot; height=&quot;960&quot; controls=&quot;&quot;&gt;
    &lt;source src=&quot;/blog/images/mk.ii/traction.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
&lt;/div&gt;

&lt;p&gt;My friend Arthur, who printed the whole first prototype for me, shared a trick he used in combat robotics: coat the wheels with &lt;a href=&quot;https://amzn.to/47avufn&quot;&gt;latex paint&lt;/a&gt; to give them extra traction. This worked, but it wore off far too quickly. Arthur also encouraged me to join him at a couple of his robotics competitions, and there I met someone who shared a solution to this problem using urethane rubber casting.&lt;/p&gt;

&lt;h3 id=&quot;molding&quot;&gt;Molding&lt;/h3&gt;

&lt;p&gt;From the combat robotics meetup, I learned that designing a tire mold was pretty easy: subtract the tire from a solid block and slice it into 4 parts. I grabbed some 30A Hardness urethane and, due to the complex tread pattern, I chose to purchase some mold release as well.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://amzn.to/3NLCpF9&quot;&gt;Liquid Urethane&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://amzn.to/4bD1Lx7&quot;&gt;Mold Release&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I secured the wheels into the center of the molds, screwed them down, and poured the rubber.&lt;/p&gt;

&lt;div class=&quot;embed-container&quot;&gt;
  &lt;video width=&quot;600&quot; height=&quot;682&quot; playsinline=&quot;&quot; autoplay=&quot;&quot; muted=&quot;&quot; loop=&quot;&quot;&gt;
    &lt;source src=&quot;/blog/images/mk.ii/molding.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
&lt;/div&gt;

&lt;p&gt;The final iteration of the wheels came out great. The sprues (extra bits) were easily cut off by passing a hobby knife between the lid and the rest of the mold. The rubber tires have performed well on a variety of surfaces, both soft and hard. With traction solved, the next challenge was stability.&lt;/p&gt;

&lt;h2 id=&quot;balance-logic&quot;&gt;Balance Logic&lt;/h2&gt;

&lt;p&gt;Getting a bot to balance is theoretically straightforward. Similar to a car in cruise control, it’s largely a problem of controlling a single variable. In the case of the car, the variable would be the speed; for the Mk.II, it is the pitch angle. PID controllers are a very common way to do this since they model many types of problems reasonably well. PID controllers relate the difference in the target variable to some other output, such as throttle or torque. Their robustness comes from their use of the “present” (the Proportional term), the “past” (the Integral term), and the “future” (the Derivative term).&lt;/p&gt;

&lt;p&gt;In practice, optimizing only a single variable won’t work without precise calibration. So, we have to control an additional variable: the target pitch angle. If our robot drifts to one side or another, we can use a second PID controller to adjust the target pitch in the opposite direction.&lt;/p&gt;

&lt;p&gt;This turns out to be sufficient to get the bot to balance. Here are some resources to learn more about this specific arrangement and PID tuning in general:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/simplefoc/Arduino-FOC-balancer?tab=readme-ov-file#control-algorithm&quot;&gt;Arduino-FOC-balancer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://pidexplained.com/how-to-tune-a-pid-controller/&quot;&gt;How to Tune a PID Controller&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;embed-container&quot;&gt;
  &lt;video width=&quot;540&quot; height=&quot;764&quot; controls=&quot;&quot;&gt;
    &lt;source src=&quot;/blog/images/mk.ii/prototype.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
&lt;/div&gt;

&lt;h3 id=&quot;dual-board-control&quot;&gt;Dual Board Control&lt;/h3&gt;

&lt;p&gt;Having seen good results with the small-scale prototype, I began putting together the full-sized bot. Still, the testing showed some issues that needed to be addressed. The ESP32-S3 only supports BLE (Bluetooth Low Energy) but all of the controllers I wanted to use needed Bluetooth Classic. In addition, the IMU I had purchased gave &lt;em&gt;incredibly&lt;/em&gt; noisy data but only intermittently.&lt;/p&gt;

&lt;p&gt;I purchased an &lt;a href=&quot;https://amzn.to/4bPS3bI&quot;&gt;ESP32 DevKit v1&lt;/a&gt; and tested it with the small scale prototype. While it looked like it would have the specs needed to run the bot, it turned out to be very difficult to get a 1khz control loop to run smoothly. This seemed to put me in a worse position at first, but I realized that I had written-off a perfectly good solution: using two boards together.&lt;/p&gt;

&lt;p&gt;Using both the STM32 and ESP32 allowed me to leverage their individual strengths. My STM32 Discovery has an onboard IMU and the performance needed to run the balance control loop. The ESP32 can asynchronously communicate with many clients at once: Bluetooth, WiFi, UART, etc. I chose to use &lt;a href=&quot;https://github.com/MaJerle/lwpkt&quot;&gt;lwpkt&lt;/a&gt; on top of UART to frame messages between the boards and to reject bad packets.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/dataflow.png&quot; alt=&quot;Dataflow Diagram&quot; /&gt;&lt;/p&gt;
&lt;div class=&quot;alt&quot; style=&quot;display: none&quot;&gt;&lt;pre&gt;&lt;code&gt;
language: mermaid
flowchart LR
  ds3
  xinput
  subgraph bot
    esp32[ESP32 DEVKITV1]
    stm32[STM32F411E-DISCO]
    esp32 --UART (Input &amp;amp; Console)--&amp;gt; stm32
    stm32 --UART (Metrics &amp;amp; Logs)--&amp;gt; esp32
  end
  xinput --USB (Input)--&amp;gt; linq
  ds3 --Bluetooth (Input)--&amp;gt; esp32
  linq --UDP:2008 (Input)--&amp;gt; esp32
  linq --UDP:2014 (Console)--&amp;gt; esp32
  esp32 --UDP:2008 (Metrics)--&amp;gt; telegraf
  esp32 --UDP:2014 (Logs)--&amp;gt; telegraf
  subgraph pc
    linq[C# Desktop App]
    grafana[Grafana]
    influx[(InfluxDB)]
    telegraf[Telegraf]
    grafana &amp;lt;--HTTP:8086--&amp;gt; influx
    linq &amp;lt;--HTTP:8086--&amp;gt; influx
    telegraf --HTTP:8086--&amp;gt; influx
  end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&quot;assembly&quot;&gt;Assembly&lt;/h3&gt;

&lt;p&gt;With the decision to use two microcontroller boards came the requirement to mount them securely. I designed a set of lightweigth brackets to hold the boards together.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/dual-board.png&quot; alt=&quot;Dual Board CAD Rendering&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The Mk.II model in game has a back-panel that resembles a 1990’s camcorder. On the back, it says “整備ケーブルコネクタ口 ケーブルが挿す上下が気を付けろ” which Google tells me means “Maintenance Cable Port: Pay Attention to Connector Orientation”. While I’m a stickler for details, I decided that &lt;a href=&quot;https://amzn.to/4sTbSEX&quot;&gt;USB-C Panel Mount&lt;/a&gt; connectors would be acceptable. These were connected as the boards were installed with the help of a couple of adapters:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://amzn.to/4bVluIz&quot;&gt;USB-mini to USB-C Connectors&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://amzn.to/4bi1D7d&quot;&gt;90 Degree USB-micro to USB-mini Connectors&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also added an &lt;a href=&quot;https://amzn.to/4uD0oai&quot;&gt;external USB-B&lt;/a&gt; cable to represent the Mk.II’s “tentacle.” In the game, he uses it to manipulate both objects and computers. While I don’t yet have the ability to make a prehensile arm, I was able to give him mild hacking abilities.&lt;/p&gt;

&lt;div class=&quot;embed-container&quot;&gt;
  &lt;video width=&quot;1920&quot; height=&quot;1080&quot; controls=&quot;&quot;&gt;
    &lt;source src=&quot;/blog/images/mk.ii/flipper.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
&lt;/div&gt;

&lt;h3 id=&quot;phantom-vibration&quot;&gt;Phantom Vibration&lt;/h3&gt;

&lt;p&gt;Once fully assembled, however, the Mk.II developed an odd vibration. I first suspected this to be caused by excessively high PID coefficients.&lt;/p&gt;

&lt;div class=&quot;embed-container&quot;&gt;
  &lt;video width=&quot;960&quot; height=&quot;540&quot; controls=&quot;&quot;&gt;
    &lt;source src=&quot;/blog/images/mk.ii/vibration.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
&lt;/div&gt;

&lt;p&gt;However, no amount of tuning could remove the oscillation. After chatting with the folks in the SimpleFOC discord again, I learned that the actual source of the issue was the placement of the accelerometer away from the center of rotation. My decision to pivot to the STM32 Discovery board placed the IMU several centimeters above the center of mass.&lt;/p&gt;

&lt;p&gt;@copper280z told me that, in a configuration like this, the accelerometer will feel forces from rotation which it cannot distinguish from gravity. While this made sense, I was intrigued to learn that the effect can be subtracted out using the gyroscope if the exact distance from the center of rotation is known.&lt;/p&gt;

&lt;p&gt;At the time, I did not have the gyroscope working. I had to debug the Adafruit library to add support for the onboard IMU. If you see the Adafruit maintainers, kindly ask them to look at &lt;a href=&quot;https://github.com/adafruit/Adafruit_L3GD20_U/pull/23&quot;&gt;my pull request&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I was able to reduce the vibrations to a small jitter by estimating the offset and subtracting out a centripetal term. It seemed that fully eliminating the effect would again require precise calibration. I chatted with Art from &lt;a href=&quot;https://rbmates.com/&quot;&gt;robomates&lt;/a&gt; about how he solved this problem for his bots. He said that his DMP IMU solved it for him.&lt;/p&gt;

&lt;p&gt;After a bit of searching and a bit more chatting with @copper280z I finally learned what to do. The final trick to get rid of the vibration was to use the gyroscope as the primary source of pitch information. This can only happen after finding an absolute “down” direction with the accelerometer. I implemented this for the Mk.II using a complementary filter weighted 98% to the gyroscope. This completely eliminated the vibration while still allowing the accelerometer to provide long-term stability.&lt;/p&gt;

&lt;div class=&quot;embed-container&quot;&gt;
  &lt;video width=&quot;960&quot; height=&quot;540&quot; controls=&quot;&quot;&gt;
    &lt;source src=&quot;/blog/images/mk.ii/balance.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
&lt;/div&gt;

&lt;h2 id=&quot;coming-up&quot;&gt;Coming Up…&lt;/h2&gt;

&lt;p&gt;In the final post, I’ll show how to control the Mk.II in real time, along with the telemetry and tooling I use to debug it while it’s running.&lt;/p&gt;

&lt;p&gt;Previous Post: &lt;a href=&quot;/blog/2026/04/12/building-a-metal-gear-mk.ii-inspired-self-balancing-robot-part-3-cad-design.html&quot;&gt;Part 3: CAD Design&lt;/a&gt;&lt;/p&gt;

   </description>
  </item>
  <item>
   <title>Building a Metal Gear Mk.II-Inspired Self-Balancing Robot (Part 3: CAD Design)</title>
   <link>https://otac0n.com/blog/2026/04/12/building-a-metal-gear-mk.ii-inspired-self-balancing-robot-part-3-cad-design.html</link>
   <pubDate>Sun, 12 Apr 2026 00:00:00 +0000</pubDate>
   <guid isPermaLink="false">https://otac0n.com/blog/2026/04/12/building-a-metal-gear-mk.ii-inspired-self-balancing-robot-part-3-cad-design</guid>
   <description>
&lt;h2 id=&quot;freecad&quot;&gt;FreeCAD&lt;/h2&gt;

&lt;p&gt;When I started the Mk.II project, I didn’t have any meaningful CAD experience. I had been watching channels like &lt;a href=&quot;https://www.youtube.com/@MakersMuse&quot;&gt;Maker’s Muse&lt;/a&gt;, &lt;a href=&quot;https://www.youtube.com/@Wintergatan&quot;&gt;Wintergatan&lt;/a&gt;, &lt;a href=&quot;https://www.youtube.com/bpsspace&quot;&gt;BPS.space&lt;/a&gt;, and &lt;a href=&quot;https://www.youtube.com/user/RCtestflight&quot;&gt;rctestflight&lt;/a&gt; do amazing things with CAD, so I had some idea of what to do. I chose to learn FreeCAD because of its open-source nature and fully-featured user experience. In order to get up to speed, I made use of the FreeCAD 101 series on YouTube as well as Mangojelly’s videos:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=jULWgMV9_TM&quot;&gt;FreeCAD 1.0 Tutorial for beginners 2025&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=93LIxgRXeew&quot;&gt;FreeCAD: Sketch on Curved Surface&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=IjzhUCl3gXg&quot;&gt;Complex Extrude from a Single Sketch&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=x0zhLrjiZ7o&quot;&gt;How to Split Solids in FreeCAD&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tutorials helped me learn the UI idiosyncrasies and the specific features I needed in order to model the Mk.II.  I was able to recreate a relatively accurate model of him over the course of a couple of months.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/mk.ii-body.png&quot; alt=&quot;Mk.II Body&quot; /&gt;
&lt;img src=&quot;/blog/images/mk.ii/mk.ii-head.png&quot; alt=&quot;Mk.II Head&quot; /&gt;
&lt;img src=&quot;/blog/images/mk.ii/mk.ii-pelvis.png&quot; alt=&quot;Mk.II Pelvis&quot; /&gt;
&lt;img src=&quot;/blog/images/mk.ii/mk.ii-thigh.png&quot; alt=&quot;Mk.II Thigh&quot; /&gt;
&lt;img src=&quot;/blog/images/mk.ii/mk.ii-lower-leg.png&quot; alt=&quot;Mk.II Lower Leg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This is not to say that the journey was easy. FreeCAD has two really big issues that cause user friction:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Edge/face renames break history &amp;amp; sketches&lt;/li&gt;
  &lt;li&gt;B-splines get introduced for linear features by some operations.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These issues will absolutely break your workflow if you don’t plan around them. I have managed to find workarounds that avoid these issues wherever possible.&lt;/p&gt;

&lt;h2 id=&quot;dodging-freecad-roadblocks&quot;&gt;Dodging FreeCAD Roadblocks&lt;/h2&gt;

&lt;h3 id=&quot;master-sketches&quot;&gt;Master Sketches&lt;/h3&gt;

&lt;p&gt;The first strategy that I want to share is the use of Master Sketches. FreeCAD’s operations, like Pad, Pocket, Groove, etc. operate on the selection they are given. To put it another way, you can select part of a sketch in order to limit the operation to that part. For example, take this simple shape:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/freecad-master-1.4.png&quot; alt=&quot;Simple Block&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The most straight-forward way to construct this is by Padding (extruding) with a sketch drawn on the top face, like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/freecad-master-1.gif&quot; alt=&quot;Simple Block Construction 1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This works well if you are using absolute measurements everywhere. However, as soon as you need constraints between e.g. the larger block and smaller one, then this strategy would have you depending on specific edges and faces of the output geometry. Output geometry can and will change as you are iterating on a design, so this is a shaky foundation. You will end up breaking the references that you constrained your sketch to.&lt;/p&gt;

&lt;p&gt;A better solution is to put as many of the shapes and constraints into a single sketch as you can. Then, only one sketch drives the outputs of your object, and each feature is independent of the output geometry of the others.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/freecad-master-2.gif&quot; alt=&quot;Simple Block Construction 2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Note that both Pad operations in this example refer to the same sketch. Destructive operations such as deleting sketch edges will still potentially lead to broken geometry, but all &lt;em&gt;additive&lt;/em&gt; modifications to the sketch will apply without breaking any unrelated geometry. This turns out to be a specific form of my next strategy.&lt;/p&gt;

&lt;h3 id=&quot;refer-to-the-earliest-geometry-possible&quot;&gt;Refer to the earliest geometry possible.&lt;/h3&gt;

&lt;p&gt;The main benefit of Master Sketches is that they automatically force your operations to refer to the earliest possible feature (the Master Sketch itself). Since none of your operations rely on the outputs of any others, they cannot break each other’s constraints. This can be generalized to situations where a single sketch is not sufficient.&lt;/p&gt;

&lt;p&gt;If you must base a feature or sketch on output geometry, reference the earliest instance of that geometry whenever possible. In particular, avoid referencing the output of chamfer and fillet operations, preferring to reference the unmodified faces from the previous feature tree item.&lt;/p&gt;

&lt;h3 id=&quot;use-clones-and-the-part-workbench&quot;&gt;Use Clones and the Part Workbench&lt;/h3&gt;

&lt;p&gt;Cloning or shape-binding a Master Object is another way to ensure your feature tree stays linear and short. If you have two parts that interface in some way, creating a single Master Object and deriving both parts from that will prevent your tree from getting tangled.&lt;/p&gt;

&lt;p&gt;In addition, several operations in the Part Design workbench do not allow access to modify earlier features in the feature tree. Namely the boolean operations and the Hole operation as they “consume” the previous node in the feature tree. There are two strategies to avoid getting stuck, unable to modify those past objects.&lt;/p&gt;

&lt;p&gt;The first option is to always clone your object before performing a boolean operation in the Part Design workbench. The clone will track changes to the “tip” of the object it references, allowing you to make changes to that node that propagate.&lt;/p&gt;

&lt;p&gt;The second option is to use the Part workbench to do the boolean operation and then converting the object back into a Part Design body. This option is my preferred way of working as it keeps the feature tree a bit more tidy.&lt;/p&gt;

&lt;p&gt;Having both of these options available has helped me work around a few bugs, so it’s good to keep both in mind.&lt;/p&gt;

&lt;h2 id=&quot;dont-reinvent-the-gm4108h-120t&quot;&gt;Don’t Reinvent the GM4108H-120T&lt;/h2&gt;

&lt;p&gt;I purchased several off-the-shelf components for my bot. While I might eventually design my own board, for the prototypes I chose to use single-purpose module boards and dev kit boards. These have the advantage of being well documented. This usually means that there are CAD files with the exact part dimensions already available online. The motors I chose are also a very standard entity. Because they are being used for drones and other robotics projects, the CAD files for them have been released as well.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/freecad-reference-1.gif&quot; alt=&quot;Downloaded References&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Several of the components I purchased didn’t have existing CAD models. Rather than design them into the Mk.II, I chose to design separate models and import them:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/freecad-reference-2.gif&quot; alt=&quot;Created References&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I used these reference models as Master Objects via clones and shape-binders to drive the interfaces between them and the bot. But just using the parts alone was not enough to guarantee things fit.&lt;/p&gt;

&lt;h2 id=&quot;designing-for-3d-printing&quot;&gt;Designing for 3D-Printing&lt;/h2&gt;

&lt;h3 id=&quot;parts-have-layers-like-an-ogre&quot;&gt;Parts Have Layers, Like an Ogre&lt;/h3&gt;

&lt;p&gt;3D printers typically produce objects with horizontal layers. There are, of course, exceptions including belt-fed printers and unconstrained toolpath generation (like https://www.gerridaj.com/ or https://fullcontrol.xyz). But even in these cases 3D prints tend to have weakpoints due to layer adhesion.&lt;/p&gt;

&lt;p&gt;These implicit weakpoints necessitated design consideration. For each of my parts I applied this simple process to work around these weaknesses:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Determine the limits of stress that the part will experience. Make particular note of tension and shear stresses. Layer adhesion is typically not a problem for compressive stresses.&lt;/li&gt;
  &lt;li&gt;Plan the layer lines so that the solid filament lines are parallel to the stresses.&lt;/li&gt;
  &lt;li&gt;Incorporate a large, flat area on your part parallel to your layer lines. You will print with this area on the bed, minimizing support.
    &lt;ul&gt;
      &lt;li&gt;If there is no flat area, plan to slice the part in half and join them. I primarily used screws as fasteners, but also included a couple of snap-fit interfaces.&lt;/li&gt;
      &lt;li&gt;If multiple flat areas are available, choose the one that will result in the most visually appealing layer lines, followed by the one that uses the least support material.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Proceed to design your part, applying clearances according to the accuracy of your printer in each dimension.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;During the export of any 3D model to FDM G-code, curved edges will get turned into small line segments. This means that any curved surface will have a slightly smaller radius when printed. Also, since 3D printers cannot draw lines significantly narrower than the nozzle width, corners are always rounded.&lt;/p&gt;

&lt;p&gt;To compensate for this, clearances need to be added on faces and corners where parts fit together. For my X &amp;amp; Y axes, I used a quarter of my nozzle size (0.1mm) on each face. When adding up the left and right sides, this means I am allowing a total deviation of one-half of a nozzle.&lt;/p&gt;

&lt;p&gt;Zero clearance will almost never work, even for snug fit parts. Only the strongest parts can withstand assembly with no clearance.&lt;/p&gt;

&lt;p&gt;One thing I learned late in the process was the use of variables. I wish I had introduced a variable for my clearance early on in my project, so please learn from my mistake and use a Variable Set for your printer tolerances, etc.&lt;/p&gt;

&lt;h3 id=&quot;watch-your-first-layer&quot;&gt;Watch Your First Layer&lt;/h3&gt;

&lt;p&gt;The first layer of any 3D print is the most critical. If the filament doesn’t stick to the print bed, your part will not take shape. In contrast, if your first layer prints perfectly, the rest of your print is very likely to succeed (overhangs &amp;amp; bridges notwithstanding). So, the advice you will hear time and again is to always watch the first layer. I can attest that this is the best way to avoid wasting time and material on a print that is doomed to fail.&lt;/p&gt;

&lt;h2 id=&quot;coming-up&quot;&gt;Coming Up…&lt;/h2&gt;

&lt;p&gt;If you read up to this point, you’ve seen the process I used to design the Mk.II’s various components. Coming up is where the rubber meets the road (literaly!). We’ll be talking traction, balance, PID tuning and finally showing off the bot!&lt;/p&gt;

&lt;p&gt;Previous Post: &lt;a href=&quot;/blog/2026/03/19/building-a-metal-gear-mk.ii-inspired-self-balancing-robot-part-2-prototypes.html&quot;&gt;Part 2: Prototypes&lt;/a&gt;
Next Post: &lt;a href=&quot;/blog/2026/04/17/building-a-metal-gear-mk.ii-inspired-self-balancing-robot-part-4-traction-and-balance.html&quot;&gt;Part 4: Traction and Balance&lt;/a&gt;&lt;/p&gt;

   </description>
  </item>
  <item>
   <title>Building a Metal Gear Mk.II-Inspired Self-Balancing Robot (Part 2: Prototypes)</title>
   <link>https://otac0n.com/blog/2026/03/19/building-a-metal-gear-mk.ii-inspired-self-balancing-robot-part-2-prototypes.html</link>
   <pubDate>Thu, 19 Mar 2026 00:00:00 +0000</pubDate>
   <guid isPermaLink="false">https://otac0n.com/blog/2026/03/19/building-a-metal-gear-mk.ii-inspired-self-balancing-robot-part-2-prototypes</guid>
   <description>
&lt;p&gt;In the &lt;a href=&quot;/blog/2026/03/11/building-a-metal-gear-mk.ii-inspired-self-balancing-robot-part-1-system-design.html&quot;&gt;last post&lt;/a&gt; I went over my inspiration and goals for the Mk.II project. This post covers the steps I took to get the various prototypes up and running. I will be including sponsored links to the parts I purchased; if you use these links it will help me continue making content like this!&lt;/p&gt;

&lt;h2 id=&quot;parts&quot;&gt;Parts&lt;/h2&gt;

&lt;p&gt;At the end of August, after getting my plan reviewed by the experts, I eagerly ordered my first batch of parts.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/foc-balancer-system-v2.png&quot; alt=&quot;System Design (ordered)&quot; /&gt;&lt;/p&gt;
&lt;div class=&quot;alt&quot; style=&quot;display: none&quot;&gt;&lt;pre&gt;&lt;code&gt;
language: mermaid
graph TB
  battery[4S LIPO]
  splitter[XT90 Splitter]
  step_down[5V 5A step-down]
  rail_14v_in@{ shape: junction }
  rail_5v_in@{ shape: junction }
  battery -- 14.8V --&amp;gt; splitter
  splitter -- 14.8V --&amp;gt; rail_14v_in
  splitter -- 14.8V --&amp;gt; step_down
  step_down -- 5V --&amp;gt; rail_5v_in
  high_level_controller[Pi 5 / Jetson Orin]
  camera
  screen
  low_level_controller[STM32F411E-DISCOVERY]
  motor_controller_left[SimpleFOC Mini]
  motor_controller_right[SimpleFOC Mini]
  motor_left[GM4108 BLDC]
  motor_right[GM4108 BLDC]
  sensor_left[AS5047P]
  sensor_right[AS5047P]
  rail_5v_1@{ shape: junction } -- 5V --&amp;gt; high_level_controller
  rail_5v_2@{ shape: junction } -- 5V --&amp;gt; low_level_controller
  high_level_controller -- Direction --&amp;gt; low_level_controller
  camera -- A/V --&amp;gt; high_level_controller
  high_level_controller -- UI --&amp;gt; screen
  low_level_controller -- Telemetry --&amp;gt; high_level_controller
  low_level_controller -- PWM --&amp;gt; motor_controller_left
  rail_14v_1@{ shape: junction } -- 14.8V --&amp;gt; motor_controller_left
  motor_controller_left --&amp;gt; motor_left
  motor_left --&amp;gt; sensor_left
  rail_5v_3@{ shape: junction } -- 5V --&amp;gt; sensor_left
  sensor_left -- ABZ --&amp;gt; low_level_controller
  low_level_controller -- PWM --&amp;gt; motor_controller_right
  rail_14v_2@{ shape: junction } -- 14.8V --&amp;gt; motor_controller_right
  motor_controller_right --&amp;gt; motor_right
  motor_right --&amp;gt; sensor_right
  rail_5v_4@{ shape: junction } -- 5V --&amp;gt; sensor_right
  sensor_right -- ABZ --&amp;gt; low_level_controller
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I sent in orders for the MCU, the motors, sensors, motor controllers, and a few other things:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Boards
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://www.st.com/en/evaluation-tools/32f411ediscovery.html&quot;&gt;STM32F411E-DISCO&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://shop.iflight.com/ipower-motor-gm4108h-120t-brushless-gimbal-motor-pro217&quot;&gt;GM4108H-120T&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;2x &lt;a href=&quot;https://amzn.to/4cPbORQ&quot;&gt;SimpleFOC Mini&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;2x &lt;a href=&quot;https://amzn.to/4lzFlkV&quot;&gt;AS5047P Magnetic Encoder&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;del&gt;&lt;a href=&quot;https://amzn.to/479lClZ&quot;&gt;5V Regulator&lt;/a&gt;&lt;/del&gt; &lt;em&gt;not used in current design&lt;/em&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Hardware
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://amzn.to/41cBa4V&quot;&gt;M3 Screws &amp;amp; Nuts (black)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://amzn.to/4cQIH0s&quot;&gt;M3 Screws &amp;amp; Nuts (silver)&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Power
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://amzn.to/4rABl53&quot;&gt;4x 2S Lipo Batteries&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://amzn.to/4lxgxd2&quot;&gt;XT30 Connectors&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://amzn.to/4sWHqK8&quot;&gt;20AWG red/black&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://amzn.to/4scgLZI&quot;&gt;18AWG red/black&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;motion-sensing&quot;&gt;Motion Sensing&lt;/h2&gt;

&lt;p&gt;While I waited for parts to arrive, I began modelling the Mk.II in FreeCAD. I learned quite a bit here even beyond the prototyping phase, and it deserves a post of its own. Stay tuned for more on that in a later installment.&lt;/p&gt;

&lt;p&gt;As soon as I got the STM32 board, it was time to get some coding done. I surveyed the embedded development landscape for operating systems and IDEs. What I found was that &lt;a href=&quot;https://platformio.org/&quot;&gt;Platform.IO&lt;/a&gt; is pretty much the standard for embedded software, enabling a single project to target multiple boards.&lt;/p&gt;

&lt;p&gt;I created a project but couldn’t find Arduino support for my board. I &lt;em&gt;did&lt;/em&gt; find support for the STM32F407-DISCO board which was the previous hardware revision. I guessed they were compatible, so I moved forward with that as a project starting point. It didn’t take long before issues started to crop up, likely due to the different MCU settings between the boards. I felt I had to pivot to ZephyrOS on the STM32F411-DISCO, and luckily Platform.IO made this relatively painless:&lt;/p&gt;

&lt;p&gt;Before:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[env:disco_f411ve]
platform = ststm32
board = disco_f407vg ;disco_f411ve
framework = arduino
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[env:disco_f411ve]
platform = ststm32
board = disco_f411ve
framework = zephyr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The first prototype I wanted to create was something that could display the state of the accelerometer. This was very straight-forward in Zephyr, taking only a few minutes to implement:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;static const struct device *const accelerometer = DEVICE_DT_GET_ONE(st_lis2dh);
...
IMUReading reading;
sensor_sample_fetch(accelerometer);
reading.accelerometer[0] = sensor_value_to_double(&amp;amp;val[0]);
reading.accelerometer[1] = sensor_value_to_double(&amp;amp;val[1]);
reading.accelerometer[2] = sensor_value_to_double(&amp;amp;val[2]);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Combined with a basic &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;led_service&lt;/code&gt;, this was enough to build a “this-way-up” demo:&lt;/p&gt;

&lt;div class=&quot;embed-container&quot;&gt;
  &lt;video width=&quot;480&quot; height=&quot;600&quot; controls=&quot;&quot;&gt;
    &lt;source src=&quot;/blog/images/mk.ii/this-way-up.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
&lt;/div&gt;

&lt;p&gt;Next, I wanted to implement something similar for the gyroscope. Only one problem: Zephyr didn’t know about the STM32’s gyroscope. It took me about an hour to figure out how to inform Zephyr about the device. I was able to reuse most of the details from the STM32F407 board configuration.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;amp;spi1 {
    pinctrl-0 = &amp;lt;&amp;amp;spi1_nss_pa4 &amp;amp;spi1_sck_pa5
                &amp;amp;spi1_miso_pa6 &amp;amp;spi1_mosi_pa7&amp;gt;;
    pinctrl-names = &quot;default&quot;;
    status = &quot;okay&quot;;
    cs-gpios = &amp;lt;&amp;amp;gpioe 3 GPIO_ACTIVE_LOW&amp;gt;;
    i3g4250d@0 {
        compatible = &quot;st,i3g4250d&quot;;
        reg = &amp;lt;0&amp;gt;;
        spi-max-frequency = &amp;lt;1000000&amp;gt;;
    };
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I &lt;a href=&quot;https://github.com/zephyrproject-rtos/zephyr/pull/95133&quot;&gt;sent a PR&lt;/a&gt; so that others could benefit and then set my focus on integrating the magnetic sensors. I added an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;angle_service&lt;/code&gt; to the project that was responsible for the AS5047P sensors. The sensors support several modes: ABZ, PWM, UVW, and I²C. If you’ll recall, in the last post I received advice from the SimpleFOC forums that ABZ (aka ABI or Quadrature) was the lowest overhead. Adding this sensor to my Zephyr project as a quadrature decoder was also quite easy:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;amp;timers3 {
    status = &quot;okay&quot;;

    qdec: qdec {
        status = &quot;okay&quot;;
        pinctrl-0 = &amp;lt;&amp;amp;tim3_ch1_pb4 &amp;amp;tim3_ch2_pb5&amp;gt;;
        pinctrl-names = &quot;default&quot;;
        st,counts-per-revolution = &amp;lt;1000&amp;gt;;
    };
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Using a cheap fridge magnet, I was able to show that the sensor was working:&lt;/p&gt;

&lt;div class=&quot;embed-container&quot;&gt;
  &lt;video width=&quot;600&quot; height=&quot;600&quot; controls=&quot;&quot;&gt;
    &lt;source src=&quot;/blog/images/mk.ii/magnetic-encoder-demo.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
&lt;/div&gt;

&lt;p&gt;A couple of times I managed to short out the system by touching the sensor power leads with the magnet’s metal housing. I didn’t realize it at the time, but this was a clear indication that my electronics hygiene needed to improve.&lt;/p&gt;

&lt;h2 id=&quot;motion-control&quot;&gt;Motion Control&lt;/h2&gt;

&lt;p&gt;In order to wire up a full motion-control prototype, I ordered a few more things:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://amzn.to/3PJZBnL&quot;&gt;24AWG assorted colors&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://amzn.to/3PgmxLu&quot;&gt;DuPont Connectors&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://amzn.to/4rCO07u&quot;&gt;Key Switches&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://amzn.to/4uxCiOh&quot;&gt;5A Slow Blow Fuse&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://amzn.to/4bQWIdt&quot;&gt;Glass/Nylon Bearings&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;del&gt;&lt;a href=&quot;https://amzn.to/4bs0icM&quot;&gt;10k Resistors&lt;/a&gt;&lt;/del&gt; &lt;em&gt;get an assorted set first, replace with specific values&lt;/em&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://amzn.to/4biP5wh&quot;&gt;Assorted Resistors&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My first soldering project was the pair of SimpleFOC minis. The purpose of these little boards is to translate low-voltage signals (3.3v pulses) into higher voltages (~15V) sent to the motor leads.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/simple-foc-solder.jpg&quot; alt=&quot;SimpleFOC Soldering&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you have any soldering experience, you can probably tell there are a few things wrong:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Several connections have too much solder and have bulged up.&lt;/li&gt;
  &lt;li&gt;One of the joints appears cold. (nFT on the right board)&lt;/li&gt;
  &lt;li&gt;Flux residue not cleaned off.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don’t worry too much about this, as I ended up rewiring this board directly and these errors didn’t impact the prototyping progress.&lt;/p&gt;

&lt;p&gt;From the software side things weren’t simple. On one hand, I had fully working sensors under ZephyrOS, but on the other hand, I had a proof of concept in the way of the Arduino SimpleFOC Balancer project. At the time, there was only a single lonesome Zephyr project doing FOC: &lt;a href=&quot;https://github.com/teslabs/spinner&quot;&gt;Spinner&lt;/a&gt;. I had to decide immediately whether I would attempt to fill the feature gaps to enable a SimpleFOC-like API on Zephyr or to add Arduino support for my board.&lt;/p&gt;

&lt;p&gt;I decided, since the process to add a new STM32 Arduino variant was &lt;a href=&quot;https://github.com/stm32duino/Arduino_Core_STM32/wiki/Add-a-new-variant-%28board%29&quot;&gt;well documented&lt;/a&gt;, that adding the board aligned better with my skillset. While this did set me back several days and a couple of dollars for a &lt;a href=&quot;https://amzn.to/3NyFk3T&quot;&gt;CP2101 USB UART&lt;/a&gt; serial adapter, I do think that &lt;a href=&quot;https://github.com/stm32duino/Arduino_Core_STM32/pull/2805&quot;&gt;my contribution&lt;/a&gt; here has already been beneficial to the community. I wasn’t able to convince my local copy of Platform.IO to use my custom build of STM32Duino, so unfortunately I had to avoid Platform.IO for anything except serial debugging from here out.&lt;/p&gt;

&lt;p&gt;Nevertheless, after adding a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;motor_service&lt;/code&gt; I was able to get a basic SimpleFOC open-loop motion demo running:&lt;/p&gt;

&lt;div class=&quot;embed-container&quot;&gt;
  &lt;video width=&quot;600&quot; height=&quot;800&quot; controls=&quot;&quot;&gt;
    &lt;source src=&quot;/blog/images/mk.ii/open-loop.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
&lt;/div&gt;

&lt;p&gt;The periodic pausing you see there is due to one out of three phases conflicting with other onboard devices. After switching the signal PWM channels to unused pins, I got smooth open-loop control working:&lt;/p&gt;

&lt;div class=&quot;embed-container&quot;&gt;
  &lt;video width=&quot;600&quot; height=&quot;800&quot; controls=&quot;&quot;&gt;
    &lt;source src=&quot;/blog/images/mk.ii/open-loop-motion-control.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
&lt;/div&gt;

&lt;h2 id=&quot;the-missing-magnet&quot;&gt;The Missing Magnet&lt;/h2&gt;

&lt;p&gt;I purchased some &lt;a href=&quot;https://amzn.to/4bhpWCa&quot;&gt;Gold Filament&lt;/a&gt; for the prototype. I always equip Gold in Kojima’s Games and wanted to pay homage.&lt;/p&gt;

&lt;table&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;img src=&quot;/blog/images/mk.ii/gold-mgsv.jpg&quot; alt=&quot;Metal Gear Solid V - Gold Loadout&quot; /&gt;&lt;/td&gt;
    &lt;td&gt;&lt;img src=&quot;/blog/images/mk.ii/gold-death-stranding.jpg&quot; alt=&quot;Death Stranding - Gold Loadout&quot; /&gt;&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;My friend Arthur was kind enough to 3D-print a few of my designs, so I was now able to integrate all of the leg parts into a single package.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/ankle-sensor.jpg&quot; alt=&quot;Ankle Sensor Placement&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/ankle-assembled.jpg&quot; alt=&quot;Ankle Assembled&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/ankle-powered.jpg&quot; alt=&quot;Ankle Powered&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I powered up the experiment, saw the motors move, but the angle sensors read zero. I was clearly missing something. I once again implored the help of the SimpleFOC Discord channel. I had assumed that the motors’ own magnetic fields would be captured by the sensor. The AS5047P magnetic sensor does after offer the “UVW” mode, which I understood to be reading the field strength of each motor’s coils. What I did not realize is that this is merely an emulation mode offered by the chip. The chip itself requires a magnet positioned directly above it to work. And it can’t just be any old magnet either; it has to be a diametrically magnetized magnet.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/mk.iii-slide.jpg&quot; alt=&quot;Mk.III Slide&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If I wanted to stay true to the Mk.II/III design, I had to mount the inner wheel covers &lt;em&gt;through&lt;/em&gt; the motor shaft. The gimbal motors I’m using have room for that, but a magnet would just block the shaft. This meant that, suddenly, I had a very very unique magnet requirement:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Ring magnet&lt;/li&gt;
  &lt;li&gt;Diametrically magnetized&lt;/li&gt;
  &lt;li&gt;Small
    &lt;ul&gt;
      &lt;li&gt;&amp;lt; ~3 mm thick&lt;/li&gt;
      &lt;li&gt;&amp;lt; ~10 mm outer diameter&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;As wide of an inner diameter as possible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I searched through every magnet website around but I could not find anything that fit perfectly within my original design. But, as luck would have it, I did find exactly &lt;a href=&quot;https://www.buyneomagnets.com/p/9mm-od-x-5mm-id-x-3mm-thick-diametrically-magnetized-ring-magnets-n38-strong-neodymium-ring-magnets-20-pack/&quot;&gt;ONE option&lt;/a&gt; that was close. It had a much smaller inner diameter than I like, but I wagered: with a small redesign and a change in material, I could make it work.&lt;/p&gt;

&lt;p&gt;Once they arrived and were installed, I had every individual component working.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/magnet-fit.jpg&quot; alt=&quot;Magnet Fit&quot; /&gt;&lt;/p&gt;

&lt;div class=&quot;embed-container&quot;&gt;
  &lt;video width=&quot;600&quot; height=&quot;750&quot; controls=&quot;&quot;&gt;
    &lt;source src=&quot;/blog/images/mk.ii/sensor-working.mp4&quot; type=&quot;video/mp4&quot; /&gt;
  &lt;/video&gt;
&lt;/div&gt;

&lt;h2 id=&quot;the-hygiene-lesson&quot;&gt;The Hygiene Lesson&lt;/h2&gt;

&lt;p&gt;I was still depending on my friend Arthur for 3D prints, so I figured the easiest way to get a fully integrated prototype assembled would be to build the body out of cardboard. I grabbed a cardboard box, measured up and cut holes for mounting the ankles, and threw it all together:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/just-a-box.jpg&quot; alt=&quot;Huh, it&apos;s just a box.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I arranged a meet-up to get the 3D printed wheels &amp;amp; tires at our local makerspace. And it was there that the poor electronics hygiene caught up with me. I assembled the wheels, powered the bot on, and… a twitch and then it almost immediately fell silent.&lt;/p&gt;

&lt;p&gt;I pulled the power and hooked up USB serial to assess the damage. The board gave me random text in return. I fried the brains and the sensors. Oof. Most likely what happened is that one of the 15V leads from the step-down must have contacted one of the lower-voltage data lines on the STM32. There was nowhere to secure the voltage regulator inside the box, and I had not protected the leads.&lt;/p&gt;

&lt;p&gt;At this point, I decided I had to make some specific changes. Going forward, I decided:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;All power leads must be sleeved.&lt;/li&gt;
  &lt;li&gt;Any unshielded male power connector must not have power when disconnected.
    &lt;ul&gt;
      &lt;li&gt;Follow standards for XT connectors.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;All power leads must be secured to the chassis.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I designed an enclosure with plenty of tie-down points and asked for Arthur to print it. I also reordered the fried parts: 1 STM32 board and 2 AS5047P sensors (all of my low-voltage devices). It didn’t take long for me to reconsider my choice of STM32. I wanted the bot to be controlled like it is in the game, and this meant using a Bluetooth controller. In parallel, I ordered a few extra parts that could be here quicker.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;del&gt;&lt;a href=&quot;https://amzn.to/4rHftoB&quot;&gt;ESP32-S3-DevKitC-1&lt;/a&gt;&lt;/del&gt; &lt;em&gt;BLE only, not used in latest design&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://amzn.to/4rDjpq8&quot;&gt;WiFi Antenna&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://amzn.to/3NATH7M&quot;&gt;INA219 Power Monitor&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://amzn.to/4dpaLbu&quot;&gt;3.3V Regulator&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://amzn.to/41bLxpB&quot;&gt;ICM-42688 IMU&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This further hints at some design changes that we will see in later posts.&lt;/p&gt;

&lt;h2 id=&quot;coming-up&quot;&gt;Coming Up…&lt;/h2&gt;

&lt;p&gt;In the upcoming posts, I’ll be covering my CAD journey, traction, PID tuning, designing for 3D printing, and more!&lt;/p&gt;

&lt;p&gt;Stay tuned.&lt;/p&gt;

&lt;p&gt;Previous Post: &lt;a href=&quot;/blog/2026/03/11/building-a-metal-gear-mk.ii-inspired-self-balancing-robot-part-1-system-design.html&quot;&gt;Part 1: System Design&lt;/a&gt;
Next Post: &lt;a href=&quot;/blog/2026/04/12/building-a-metal-gear-mk.ii-inspired-self-balancing-robot-part-3-cad-design.html&quot;&gt;Part 3: CAD Design&lt;/a&gt;&lt;/p&gt;

   </description>
  </item>
  <item>
   <title>Building a Metal Gear Mk.II-Inspired Self-Balancing Robot (Part 1: System Design)</title>
   <link>https://otac0n.com/blog/2026/03/11/building-a-metal-gear-mk.ii-inspired-self-balancing-robot-part-1-system-design.html</link>
   <pubDate>Wed, 11 Mar 2026 00:00:00 +0000</pubDate>
   <guid isPermaLink="false">https://otac0n.com/blog/2026/03/11/building-a-metal-gear-mk.ii-inspired-self-balancing-robot-part-1-system-design</guid>
   <description>
&lt;h2 id=&quot;inspiration&quot;&gt;Inspiration&lt;/h2&gt;

&lt;p&gt;At the end of July last year I happened across &lt;a href=&quot;https://www.reddit.com/r/EngineeringPorn/comments/1m8ztyc/my_mini_robomate_is_finally_alive/&quot;&gt;a Reddit post&lt;/a&gt; showing off the performance of a two-wheeled balancer robot. At the time I was still playing through &lt;em&gt;Metal Gear Solid 4&lt;/em&gt;, so I immediately noticed the similarities between their robots and the &lt;a href=&quot;https://metalgear.fandom.com/wiki/Metal_Gear_Mk._II&quot;&gt;Metal Gear Mk.II&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/robomates-comp.jpg&quot; alt=&quot;Comparison of Robomates and Mk.II&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I eagerly joined their subreddit and Discord channel to see if their bots were customizable. In the game, the Mk.II (and later the Mk.III) is a friendly companion that the player can pilot. He’s nimble on his wheels and can act as your eyes and hands. This is a perfect fit to Robomate’s bring-your-own controller approach. However, their kits weren’t available yet.&lt;/p&gt;

&lt;p&gt;I was too eager to wait, so I started planning my own bot. After a bit of searching, I found a couple of preexisting projects that seemed like good places to start. The most similar project to Mk.II was &lt;a href=&quot;https://github.com/raspibotics/MABEL&quot;&gt;MABEL&lt;/a&gt;, with its independent legs.  However, &lt;a href=&quot;https://github.com/simplefoc/Arduino-FOC-balancer&quot;&gt;SimpleFOCBalancer&lt;/a&gt; won me over by its simplicity as a starting point.&lt;/p&gt;

&lt;h2 id=&quot;goals&quot;&gt;Goals&lt;/h2&gt;

&lt;p&gt;My goals with this project were to (A) learn basic robotics and (B) achieve as close of a representation of Mk.II as I could manage. Since I had zero practical experience with robotics and a pretty abysmal electronics track record, I knew I needed to take it slow. Mistakes would be made.&lt;/p&gt;

&lt;p&gt;I paved this basic roadmap:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;IMU + Motor prototype&lt;/li&gt;
  &lt;li&gt;Simple 2-wheel prototype&lt;/li&gt;
  &lt;li&gt;Full-size 2-wheel bot&lt;/li&gt;
  &lt;li&gt;Independent leg movement&lt;/li&gt;
  &lt;li&gt;Computer Vision integration&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;#4 and #5 on this list are long-term goals with the project.  A bot similar to the Robomates implementation would be wonderful, but even achieving #1 would be a win.&lt;/p&gt;

&lt;p&gt;To save costs, I hoped to reuse as many of the prototype components in the final bot as possible. So, based mostly on the Simple FOC Arduino Balancer project, I drafted this design:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/foc-balancer-system-v1.png&quot; alt=&quot;System Design (draft)&quot; /&gt;&lt;/p&gt;
&lt;div class=&quot;alt&quot; style=&quot;display: none&quot;&gt;&lt;pre&gt;&lt;code&gt;
language: mermaid
graph TB
  battery[4S LIPO]
  splitter[XT90 Splitter]
  step_down[5V 5A Step-Down]
  rail_14v_in@{ shape: junction }
  rail_5v_in@{ shape: junction }
  battery -- 14.8V --&amp;gt; splitter
  splitter -- 14.8V --&amp;gt; rail_14v_in
  splitter -- 14.8V --&amp;gt; step_down
  step_down -- 5V --&amp;gt; rail_5v_in
  high_level_controller[Pi 5 / Jetson Orin]
  camera
  screen
  low_level_controller[STM32F3DISCOVERY]
  motor_controller_left[SimpleFOC Mini]
  motor_controller_right[SimpleFOC Mini]
  motor_left[2408 BLDC]
  motor_right[2408 BLDC]
  sensor_left[AS5600]
  sensor_right[AS5600]
  rail_5v_1@{ shape: junction } -- 5V --&amp;gt; high_level_controller
  rail_5v_2@{ shape: junction } -- 5V --&amp;gt; low_level_controller
  high_level_controller -- Direction --&amp;gt; low_level_controller
  camera -- A/V --&amp;gt; high_level_controller
  high_level_controller -- UI --&amp;gt; screen
  low_level_controller -- Telemetry --&amp;gt; high_level_controller
  low_level_controller -- PWM --&amp;gt; motor_controller_left
  rail_14v_1@{ shape: junction } -- 14.8V --&amp;gt; motor_controller_left
  motor_controller_left --&amp;gt; motor_left
  motor_left --&amp;gt; sensor_left
  rail_5v_3@{ shape: junction } -- 5V --&amp;gt; sensor_left
  sensor_left -- SPI --&amp;gt; low_level_controller
  low_level_controller -- PWM --&amp;gt; motor_controller_right
  rail_14v_2@{ shape: junction } -- 14.8V --&amp;gt; motor_controller_right
  motor_controller_right --&amp;gt; motor_right
  motor_right --&amp;gt; sensor_right
  rail_5v_4@{ shape: junction } -- 5V --&amp;gt; sensor_right
  sensor_right -- SPI --&amp;gt; low_level_controller
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;Raspberry Pi 5 8GB / NVIDIA Jetson Orin Nano (8GB) for computer vision&lt;/li&gt;
  &lt;li&gt;STM32F3DISCOVERY with microcontroller, accelerometer, gyroscope, and motor output/input pins&lt;/li&gt;
  &lt;li&gt;4S Lipo for power
    &lt;ul&gt;
      &lt;li&gt;Needs enough juice to run both of the control boards as well as the motors.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;5V Step Down for main power rail
    &lt;ul&gt;
      &lt;li&gt;I had originally planned for both a 5v and 3.3v rail, but decided to unify behind 5v for simplicity since the STM can safely interface with it.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Simple FOC Mini motor driver board&lt;/li&gt;
  &lt;li&gt;2804 BLDC + AS5600 Encoder kit for closed-loop motor control&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;feedback&quot;&gt;Feedback&lt;/h2&gt;

&lt;p&gt;Before spending any money on this scheme, I wanted to get the input of folks much more knowledgeable than me.  Besides, I was about to travel with my family to the UK and couldn’t immediately receive packages. I started sharing my plan on a few robotics Discord servers in search of critical feedback. The SimpleFOC folks &lt;a href=&quot;https://discord.com/channels/927331369137352734/927332503654633572/1399896314682282117&quot;&gt;gave me good advice&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;@copper280z
    &lt;blockquote&gt;
      &lt;p&gt;I would change several things, don’t use the as5600 encoder, it’s not a good choice. Pick something that uses SPI or ABZ for an interface, like the mt6835, as5047, etc. ABZ is preferable for something like this because it’s got the lowest overhead.&lt;/p&gt;

      &lt;p&gt;Next, don’t use the stm32f3, use either an stm32f4, ideally one of the 168-180MHz variants like the f405 or f446, or use an stm32g4. The g4 is better but needs a bit more configuration for max performance because the stm32duino configuration for it is wrong/overly conservative.&lt;/p&gt;

      &lt;p&gt;The pi/jetson are overkill, but that’s fine. You really want the IMU to be connected to the stm32 and to have it run the balance control loop. The jetson is dramatically faster than the pi5, which might be nice if you want high res video or to run some ai type tasks.&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;@runger
    &lt;blockquote&gt;
      &lt;p&gt;I also think that for the size robot you’ll end up with, given battery, RPi/Jetson, etc you should go one size bigger with the motors, and use something like a 3506 or 4108 size motor&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I really appreciate their feedback. @copper280z highlighted that the AS5600 uses either I²C or PWM output which consumes more CPU time than ABZ or SPI. ABZ has the lowest overhead, only changing one or two pins per incremental movement. They also suggested I choose a more powerful MCU (microcontroller). @runger said I needed a LOT more torque.&lt;/p&gt;

&lt;p&gt;I narrowed down the list of STM boards based on this feedback and the prices at the time:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.st.com/en/evaluation-tools/stm32f3discovery.html&quot;&gt;STM32F3DISCOVERY&lt;/a&gt; - $16.31 - STM32F303VC (72 MHz, 256KB) - but advised against&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.st.com/en/evaluation-tools/32f411ediscovery.html&quot;&gt;STM32F411EDISCOVERY&lt;/a&gt; - $15.55 - STM32F411VE (100 MHz, 512KB) - but a bit slower than recommended&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.st.com/en/evaluation-tools/stm32l562e-dk.html&quot;&gt;STM32L562QE-DK&lt;/a&gt; - $75.77 - STM32L562QE (110 MHz, 512KB) - way too expensive and too many unwanted features&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.st.com/en/evaluation-tools/b-u585i-iot02a.html&quot;&gt;B-U585I-IOT02A&lt;/a&gt; - $64 - STM32U585AI (160 MHz, 2MB) - too expensive and too many unwanted features&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.st.com/en/evaluation-tools/stm32f4discovery.html&quot;&gt;STM32F407G-DISC1&lt;/a&gt; - $20.48 - STM32F407VG (168 MHz, 1MB) - three axis only&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I finally settled on the STM32F411DISCOVERY board based on my perception of the usefulness of the on-board hardware contrasted against the price. The AS5048A stood out as a good choice due to its ABZ and SPI modes. The larger of the motors, the GM4108H-120T, fit barely within the wheel dimensions of the Mk.II: perfect.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/images/mk.ii/foc-balancer-system-v2.png&quot; alt=&quot;System Design (ordered)&quot; /&gt;&lt;/p&gt;
&lt;div class=&quot;alt&quot; style=&quot;display: none&quot;&gt;&lt;pre&gt;&lt;code&gt;
language: mermaid
graph TB
  battery[4S LIPO]
  splitter[XT90 Splitter]
  step_down[5V 5A step-down]
  rail_14v_in@{ shape: junction }
  rail_5v_in@{ shape: junction }
  battery -- 14.8V --&amp;gt; splitter
  splitter -- 14.8V --&amp;gt; rail_14v_in
  splitter -- 14.8V --&amp;gt; step_down
  step_down -- 5V --&amp;gt; rail_5v_in
  high_level_controller[Pi 5 / Jetson Orin]
  camera
  screen
  low_level_controller[STM32F411E-DISCOVERY]
  motor_controller_left[SimpleFOC Mini]
  motor_controller_right[SimpleFOC Mini]
  motor_left[GM4108 BLDC]
  motor_right[GM4108 BLDC]
  sensor_left[AS5047P]
  sensor_right[AS5047P]
  rail_5v_1@{ shape: junction } -- 5V --&amp;gt; high_level_controller
  rail_5v_2@{ shape: junction } -- 5V --&amp;gt; low_level_controller
  high_level_controller -- Direction --&amp;gt; low_level_controller
  camera -- A/V --&amp;gt; high_level_controller
  high_level_controller -- UI --&amp;gt; screen
  low_level_controller -- Telemetry --&amp;gt; high_level_controller
  low_level_controller -- PWM --&amp;gt; motor_controller_left
  rail_14v_1@{ shape: junction } -- 14.8V --&amp;gt; motor_controller_left
  motor_controller_left --&amp;gt; motor_left
  motor_left --&amp;gt; sensor_left
  rail_5v_3@{ shape: junction } -- 5V --&amp;gt; sensor_left
  sensor_left -- ABZ --&amp;gt; low_level_controller
  low_level_controller -- PWM --&amp;gt; motor_controller_right
  rail_14v_2@{ shape: junction } -- 14.8V --&amp;gt; motor_controller_right
  motor_controller_right --&amp;gt; motor_right
  motor_right --&amp;gt; sensor_right
  rail_5v_4@{ shape: junction } -- 5V --&amp;gt; sensor_right
  sensor_right -- ABZ --&amp;gt; low_level_controller
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;coming-up&quot;&gt;Coming Up…&lt;/h2&gt;

&lt;p&gt;This project is several firsts for me:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;my first non-LEGO robotics project&lt;/li&gt;
  &lt;li&gt;my first CAD project&lt;/li&gt;
  &lt;li&gt;my first successful electronics project&lt;/li&gt;
  &lt;li&gt;my first 3D-printing project&lt;/li&gt;
  &lt;li&gt;my first soldering project&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the next post, I will cover the path to the first working prototypes.&lt;/p&gt;

&lt;p&gt;Does this design ultimately change? (Spoiler: yes)&lt;/p&gt;

&lt;p&gt;Next Post: &lt;a href=&quot;/blog/2026/03/19/building-a-metal-gear-mk.ii-inspired-self-balancing-robot-part-2-prototypes.html&quot;&gt;Part 2: Prototypes&lt;/a&gt;&lt;/p&gt;

   </description>
  </item>
  <item>
   <title>Running MVC5 Applications on Ubuntu Server (14.04.1 LTS)</title>
   <link>https://otac0n.com/blog/2015/02/08/running-mvc5-applications-on-ubuntu-server.html</link>
   <pubDate>Sun, 08 Feb 2015 00:00:00 +0000</pubDate>
   <guid isPermaLink="false">https://otac0n.com/blog/2015/02/08/running-mvc5-applications-on-ubuntu-server</guid>
   <description>
&lt;p&gt;We will be following the steps outline in the &lt;a href=&quot;http://www.mono-project.com/docs/getting-started/install/linux/&quot;&gt;Install Mono on Linux&lt;/a&gt; guide and the
&lt;a href=&quot;https://github.com/aspnet/Home#getting-started&quot;&gt;ASP.NET 5 Getting Started&lt;/a&gt; guide.&lt;/p&gt;

&lt;p&gt;When I installed Mono, KVM, and KPM as described in the above guides, I ran in to a couple of issues.  First, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unzip&lt;/code&gt; was not installed, causing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kvm upgrade&lt;/code&gt; command to fail.  Secondly, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libtool&lt;/code&gt; was not found, yielding the following exception:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;System.DllNotFoundException: libdl
  at (wrapper managed-to-native) Microsoft.AspNet.Server.Kestrel.Networking.PlatformApis/LinuxApis:dlopen (string,int)
  at Microsoft.AspNet.Server.Kestrel.Networking.PlatformApis+LinuxApis.LoadLibrary (System.String dllToLoad) [0x00000] in &amp;lt;filename unknown&amp;gt;:0
  at Microsoft.AspNet.Server.Kestrel.Networking.Libuv.Load (System.String dllToLoad) [0x00000] in &amp;lt;filename unknown&amp;gt;:0
  at Microsoft.AspNet.Server.Kestrel.KestrelEngine..ctor (ILibraryManager libraryManager) [0x00000] in &amp;lt;filename unknown&amp;gt;:0
  at Kestrel.ServerFactory.Start (IServerInformation serverInformation, System.Func`2 application) [0x00000] in &amp;lt;filename unknown&amp;gt;:0
  at Microsoft.AspNet.Hosting.HostingEngine.Start (Microsoft.AspNet.Hosting.HostingContext context) [0x00000] in &amp;lt;filename unknown&amp;gt;:0
  at Microsoft.AspNet.Hosting.Program.Main (System.String[] args) [0x00000] in &amp;lt;filename unknown&amp;gt;:0
  at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&amp;amp;)
  at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in &amp;lt;filename unknown&amp;gt;:0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Installing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libtool&lt;/code&gt; package fixed the issue.  Lastly, once &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libtool&lt;/code&gt; was installed, I was greeted with this exception:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;System.NullReferenceException: Object reference not set to an instance of an object
  at Microsoft.AspNet.Server.Kestrel.Networking.Libuv.loop_size () [0x00000] in &amp;lt;filename unknown&amp;gt;:0
  at Microsoft.AspNet.Server.Kestrel.Networking.UvLoopHandle.Init (Microsoft.AspNet.Server.Kestrel.Networking.Libuv uv) [0x00000] in &amp;lt;filename unknown&amp;gt;:0
  at Microsoft.AspNet.Server.Kestrel.KestrelThread.ThreadStart (System.Object parameter) [0x00000] in &amp;lt;filename unknown&amp;gt;:0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This was remedied by downloading, compiling, and installing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libuv&lt;/code&gt;.  In particular, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libuv&lt;/code&gt; needs to be installed (or symlinked) to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/lib/libuv.so.1&lt;/code&gt; for everything to work correctly.&lt;/p&gt;

&lt;p&gt;So without further ado, here is a quick step-by-step guide to Running MVC5 applications on Ubuntu Server (14.04.1 LTS).&lt;/p&gt;

&lt;h3 id=&quot;install-mono&quot;&gt;Install Mono&lt;/h3&gt;

&lt;p&gt;First, install Mono.  These steps are pulled straight from the &lt;a href=&quot;http://www.mono-project.com/docs/getting-started/install/linux/&quot;&gt;Install Mono on Linux&lt;/a&gt; guide.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: sh
# Add the Xamarin public code-signing key
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF

# Add the Mono repository to apt sources
echo &quot;deb http://download.mono-project.com/repo/debian wheezy main&quot; | sudo tee /etc/apt/sources.list.d/mono-xamarin.list

# Install Mono
sudo apt-get update
sudo apt-get install -y mono-complete
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;install-libtool-libuv-unzip-and-their-dependencies&quot;&gt;Install libtool, libuv, unzip and Their Dependencies&lt;/h3&gt;

&lt;p&gt;Next we install the rest of the dependencies.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: sh
# Install other prerequisites
sudo apt-get install -y autoconf build-essential git-core libtool unzip

# Compile libuv
cd /opt
sudo git clone https://github.com/libuv/libuv.git
cd libuv
sudo ./autogen.sh
sudo ./configure
sudo make
sudo make install
sudo ln -s /usr/local/lib/libuv.so /usr/lib/libuv.so.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autoconf&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build-essential&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git-core&lt;/code&gt; are necessary to build and install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libuv&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;install-the-k-version-manager-and-the-k-runtime-environment&quot;&gt;Install the K Version Manager and the K Runtime Environment&lt;/h3&gt;

&lt;p&gt;These steps are pulled from the &lt;a href=&quot;https://github.com/aspnet/Home#getting-started&quot;&gt;ASP.NET 5 Getting Started&lt;/a&gt; guide.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: sh
# Get the K Version Manager
curl -sSL https://raw.githubusercontent.com/aspnet/Home/master/kvminstall.sh | sh &amp;amp;&amp;amp; source ~/.kre/kvm/kvm.sh

# Install the runtime
kvm upgrage
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;all-done&quot;&gt;All Done?&lt;/h2&gt;

&lt;p&gt;Here we could call it a day, since your Ubuntu system is now set up to run ASP.NET 5 applications. Why don’t we follow through with the rest of the guide so we can see it working?&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: sh
# Obtain the ASP.NET 5 samples
git clone https://github.com/aspnet/Home.git ~/AspNetHome
cd ~/AspNetHome/samples/HelloMvc

# Get all of the .NET dependencies necessary to run the sample
kpm restore

# Run the sample
k kestrel
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here it is, running on my machine:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://otac0n.com/blog/images/AspNetUbuntu%20-%201%20-%20Running%20Kestrel.png&quot; alt=&quot;Running Kestrel&quot; title=&quot;Running Kestrel&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://otac0n.com/blog/images/AspNetUbuntu%20-%202%20-%20Working%20Sample.png&quot; alt=&quot;Working Sample&quot; title=&quot;Working sample&quot; /&gt;&lt;/p&gt;


   </description>
  </item>
  <item>
   <title>Range header, I choose you (for pagination)!</title>
   <link>https://otac0n.com/blog/2012/11/21/range-header-i-choose-you.html</link>
   <pubDate>Wed, 21 Nov 2012 00:00:00 +0000</pubDate>
   <guid isPermaLink="false">https://otac0n.com/blog/2012/11/21/range-header-i-choose-you</guid>
   <description>
&lt;p&gt;I was looking around for a semantic way to do pagination over HTTP recently.  I had previously used the OData-style &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$skip&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$top&lt;/code&gt; query string parameters and I was just generally dissatisfied with how that turned out.  So, I was searching for alternatives.&lt;/p&gt;

&lt;p&gt;I happened upon &lt;a href=&quot;http://stackoverflow.com/questions/924472/paging-in-a-rest-collection&quot;&gt;a question on Stack Overflow&lt;/a&gt; that discussed using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range&lt;/code&gt; HTTP header for pagination purposes.  The conclusion there was to use a different approach (mimicking Atom), but I disagree.  I feel that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range&lt;/code&gt; header is a perfect fit for pagination.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://otac0n.com/blog/images/Range%20Header%20-%201%20-%20I%20Choose%20You.jpg&quot; alt=&quot;(for pagination)&quot; title=&quot;(for pagination)&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;why-is-the-range-header-a-good-fit&quot;&gt;Why is the Range header a good fit?&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range&lt;/code&gt; header is normally used by browsers to request specific byte-ranges of binary files.  It powers the pause-and-resume functionality of almost every download manager in existence.  This fact tempted me to simply conclude that usage of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range&lt;/code&gt; header for any purpose other than pause-and-resume would be an abuse.&lt;/p&gt;

&lt;p&gt;However, &lt;a href=&quot;http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2&quot;&gt;RFC 2616&lt;/a&gt; has this to say about the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range&lt;/code&gt; header:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;HTTP retrieval requests using conditional or unconditional GET methods MAY request one or more sub-ranges of the entity, instead of the entire entity, using the Range request header, which applies to the entity returned as the result of the request.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Our entity is a collection of objects, and we are requesting “sub-ranges of the entity, instead of the entire entity.”  This is a perfect fit.&lt;/p&gt;

&lt;h2 id=&quot;how-does-it-measure-up&quot;&gt;How does it measure up?&lt;/h2&gt;

&lt;p&gt;So, from the spec, it looks like the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range&lt;/code&gt; header was designed to handle this concern, but how does this play out in practice?  It would be foolish to just commit to using the header without making sure it was up to the task.&lt;/p&gt;

&lt;p&gt;Let’s evaluate its behavior in contrast to OData-style pagination.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;One thing to note:&lt;br /&gt;
These examples contain partial HTTP requests.  Common elements between the OData and Ranger header styles have been factored out.  These include the http version; the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Host&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Accept&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Type&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Length&lt;/code&gt; headers; and the data itself.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;querying-the-root-of-the-collection&quot;&gt;Querying the root of the collection.&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;OData-style&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;language: http
GET /users&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;language: http
200 OK

[ 0, …, 9 ]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Range-header-style&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;language: http
GET /users&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;language: http
200 OK
Accept-Ranges: users
Content-Range: users 0-9/200

[ 0, …, 9 ]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Comparison&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Both of these have defaults for what the user is allowed to request (limited to 10), but the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range&lt;/code&gt; header style is allowed to send back the count, without &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$inlinecount&lt;/code&gt; being specified.  The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Accept-Ranges&lt;/code&gt; header signals that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;users&lt;/code&gt; range is accepted and implies that a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Ranges&lt;/code&gt; may be present. This makes for good discoverability.&lt;/p&gt;

&lt;p&gt;Importantly, the response code for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range&lt;/code&gt; header style is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;200&lt;/code&gt; (rather than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;206&lt;/code&gt; as you might expect) because the request did not include the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range&lt;/code&gt; header itself.  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Accept-Ranges&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Range&lt;/code&gt; headers are still allowed in the response, keeping it semantically correct.&lt;/p&gt;

&lt;p&gt;The OData-style, in contrast, will not automatically include the count of the collection in the response.  Even if this response were to include the count, unsolicited, there is still no easy way to discover how this data is sent.&lt;/p&gt;

&lt;h3 id=&quot;pulling-the-first-page-of-results-normally&quot;&gt;Pulling the first page of results normally.&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;OData-style&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;language: http
GET /users?$skip=0&amp;amp;$top=10&amp;amp;$inlinecount=allpages&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;language: http
200 OK
X-Some-Side-Channel: count=200

[ 0, …, 9 ]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Range-header-style&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;language: http
GET /users
Range: users=0-9&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;language: http
206 Partial Content
Accept-Ranges: users
Content-Range: users 0-9/200

[ 0, …, 9 ]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Comparison&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Since the request included the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range&lt;/code&gt; header, the server is allowed to respond with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;206 Partial Content&lt;/code&gt; status code, indicating the presence of the Content-Range response header.&lt;/p&gt;

&lt;p&gt;OData had to specify the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$inlinecount=allpages&lt;/code&gt; parameter in order to get the full length of the filtered collection, bloating the URL.&lt;/p&gt;

&lt;p&gt;Additionally, the Range header style is allowed to return a Content-Range response looking something like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: http
Content-Range: 200-250/*
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This indicates that the full count is not included, possibly because it is too expensive to calculate.  This is often the case for complex queries.  This flexibility allows the server to chose whether or not to calculate the total length, based on the particular query at hand. In the OData version, however, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$inlinecount&lt;/code&gt; parameter is a command to get the count.  The server is not free to withold the count when it is expensive or difficult to obtain.&lt;/p&gt;

&lt;h3 id=&quot;pulling-subsequent-pages-of-data&quot;&gt;Pulling subsequent pages of data.&lt;/h3&gt;

&lt;p&gt;Both systems perform roughly the same for pages in the middle of the collection.  Neither system has anything to offer here, nor does either fail in any special way.&lt;/p&gt;

&lt;h3 id=&quot;requesting-past-the-end-of-the-collection&quot;&gt;Requesting past the end of the collection.&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;OData-style&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;language: http
GET /users?$skip=1000&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;language: http
200 OK

[]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Range-header-style&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;language: http
GET /users
Range: users=1000-&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;language: http
416 Requested Range Not Satisfiable&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;Notice that the unbounded range mimics the semantics of the OData-style request.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Comparison&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The response of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range&lt;/code&gt; header style request is precisely in line with the spec:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;A server SHOULD return a response with this status code if a request included a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range&lt;/code&gt; request-header field, and none of the range-specifier values in this field overlap the current extent of the selected resource, and the request did not include an If-Range request-header field. (For byte-ranges, this means that the first-byte-pos of all of the byte-range-spec values were greater than the current length of the selected resource.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Note, as well, that byte-ranges are specified here as a single use-case of the range header, firmly implying that the usage as shown here is the correct semantic usage.&lt;/p&gt;

&lt;p&gt;The OData-style is not allowed to return a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;416&lt;/code&gt; status code, because it never sent a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range&lt;/code&gt; header.  One could argue, however, that this status code is semantically correct, even for the OData style request.&lt;/p&gt;

&lt;h3 id=&quot;additional-functionality-of-the-range-header&quot;&gt;Additional functionality of the range header.&lt;/h3&gt;

&lt;p&gt;Here are some things that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range&lt;/code&gt; header supports that have no analog in the OData-style.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Discoverability&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;language: http
OPTIONS /users&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;language: http
200 OK
Accept-Ranges: users&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Range header style allows for discovery of acceptable ranges via the OPTIONS HTTP verb.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Last-n&lt;/em&gt; requests&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;language: http
GET /users
Range: users=-5&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;language: http
206 Partial Content
Accept-Ranges: users
Content-Range: users 195-199/200

[ 195, …, 199 ]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Range header style allows for requests rooted at the end of the entity, rather than the begining.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multipart ranges&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;language: http
GET /users
Range: users=0-9,50-59&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;language: http
206 Partial Content
Accept-Ranges: users
Content-Type: multipart/mixed; boundary=next

--next
Content-Range: users 0-9/200

[ 0, …, 9 ]

--next
Content-Range: users 50-59/200

[ 50, …, 59 ]

--next--&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range&lt;/code&gt; header style allows for requests that specify multiple ranges; HTTP supports sending results back as a multipart document.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;If-Range&lt;/code&gt; header&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;If-Range&lt;/code&gt; header allows a range of the entity to be downloaded if it has not changed, but download the entire entity if it has changed.  These semantics don’t really fit the pagination model very well, since it is pretty much aimed at resuming paused downloads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Infinite or indeterminate collections&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;language: http
GET /users?name=Fred&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;language: http
206 Partial Content
Accept-Ranges: users
Content-Range: users 0-100/*

[ 0, …, 100 ]&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;As mentioned earlier, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Content-Range&lt;/code&gt; response header can specify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt; as the total size of the entity.  This means that the entity has an unknown or unbounded size.  This is particularly useful in search applications that may not know the full size of the result set for every query.&lt;/p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;To me, it seems that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range&lt;/code&gt; header is both more powerful and more semantically correct than the OData-style of query string parameters (or any query string style, for that matter). As such, I will always use the standard &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Range&lt;/code&gt; HTTP header whenever I implement REST APIs.&lt;/p&gt;

&lt;p&gt;I urge you to do the same.&lt;/p&gt;


   </description>
  </item>
  <item>
   <title>Getting a Proper MVC Date-picker using jQuery UI</title>
   <link>https://otac0n.com/blog/2011/09/03/getting-a-proper-mvc-datepicker-using-jquery-ui.html</link>
   <pubDate>Sat, 03 Sep 2011 00:00:00 +0000</pubDate>
   <guid isPermaLink="false">https://otac0n.com/blog/2011/09/03/getting-a-proper-mvc-datepicker-using-jquery-ui</guid>
   <description>
&lt;p&gt;There are plenty of tutorials out there on how to get date-pickers to work in MVC, but most of them that I have seen fall short for some reason or another.  Here are my requirements for a “proper” date-picker in MVC:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;It must be automatic, when using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EditorFor&lt;/code&gt; family of methods.&lt;/li&gt;
  &lt;li&gt;It must degrade gracefully. That is, it should fall back to a regular text box for users without JavaScript.&lt;/li&gt;
  &lt;li&gt;It must &lt;em&gt;always&lt;/em&gt; work for any complex model.&lt;/li&gt;
  &lt;li&gt;It must round-trip the data entered, even if the data is an invalid date.&lt;/li&gt;
  &lt;li&gt;It must be self-contained.  That is, it should not require a script at the top of the page to work.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Some demos fail to work for complex models, and most require a surrogate script at the top of the page.  We’ll see how to avoid those problems in the coming sections.  I will be assuming that your project already has jQuery and jQuery UI.&lt;/p&gt;

&lt;h2 id=&quot;automatic-editor&quot;&gt;Automatic Editor&lt;/h2&gt;

&lt;p&gt;The ability for MVC to automatically pick an editor based on the data-type has been covered at length before, just &lt;a href=&quot;http://www.google.com/search?q=EditorTemplates&quot;&gt;search Google for “EditorTemplates”&lt;/a&gt; if you are looking for examples.&lt;/p&gt;

&lt;p&gt;Quickly, then, here is how to add an automatic template for any type:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Navigate to the ~/Views/Shared folder of your web project.&lt;/li&gt;
  &lt;li&gt;Create a folder named “EditorTemplates”, if it does not already exist.&lt;/li&gt;
  &lt;li&gt;Inside of this folder, create a partial view with the name of your type. (DateTime, in our case).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We will also choose to have a strongly-typed view, using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DateTime?&lt;/code&gt; as our type.  This will allow it to work for both nullable and non-nullable dates&lt;/p&gt;

&lt;p&gt;Here is how the folder structure should be laid out:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://otac0n.com/blog/images/Date%20Picker%20-%201%20-%20Layout.png&quot; title=&quot;Date Picker - 1 - Layout&quot;&gt;Date Picker - 1 - Layout&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, MVC will automatically select our editor whenever it has a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DateTime&lt;/code&gt; or a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Nullable&amp;lt;DateTime&amp;gt;&lt;/code&gt; to render.&lt;/p&gt;

&lt;h2 id=&quot;round-trippin-with-my-two-favorite-allies&quot;&gt;Round-trippin’ With My Two Favorite Allies&lt;/h2&gt;

&lt;p&gt;We need to use a regular HTML text box for our date picker for two reasons:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;It will allow for date-input, even if the user has disabled JavaScript.&lt;/li&gt;
  &lt;li&gt;MVC will automatically round-trip the data and perform model binding, if it is rendered in a certain way.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We chose to use a dynamic partial view, so that we could round-trip textual data, above, so the simplest way to get the editor working is this, placed in the DateTime.cshtml file:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: cshtml
@model DateTime?
@Html.TextBox(&quot;&quot;, Model)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Interestingly, we are passing an empty string in for the “name” parameter for the text box.  This is the &lt;em&gt;secret sauce&lt;/em&gt; for getting MVC to render the proper name to support complex models and for it to automatically round-trip the model for.  Second, we are simply passing the model as the value of the text box.  MVC will take this and call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ToString()&lt;/code&gt; on the value, which will give us the default formatting for dates.&lt;/p&gt;

&lt;p&gt;We may, however, want dates to be shown without their time component. To do that, we need to override the default formatting to our liking:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: cshtml
@model DateTime?
@Html.TextBox(&quot;&quot;, Model.HasValue ? Model.Value.ToString(&quot;d MMM yyyy&quot;) : &quot;&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This will not prevent the users’ input from round-tripping, but will instead provide a default formatting for views where there is no posted data to reference, e.g. loading the edit view for the first time.&lt;/p&gt;

&lt;h2 id=&quot;self-contained-script&quot;&gt;Self-contained Script&lt;/h2&gt;

&lt;p&gt;Some people prefer to have a single script for wiring-up their date-pickers at the top of the page.  I find this to be less than ideal, because I usually don’t date pickers on a page, so it doesn’t belong in the master layout.  I also don’t want to duplicate the code on every page, because it means that a simple change to the date picker would have to be performed in many places, and it could easily be forgotten on a page, preventing date pickers from working there.&lt;/p&gt;

&lt;p&gt;With that in mind, my preference is to have a self-contained script for creating the date-picker immediately following the text box.  The challenge that we face when we want to do this is coming up with a way to refer to the specific text-box in a jQuery selector.  The easiest way, from a jQuery standpoint, would be to use the ID of the text box.&lt;/p&gt;

&lt;p&gt;Luckily, MVC allows us access to the field name using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName&lt;/code&gt; method.  This is, in fact, the way that MVC assigns the name and ID to the text box.  However, there is no built-in way to turn that name into an ID.  A quick perusal of the MVC source code shows that the ID is a simple text replacement.  We can precisely emulate their text replacement with a regular expression replacement.  Here is the completed control:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: cshtml
@model DateTime?
@{
    var name = Html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(string.Empty);
    var id = System.Text.RegularExpressions.Regex.Replace(name, @&quot;[^-\w\d:_]&quot;, HtmlHelper.IdAttributeDotReplacement);
}
@Html.TextBox(&quot;&quot;, Model.HasValue ? Model.Value.ToString(&quot;d MMM yyyy&quot;) : &quot;&quot;)
&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;$(function () { $(&quot;#@id&quot;).datepicker({ dateFormat: &apos;d M yy&apos; }); });&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, we have a feature-complete, self-contained date picker, that is automatically applied for all DateTime fields!&lt;/p&gt;


   </description>
  </item>
  <item>
   <title>Getting JavaScript IntelliSense in MVC Razor Views</title>
   <link>https://otac0n.com/blog/2011/09/01/getting-javascript-intellisense-in-mvc-razor-views.html</link>
   <pubDate>Thu, 01 Sep 2011 00:00:00 +0000</pubDate>
   <guid isPermaLink="false">https://otac0n.com/blog/2011/09/01/getting-javascript-intellisense-in-mvc-razor-views</guid>
   <description>
&lt;p&gt;A while ago, I posted about Getting IntelliSense working in ASP.NET MVC 3.  Since the release MVC 3, the primary view engine has changed to Razor, and the previous technique isn’t as elegant.&lt;/p&gt;

&lt;p&gt;With that in mind, I searched for a slightly prettier way to get IntelliSense working in Razor views.  I was, unfortunately, unable to get the scripts to be referenced in the views &lt;em&gt;automatically&lt;/em&gt;, but I think that this way is clean enough.&lt;/p&gt;

&lt;p&gt;I used a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@section&lt;/code&gt; directive to scoop out a part of the page during rendering, in order to prevent the “vsdoc” scripts files from being rendered to the final output. Here is how it looks in action:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://otac0n.com/blog/images/Razor%20Intellisense%20-%201%20-%20Working.png&quot; alt=&quot;Razor Intellisense - 1 - Working&quot; title=&quot;Razor Intellisense - 1 - Working&quot; /&gt;&lt;/p&gt;

&lt;p&gt;But now we have a couple of challenges to deal with. If we just ignore the section, we get this:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The following sections have been defined but have not been rendered for the layout page “~/Views/Shared/_Layout.cshtml”: “intellisense”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And we know that we don’t want to render it to the final output, so we have to come up with a way to trick the Razor engine into thinking that we did, in fact, render the output.&lt;/p&gt;

&lt;p&gt;My first attempt at solving this was to put this into the _Layout.cshtml page:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: cshtml
@{RenderSection(&quot;intellisense&quot;, required: false);}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But that was not enough to trick the view engine. Apparently, you have to actually &lt;em&gt;render&lt;/em&gt; the section &lt;em&gt;somewhere&lt;/em&gt; in order for it to be considered “rendered. Luckily, we can just render it to a throw-away StringWriter, like so:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: cshtml
@{WriteTo(new StringWriter(), RenderSection(&quot;intellisense&quot;, required: false));}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That is &lt;em&gt;just enough&lt;/em&gt; to get it to work properly and display the IntelliSense as desired.&lt;/p&gt;

&lt;p&gt;I am still looking for a way to get this to happen automatically, but for now, placing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@section intellisense&lt;/code&gt; region at the top of each view will have to do.&lt;/p&gt;


   </description>
  </item>
  <item>
   <title>Slick Analytics with LogParser and SqlBulkCopy</title>
   <link>https://otac0n.com/blog/2011/08/31/slick-analytics-with-logparser-and-sqlbulkcopy.html</link>
   <pubDate>Wed, 31 Aug 2011 00:00:00 +0000</pubDate>
   <guid isPermaLink="false">https://otac0n.com/blog/2011/08/31/slick-analytics-with-logparser-and-sqlbulkcopy</guid>
   <description>
&lt;h2 id=&quot;slick-analytics&quot;&gt;Slick Analytics&lt;/h2&gt;

&lt;p&gt;What do you do when you need to add analytics to your server?  Well, &lt;a href=&quot;http://www.google.com/analytics/&quot;&gt;Google Analytics&lt;/a&gt; is a good option, for sure, but it doesn’t capture important, juicy details like bandwidth usage, time to complete requests, cache-hits and so on.  If you need data like this, the best source is going to be the web access logs from your HTTP server.&lt;/p&gt;

&lt;p&gt;I’ve taken a look at a few 3rd party tools for creating analytics from these log files, and there are downsides to every one of them.  &lt;a href=&quot;http://fwww.cacti.net/&quot;&gt;Cacti&lt;/a&gt; is a pretty good option, however it requires a few things that may not be installed on a Windows server (i.e. PHP, MySQL, RRDTool, and net-snmp).  So, based on the fact that most existing solutions aren’t designed to fit seamlessly into a windows environment, I decided to come up with my own solution.&lt;/p&gt;

&lt;p&gt;My solution is based on a couple of off-the-shelf Microsoft products that, if you are running on the Microsoft stack, should already be licensed to you.  Here’s the tool chain:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;IIS&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.microsoft.com/downloads/en/details.aspx?FamilyID=890cd06b-abf8-4c25-91b2-f8d975cf8c07&quot;&gt;Log Parser 2.2&lt;/a&gt; (For turning W3C logs into an easy-to-import format.  It may also support Apache W3C logs, but I haven’t tested it.)&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;some secret sauce&lt;/em&gt;&lt;/li&gt;
  &lt;li&gt;SQL Server&lt;/li&gt;
  &lt;li&gt;SQL Server Reporting Services (or your favorite reporting suite)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, what is the secret sauce?  Well, SQL Server’s ADO.NET provider exposes the SQL Server Bulk Import API through a class called &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx&quot;&gt;SqlBulkCopy&lt;/a&gt;.  We can easily craft a C# program to take the clean, consistent output of Log Parser and stream it into SQL Server at breakneck speeds.&lt;/p&gt;

&lt;h2 id=&quot;log-parsing&quot;&gt;Log Parsing&lt;/h2&gt;

&lt;p&gt;First, let’s get Log Parser humming.  Microsoft’s Log Parser accepts SQL-like commands from the command line, and, depending on the particular command, can output to a variety of text formats, execute SQL statements, or create images.  Here is an example of the type of SQL Statement we are looking for:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: sql
SELECT * INTO log1.csv FROM C:\WINDOWS\system32\LogFiles\W3SVC1\ex110101.log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, as you may be able to tell from the file path, we need to parameterize the source for different IIS sites (e.g. W3SVC9999) and dates (e.g. ex110228.log).  Here is an example command script that can take care of those variables:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: batch
@echo off
set logparser=&quot;C:\Program Files\Log Parser 2.2\LogParser.exe&quot;

set siteid=%1
if &quot;%siteid%&quot;==&quot;&quot; set siteid=1
set logdate=%date:~-2%%date:~4,2%%date:~7,2%
%logparser% &quot;SELECT * INTO log-w3svc%siteid%-ex%logdate%.csv FROM C:\WINDOWS\system32\LogFiles\W3SVC%siteid%\ex%logdate%.log&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you run that, you should end up with a CSV file in the current directory, with the current day’s logs for the default IIS website.  It also accepts the website ID number as a parameter on the command line, if you want to run this for more than one site.&lt;/p&gt;

&lt;p&gt;Now, here I would like to note that Log Parser supports a mode of operation in which it remembers where it left off in a log file, and skips there on subsequent runs.  However, I have found that, since IIS does not flush its log files and since Windows caches writes, the log will sometimes end half-way through an entry.  When a situation like this arises, Log Parser gets confused and completely fails to properly parse any further entries.  In addition, its SQL support is useful but is unable to do the incremental loads that we would like to do.&lt;/p&gt;

&lt;h2 id=&quot;set-up-the-database&quot;&gt;Set-up the Database&lt;/h2&gt;

&lt;p&gt;We need a place to shove that data, but we have two masters to server at this point.  On one hand, we want to transfer as little data to the database server as possible, for obvious reasons.  On the other, we don’t want to have long-running transactions against the main IIS logs table, since it is really made for OLAP and response time of queries is paramount.  This all leans toward a scheme of staging and merging data, rather than cherry-picking new rows to import.  And, even though we don’t want to transfer tons of data, we should be &lt;em&gt;OK&lt;/em&gt; with 1-day’s-worth in a staging table.  After the data is staged, it can be incrementally moved into the main storage table to reduce the impact on the analytics.&lt;/p&gt;

&lt;p&gt;So, we will need two (very similar) tables during our import process: the staging table, and the main storage table.  The main storage table should match the W3C Log format, like so:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: sql
CREATE TABLE [dbo].[w3clog]
(
    [RowId] bigint IDENTITY(1,1) NOT NULL PRIMARY KEY,
    [LogFilename] varchar(255) NOT NULL,
    [LogRow] int NOT NULL,
    [date] date NULL,
    [time] time(0) NULL,
    [datetime] AS (CONVERT(datetime2(0), date + CONVERT(datetime, time, 0), 0)) PERSISTED,
    [c-ip] varchar(50) NULL,
    [cs-username] varchar(255) NULL,
    [s-sitename] varchar(255) NULL,
    [s-computername] varchar(255) NOT NULL,
    [s-ip] varchar(50) NULL,
    [s-port] varchar(255) NULL,
    [cs-method] varchar(255) NULL,
    [cs-uri-stem] varchar(2048) NULL,
    [cs-uri-query] varchar(max) NULL,
    [sc-status] int NULL,
    [sc-substatus] int NULL,
    [sc-win32-status] bigint NULL,
    [sc-bytes] int NULL,
    [cs-bytes] int NULL,
    [time-taken] bigint NULL,
    [cs-version] int NULL,
    [cs-host] varchar(255) NULL,
    [cs(User-Agent)] varchar(1000) NULL,
    [cs(Cookie)] varchar(max) NULL,
    [cs(Referer)] varchar(2000) NULL,
    [s-event] varchar(255) NULL,
    [s-process-type] varchar(255) NULL,
    [s-user-time] int NULL,
    [s-kernel-time] int NULL,
    [s-page-faults] int NULL,
    [s-total-procs] int NULL,
    [s-active-procs] int NULL,
    [s-stopped-procs] int NULL
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The staging table will be an almost identical temp table, with the single omission of the computed ‘datetime’ column.&lt;/p&gt;

&lt;h2 id=&quot;build-the-importer&quot;&gt;Build the Importer&lt;/h2&gt;

&lt;p&gt;So, now it is time to explore the power of the SqlBulkImporter class.&lt;/p&gt;

&lt;p&gt;This code is &lt;a href=&quot;https://github.com/otac0n/LogImporter&quot;&gt;available on GitHub&lt;/a&gt;, so there is no need to follow along unless you are building a custom version.  In light of this, I will be skimming over a few of the easier parts.&lt;/p&gt;

&lt;h3 id=&quot;create-the-connections&quot;&gt;Create the Connections&lt;/h3&gt;

&lt;p&gt;Our importer needs to be able to read the CSV files, and spit the data into SQL server. Luckily, both of these are supported by Microsoft’s ADO.NET providers. First, we will use a standard SQL Server connection for the destination database:&amp;lt;/p&amp;gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://otac0n.com/blog/images/SqlBulkCopy%20-%201%20-%20WebLogs%20Connection.png&quot; alt=&quot;SqlBulkCopy - 1 - WebLogs Connection&quot; title=&quot;SqlBulkCopy - 1 - WebLogs Connection&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Next, we will use an ODBC connection for the CSV files:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: text
Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq=.;Extensions=csv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;https://otac0n.com/blog/images/SqlBulkCopy%20-%202%20-%20CSV%20Connection.png&quot; alt=&quot;SqlBulkCopy - 2 - CSV Connection&quot; title=&quot;SqlBulkCopy - 2 - CSV Connection&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Using the Microsoft Text Driver, it is possible to read CSV files like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: csharp
var table = new DataTable();
using (var connection = new OdbcConnection(Settings.Default.ImportDriver))
{
    var dataAdapter = new OdbcDataAdapter(&quot;select * from log1.csv&quot;, connection);
    dataAdapter.Fill(table);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;streaming-the-data&quot;&gt;Streaming the Data&lt;/h3&gt;

&lt;p&gt;The little example above is fine-and-dandy for reading the data into memory, but just for the sake of future-proofing, we should aim to stream the data in.  This will ensure that we can import successfully, even during extreme loads. Rather than using a DataAdapter and DataTable, we will opt to read the rows and columns ourselves with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecuteReader&lt;/code&gt; family of methods.&lt;/p&gt;

&lt;p&gt;To clear up any uncertainty, here is the order and nesting of the various operations that will need to take place for a successful, performant import:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Connect to the destination database
    &lt;ul&gt;
      &lt;li&gt;Begin a transaction
        &lt;ul&gt;
          &lt;li&gt;Create a temporary “staging” table for the logs&lt;/li&gt;
          &lt;li&gt;For each CSV file of interest:
            &lt;ul&gt;
              &lt;li&gt;Open a reader for the CSV file
                &lt;ul&gt;
                  &lt;li&gt;Bulk-import the data from the CSV file into the staging table&lt;/li&gt;
                &lt;/ul&gt;
              &lt;/li&gt;
              &lt;li&gt;Close the CSV file&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;Merge the contents of the staging table into the main storage table&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Commit the transaction&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Disconnect from the destination database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are only two noteworthy bits: the bulk import itself and the merge operation.&lt;/p&gt;

&lt;h4 id=&quot;the-bulk-import&quot;&gt;The Bulk Import&lt;/h4&gt;

&lt;p&gt;The code I use to do the import is fairly simple:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: csharp
private static void BulkImport(IDataReader reader, SqlTransaction transaction)
{
    using (var importer = new SqlBulkCopy(transaction.Connection, SqlBulkCopyOptions.Default, transaction))
    {
        for (int field = 0; field &amp;lt; reader.FieldCount; field++)
        {
            var name = reader.GetName(field);
            importer.ColumnMappings.Add(name, name);
        }

        importer.DestinationTableName = &quot;#w3clog_staging&quot;;
        importer.WriteToServer(reader);
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Simple as it is, there is a lot that we can learn from this compact section of code:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SqlBulkCopy&lt;/code&gt; class can be given options to create an internal transaction, fire (or bypass) triggers, fire (or bypass) check constraints, insert into identity columns, and etc.&lt;/li&gt;
  &lt;li&gt;Bulk SQL operations can enter into external transaction, and can be rolled back in the same way that any transaction can. I was expecting this, but was still pleasantly surprised to find that SQL Server inherently supports this.&lt;/li&gt;
  &lt;li&gt;SQL Bulk Copy operations use an ordinal column mapping by default.  This means that columns are mapped based on their position in the import data and in the table rather than their names.  This can be overridden by mapping each column pair by some combination of ordinal position and column name.  Here, we are using a simple name-to-name mapping.&lt;/li&gt;
  &lt;li&gt;Bulk operations can be performed against temp tables.  I was not expecting this to work, and was again pleasantly surprised.&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SqlBulkCopy&lt;/code&gt; class can use either a set of DataRows (from a DataTable, for example) or an IDataReader as its source.&lt;/li&gt;
  &lt;li&gt;ADO.NET does not have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;time&lt;/code&gt; data type, it uses DateTime instead. In addition, the bulk importer does not expose any way to manually convert the columns.  Therefore, either the destination table must use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;datetime&lt;/code&gt; for all &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;time&lt;/code&gt; columns, or the source reader must expose the data as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;varchar&lt;/code&gt;.  (It would also be possible to wrap one IDataReader with another that did the mapping, but this is more work than it is worth, in practice.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;the-merge-operation&quot;&gt;The Merge Operation&lt;/h4&gt;

&lt;p&gt;The final notable part of the program is the merge operation.  There are several ways to get this done; from a single, complex insert statement, to individual insert operations.&lt;/p&gt;

&lt;p&gt;We will be aiming for a set-based approach, utilizing joins to do most of the heavy lifting.&lt;/p&gt;

&lt;p&gt;First, to delete entries that already exist in the main table, we issue a command like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: sql
DELETE
    s
FROM
    [#w3clog_staging] s
INNER JOIN
    dbo.[w3clog] p
  ON
    s.[LogFilename] = p.[LogFilename]
  AND
    s.[LogRow] = p.[LogRow]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Simple stuff really, but to help it out, we will probably want a unique index on the main table: (this only needs to be done once)&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: sql
CREATE UNIQUE NONCLUSTERED INDEX [UK_w3clog_LogRow] ON dbo.[w3clog] 
(
    [LogFilename] ASC,
    [LogRow] ASC
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next we need to delete duplicate entries that may have crept into the staging table:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: sql
DELETE FROM
    [#w3clog_staging]
WHERE
    [RowId] IN
      (
        SELECT
            RowId
        FROM
          (
            SELECT
                RowId,
                ROW_NUMBER() OVER (PARTITION BY [LogFilename], [LogRow] ORDER BY [RowId]) [Instance]
            FROM
                [#w3clog_staging]
          ) instances
        WHERE
            [Instance] &amp;gt; 1
      )
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This uses the SQL Server Window Function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ROW_NUMBER()&lt;/code&gt; to determine individual rows to delete.&lt;/p&gt;

&lt;p&gt;The final action is to move the data into the main table:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: sql
INSERT INTO
    [w3clog]
    (
        [LogFilename], [LogRow], [date], …
    )
SELECT
    [LogFilename], [LogRow], [date], …
FROM
    [#w3clog_staging]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Done! Now our whole import process is complete. Let’s see if we can turn this into pretty graphs…&lt;/p&gt;

&lt;h2 id=&quot;analyzing-the-data&quot;&gt;Analyzing the Data&lt;/h2&gt;

&lt;p&gt;Let’s get a simple graph showing the last 3 day’s hits, upload, and download, grouped into hourly buckets.&lt;/p&gt;

&lt;p&gt;First, the query:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: sql
SELECT
    DATEPART(hour, [time]),
    COUNT(*) [hits],
    SUM([sc-bytes]) [upload-bytes],
    SUM([cs-bytes]) [download-bytes]
FROM
    dbo.[w3clog]
WHERE
    [datetime] &amp;gt;= DATEADD(day, -3, GETUTCDATE())
GROUP BY
    DATEPART(hour, [time])
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Simple stuff, right?&lt;/p&gt;

&lt;p&gt;So, here is how my server’s graph looks: (in Excel, since I’m using SQL Express on my server)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://otac0n.com/blog/images/SqlBulkCopy%20-%202%20-%20Graph.png&quot; alt=&quot;SqlBulkCopy - 2 - Graph&quot; title=&quot;SqlBulkCopy - 2 - Graph&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Can we find out what bots are hitting the site?  Sure:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: sql
SELECT
    [cs(User-Agent)],
    COUNT(*) [hits],
    COUNT(DISTINCT [c-ip]) [ips]
FROM
    [w3clog]
WHERE
    [cs(User-Agent)] LIKE &apos;%http%&apos;
GROUP BY
    [cs(User-Agent)]
ORDER BY
    [hits] DESC,
    [ips] DESC
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here are my results:&lt;/p&gt;

&lt;table&gt;
  &lt;colgroup&gt;
     &lt;col span=&quot;1&quot; style=&quot;width: 58%;&quot; /&gt;
     &lt;col span=&quot;2&quot; style=&quot;width: 16%;&quot; /&gt;
  &lt;/colgroup&gt;

  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;User Agent&lt;/th&gt;
      &lt;th&gt;Hits&lt;/th&gt;
      &lt;th&gt;Distinct IPs&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;

  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)&lt;/td&gt;
      &lt;td&gt;71624&lt;/td&gt;
      &lt;td&gt;112&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;Mozilla/5.0 (compatible; Googlebot/2.1;  http://www.google.com/bot.html)&lt;/td&gt;
      &lt;td&gt;60536&lt;/td&gt;
      &lt;td&gt;441&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;Mozilla/5.0 (compatible; bingbot/2.0;  http://www.bing.com/bingbot.htm)&lt;/td&gt;
      &lt;td&gt;32636&lt;/td&gt;
      &lt;td&gt;329&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;Mozilla/5.0 (compatible; Baiduspider/2.0;  http://www.baidu.com/search/spider.html)&lt;/td&gt;
      &lt;td&gt;23749&lt;/td&gt;
      &lt;td&gt;225&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;Mozilla/5.0 (compatible; YandexBot/3.0;  http://yandex.com/bots)&lt;/td&gt;
      &lt;td&gt;16696&lt;/td&gt;
      &lt;td&gt;7&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;webnumbrFetcher/1.0 (http://webnumbr.com/)&lt;/td&gt;
      &lt;td&gt;16551&lt;/td&gt;
      &lt;td&gt;1&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;Mozilla/5.0 (compatible; DotBot/1.1; http://www.dotnetdotcom.org/, crawler@dotnetdotcom.org)&lt;/td&gt;
      &lt;td&gt;14147&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;Mozilla/5.0 (compatible; Yahoo! Slurp/3.0; http://help.yahoo.com/help/us/ysearch/slurp)&lt;/td&gt;
      &lt;td&gt;13892&lt;/td&gt;
      &lt;td&gt;61&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;Baiduspider ( http://www.baidu.com/search/spider.htm)&lt;/td&gt;
      &lt;td&gt;10445&lt;/td&gt;
      &lt;td&gt;550&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;Sosospider ( http://help.soso.com/webspider.htm)&lt;/td&gt;
      &lt;td&gt;8280&lt;/td&gt;
      &lt;td&gt;76&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;Mozilla/5.0 (compatible; SiteBot/0.1;  http://www.sitebot.org/robot/)&lt;/td&gt;
      &lt;td&gt;7614&lt;/td&gt;
      &lt;td&gt;5&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td&gt;Mozilla/5.0 (compatible; MJ12bot/v1.3.3; http://www.majestic12.co.uk/bot.php? )&lt;/td&gt;
      &lt;td&gt;7085&lt;/td&gt;
      &lt;td&gt;241&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Interesting!&lt;/p&gt;

&lt;p&gt;I have included many more queries to play with in the &lt;a href=&quot;https://github.com/otac0n/LogImporter&quot;&gt;project on GitHub&lt;/a&gt;.  Stay tuned for more!&lt;/p&gt;


   </description>
  </item>
  <item>
   <title>CoffeeDemo – A Simple Demo of IronJS, using CoffeeScript</title>
   <link>https://otac0n.com/blog/2011/06/29/coffeedemo-a-simple-demo-of-ironjs-using-coffeescript.html</link>
   <pubDate>Wed, 29 Jun 2011 00:00:00 +0000</pubDate>
   <guid isPermaLink="false">https://otac0n.com/blog/2011/06/29/coffeedemo-a-simple-demo-of-ironjs-using-coffeescript</guid>
   <description>
&lt;blockquote&gt;
  &lt;p&gt;Warning: the APIs used in this demo are subject to improvement in the future.  This is just a demo to get your feet wet with the 0.2.0.1 release of IronJS.  IronJS is still in the early stages, so your mileage may vary.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;How would you like to have a CoffeeScript compiler, running 100% managed code?  Well, I’ll leave out the foreplay and get right to it.&lt;/p&gt;

&lt;h2 id=&quot;fire-up-an-instance-of-visual-studio-with-nuget-installed&quot;&gt;Fire up an instance of Visual Studio, with NuGet installed.&lt;/h2&gt;

&lt;p&gt;This is pretty self-explanatory, but just in case you don’t have NuGet installed, you can &lt;a href=&quot;http://docs.nuget.org/docs/start-here/installing-nuget&quot;&gt;follow the directions on the NuGet website&lt;/a&gt; to get started.&lt;/p&gt;

&lt;h2 id=&quot;create-a-new-windows-application&quot;&gt;Create a new Windows Application.&lt;/h2&gt;

&lt;p&gt;Create a new Windows Application and name it ‘CoffeeDemo’.&lt;/p&gt;

&lt;h2 id=&quot;use-nuget-to-install-ironjs&quot;&gt;Use NuGet to install IronJS.&lt;/h2&gt;

&lt;p&gt;For those of you experienced with NuGet, the command in the Package Manager Console is:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: power-shell
Install-Package IronJS
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you prefer to use the GUI to add your package, you can &lt;a href=&quot;http://docs.nuget.org/docs/start-here/managing-nuget-packages-using-the-dialog&quot;&gt;consult the GUI directions&lt;/a&gt; provided at NuGet.org&lt;/p&gt;

&lt;h2 id=&quot;lay-out-your-project-and-form&quot;&gt;Lay-out your project and form.&lt;/h2&gt;

&lt;p&gt;At a minimum, you should add the following to your form:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;An input textbox, for CoffeeScript.&lt;/li&gt;
  &lt;li&gt;An output textbox, for JavaScript.&lt;/li&gt;
  &lt;li&gt;A button, for executing the JavaScript.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You will want to make your text boxes Multiline, and large enough to enter some JavaScript source.&lt;/p&gt;

&lt;p&gt;Here is how mine looks:&lt;br /&gt;
&lt;img src=&quot;https://otac0n.com/blog/images/CoffeeDemo%20-%201%20-%20Layout.png&quot; alt=&quot;CoffeeDemo - 1 - Layout&quot; title=&quot;CoffeeDemo - 1 - Layout&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I decided to use a split panel (anchored to all four sides) to contain my text boxes.  I set my text boxes to dock-fill and gave them both horizontal and vertical scroll bars.  I also anchored my Execute button to the bottom right.  Finally, I hate the name  Form1 , so I always rename my form to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;View&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MainView&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Name your controls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CoffeeScriptBox&lt;/code&gt;,  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JavaScriptBox&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExecuteButton&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;create-the-ironjs-context&quot;&gt;Create the IronJS context.&lt;/h2&gt;

&lt;p&gt;In the code for our view, we need to create an IronJS context, to do all of the heavy lifting behind the scenes.  We will do this with a function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InitializeContext&lt;/code&gt;, called from the constructor:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: csharp
using System;
using System.Windows.Forms;
using IronJS;
using IronJS.Hosting;
using IronJS.Native;

namespace CoffeeDemo
{
    public partial class View : Form
    {
        private CSharp.Context context;

        public View()
        {
            InitializeContext();
            InitializeComponent();
        }

        private void InitializeContext()
        {
            Action&amp;lt;string&amp;gt; alert = message =&amp;gt; MessageBox.Show(message);
            this.context = new CSharp.Context();
            this.context.SetGlobal(&quot;alert&quot;, Utils.CreateFunction(this.context.Environment, 1, alert));
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here, we can see the basics of creating a contexts, as well as exposing a CLR function to JavaScript.  The alert function is now wired up to call directly into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MessageBox.Show&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;wire-up-the-execute-button&quot;&gt;Wire-up the execute button.&lt;/h2&gt;

&lt;p&gt;Just wire up the Click even of the execute button to a function like this,&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: csharp
private void ExecuteButton_Click(object sender, EventArgs e)
{
    try
    {
        this.context.Execute(this.JavaScriptBox.Text);
    }
    catch (IronJS.Error.Error ex)
    {
        MessageBox.Show(ex.ToString(), &quot;Error from IronJS&quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can run a test like this:&lt;br /&gt;
&lt;img src=&quot;https://otac0n.com/blog/images/CoffeeDemo%20-%202%20-%20Hello%20World.png&quot; alt=&quot;CoffeeDemo - 2 - Hello World&quot; title=&quot;CoffeeDemo - 2 - Hello World&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;automatically-download-coffeescript&quot;&gt;Automatically download CoffeeScript.&lt;/h2&gt;

&lt;p&gt;There are a couple of different methods that we could use to bring CoffeeScript into our app.  We could include it in the folder, we could add it as an assembly resource, etc.&lt;/p&gt;

&lt;p&gt;My preference for this demo, however, is to download CoffeeScript to the /bin directory on the first run of the app.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: csharp
…
using System.IO;
using System.Net;
…
namespace CoffeeDemo
{
    public partial class View : Form
    {
        …
        public View()
        {
            …
            LoadCoffeeScript();
        }
        …
        private void LoadCoffeeScript()
        {
            if (!File.Exists(&quot;coffee-script.js&quot;))
            {
                var client = new WebClient();
                client.DownloadFile(&quot;https://raw.github.com/jashkenas/coffee-script/master/extras/coffee-script.js&quot;, &quot;coffee-script.js&quot;);
            }

            this.context.ExecuteFile(&quot;coffee-script.js&quot;);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At this point CoffeeScript is ready to go, and can be tested in the JavaScript text box.  We are loading it in the constructor, which could negatively impact the application start-up time.  However, for this example, I’m not concentrating on performance.&lt;/p&gt;

&lt;p&gt;Try this for an example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: javascript
alert(CoffeeScript.compile(&apos;a = (x) -&amp;gt; x * x&apos;, { bare: true }));
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;wire-up-the-textchanged-event-for-live-updating&quot;&gt;Wire-up the TextChanged event for live updating.&lt;/h2&gt;

&lt;p&gt;Add a field of type FunctionObject to the view’s class, and add this function as the TextChanged event on the CoffeeScript text box:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: csharp
private FunctionObject compile;
…
private void CoffeeScriptBox_TextChanged(object sender, EventArgs e)
{
    if (this.compile == null)
    {
        this .context.Execute(&quot;var compile = function (src) { return CoffeeScript.compile(src, { bare: true }); };&quot;);
        this .compile = this.context.GetGlobalAs&amp;lt;FunctionObject&amp;gt;(&quot;compile&quot;);
    }
     
    try
    {
        var boxedResult = this.compile.Call(this.context.Globals, this.CoffeeScriptBox.Text);
        var result = TypeConverter.ToString(boxedResult);
        this.JavaScriptBox.Text = result.Replace(&quot;\n&quot;, &quot;\r\n&quot;);
    }
    catch (IronJS.Error.Error)
    {
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This shows you how to call a JavaScript function from the CLR.&lt;/p&gt;

&lt;h2 id=&quot;coffeedemo-in-action&quot;&gt;CoffeeDemo in action!&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;https://otac0n.com/blog/images/CoffeeDemo%20-%203%20-%20Epic%20Win%21.png&quot; alt=&quot;CoffeeDemo - 3 - Epic Win!&quot; title=&quot;CoffeeDemo - 3 - Epic Win!&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You should now have a working, live-updating CoffeeScript compiler.  You will almost certainly notice the compilation lag on the first key-press where we are compiling the helper function, and calling the CoffeeScript compiler for the first time.  The lag is due to IronJS pushing everything into an in-memory, dynamic assembly.  Subsequent key-presses should be pretty quick, tho, and we are striving to make it faster.&lt;/p&gt;

&lt;h2 id=&quot;stay-tuned&quot;&gt;Stay tuned.&lt;/h2&gt;

&lt;p&gt;We are actively working on better .NET integration so that you can use native .NET types, all without using wrapper functions.  So, stay with us, and please &lt;a href=&quot;https://github.com/fholm/IronJS/commits/master&quot;&gt;follow us on Github&lt;/a&gt;!&lt;/p&gt;


   </description>
  </item>
  <item>
   <title>Getting IntelliSense in JavaScript files in ASP.NET MVC</title>
   <link>https://otac0n.com/blog/2010/12/29/getting-intellisense-in-javascript-files-in-aspnet-mvc.html</link>
   <pubDate>Wed, 29 Dec 2010 00:00:00 +0000</pubDate>
   <guid isPermaLink="false">https://otac0n.com/blog/2010/12/29/getting-intellisense-in-javascript-files-in-aspnet-mvc</guid>
   <description>
&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;/h2&gt;

&lt;p&gt;If you are like me, you have probably had trouble in the past trying to get JavaScript IntelliSense to work well in Visual Studio.&lt;/p&gt;

&lt;p&gt;You have probably gone through these steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“I’ll just add my script here, and presto!”&lt;/strong&gt;&lt;br /&gt;
&lt;img src=&quot;https://otac0n.com/blog/images/AddScript.png&quot; alt=&quot;AddScript&quot; title=&quot;AddScript&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“Well, that didn’t work.  It kept the App Path Modifier… dammit.”&lt;/strong&gt;&lt;br /&gt;
&lt;img src=&quot;https://otac0n.com/blog/images/Result.png&quot; alt=&quot;Result&quot; title=&quot;Result&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“I’ll just add a run-at attribute, so that ASP.NET transforms the path for me…”&lt;/strong&gt;&lt;br /&gt;
&lt;img src=&quot;https://otac0n.com/blog/images/RunAtServer.png&quot; alt=&quot;RunAtServer&quot; title=&quot;RunAtServer&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“Oh, my goodness gracious!”&lt;/strong&gt;&lt;br /&gt;
&lt;img src=&quot;https://otac0n.com/blog/images/RunAtServerResult.png&quot; alt=&quot;RunAtServerResult&quot; title=&quot;RunAtServerResult&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;so-where-does-that-leave-us&quot;&gt;So where does that leave us?&lt;/h2&gt;

&lt;p&gt;We can’t use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;runat=&quot;server&quot;&lt;/code&gt; on script tags, because ASP.NET has repurposed this format in order to include server-side code into the page.  This in effect means that we can’t use the “virtual path” to reference the same script from everywhere in our app.  Since we can’t use a virtual path, and we can’t use a relative path, we are stuck.&lt;/p&gt;

&lt;p&gt;Add on top of this that we often need to switch between different scripts for auto-completion, debugging, and production and you start to see the direness of the situation.&lt;/p&gt;

&lt;p&gt;At the center of the issue is the fact that Visual Studio can’t execute code in the editor in order to “know” where a script will come from.  If it could, then we would just write a chunk of code to do the virtual path transformation based on current mode.  We would have minified scripts for production (by default), VSDoc scripts for IntelliSense (in design mode), and full source scripts for debugging (when DEBUG is defined or a debugger is attached).&lt;/p&gt;

&lt;p&gt;At this point, I used to conclude that I had to live with all of my .aspx files living in one folder, or I had to live without JavaScript IntelliSense.&lt;/p&gt;

&lt;h2 id=&quot;a-solution&quot;&gt;A Solution&lt;/h2&gt;

&lt;p&gt;The little bit of magic required to make everything work in our favor is the fact that Visual Studio will treat everything outside of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;% ... %&amp;gt;&lt;/code&gt; code sections as though it were one continuous block of HTML.  This means that we can use a technique similar to conditional comments in order to ignore sections of HTML, but still have it recognized as part of the HTML document.&lt;/p&gt;

&lt;p&gt;Take these lines for example:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: html
&amp;lt;% if (false) { %&amp;gt;
    Test
&amp;lt;% } %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After being transformed by ASP.NET into a pure C# listing, this code will be compiled into an assembly.  Since the code is unreachable, it will be ignored and will not be checked for definite assignment as per the C# spec (§5.3.3.1).&lt;/p&gt;

&lt;p&gt;Extending this idea a little bit further, we can add our long-sought-after IntelliSense:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: html
&amp;lt;% if (false) { %&amp;gt;
    &amp;lt;script src=&quot;../../Scripts/jquery-1.4.1-vsdoc.js&quot; type=&quot;text/javascript&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;% } %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can use the relative path here, since this will never make it across the wire.  Just make sure that the script is referenced relative to the physical file in which this tag exists.&lt;/p&gt;

&lt;p&gt;Now, for the real script tag, we can use the static functions that ASP.NET provides to emit the proper path:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: html
&amp;lt;script src=&quot;&amp;lt;%: Url.Content(&quot;~/Scripts/jquery-1.4.1-vsdoc.js&quot;) %&amp;gt;&quot; type=&quot;text/javascript&quot;&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For ASP.NET WebForms, you would use the Server.ApplyAppPathModifier() function in place of Url.Content().&lt;/p&gt;

&lt;h2 id=&quot;variations-and-conclusion&quot;&gt;Variations and Conclusion&lt;/h2&gt;

&lt;p&gt;Variations on this trick would include using compiler directives like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#if FALSE&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/* block comments */&lt;/code&gt; to exclude the section of code.  Both of these methods seem to work.&lt;/p&gt;

&lt;p&gt;If you use the method described above with a build server, or while compiling view locally, you may get a compiler warning saying “unreachable code detected.”  If this warning bothers you you can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#pragma warning disable 162&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#pragma warning enable 162&lt;/code&gt; at the start and end of your if statement to suppress it.&lt;/p&gt;

&lt;p&gt;I hope this helps you get the most out of Visual Studio and ASP.NET!  Your feedback is welcomed.&lt;/p&gt;


   </description>
  </item>
  <item>
   <title>Pain Free T4MVC</title>
   <link>https://otac0n.com/blog/2010/12/23/pain-free-t4mvc.html</link>
   <pubDate>Thu, 23 Dec 2010 00:00:00 +0000</pubDate>
   <guid isPermaLink="false">https://otac0n.com/blog/2010/12/23/pain-free-t4mvc</guid>
   <description>
&lt;p&gt;Here is how to get T4MVC to run every time you build, without the mark-as-dirty hack or any Visual Studio support:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Download and install the prerequisites.&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;Unfortunately, Plain-old-VS2010 does not have the ability to run T4 Templates on every build built-in, so we have to rely on an external toolkit to help us along.  On the bright side, it’s just the Visual Studio SDK (which you might already have) plus an additional little tidbit.&lt;/p&gt;

    &lt;p&gt;These must be installed in order, and you should probably exit VS to do so:&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;&lt;a href=&quot;http://go.microsoft.com/fwlink/?LinkID=186904&quot;&gt;Visual Studio SDK&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;http://www.microsoft.com/downloads/details.aspx?FamilyID=0def949d-2933-49c3-ac50-e884e0ff08a7&quot;&gt;Visualization and Modeling SDK&lt;/a&gt;&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Start Visual Studio and open your project file for editing.&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;Right-click on the project in question, and choose “Unload Project”; this will make it show up as “(unavailable)”.  Now, you can right-click it again and choose “Edit YourProject.csproj”.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Add the relevant sections to your project file.&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;Set the following properties in your project:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: xml
&amp;lt;MvcBuildViews&amp;gt;true&amp;lt;/MvcBuildViews&amp;gt;
&amp;lt;TransformOnBuild&amp;gt;true&amp;lt;/TransformOnBuild&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;The result should look something like this:&lt;br /&gt;
&lt;img src=&quot;https://otac0n.com/blog/images/TransformOnBuild.png&quot; alt=&quot;.csproj Snippet&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;Add the toolkit magic as an MSBuild import:&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;language: xml
&amp;lt;Import Project=&quot;$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TextTemplating\v10.0\Microsoft.TextTemplating.targets&quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;Again, here is a visual of the result:&lt;br /&gt;
&lt;img src=&quot;https://otac0n.com/blog/images/TextTemplatingTargets.png&quot; alt=&quot;.csproj Snippet&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Save your changes and reload your project.&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;Right-click your project, which should still be showing as “(unavailable)”, and Voila!  Your T4 templates will re-gen on every build!&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;p&gt;“That’s pretty great,” you say, “but will it work on my build server?”&lt;/p&gt;

&lt;p&gt;Yes, it will work!  You simply need to follow the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ee847423.aspx#buildserver&quot;&gt;MSDN instructions&lt;/a&gt; for this.  Just a few files need to be copied on to the build server.&lt;/p&gt;

&lt;p&gt;I hope this helps people get the most out of MVC.  Your feedback is welcomed.&lt;/p&gt;


   </description>
  </item>
 </channel>
</rss>