14/11/2011

Stop Smoking

Many IT professionals I know, have or are currently smokers.
But sometimes the shoe doesn't fit, especially if you're working in the medical industry.

Last week myself and my wife switched to using TarGuard without reducing the amount of cigarettes we were used to smoking every day.

It is a lot harder for heavy smokers (20+ cigarettes a day) to stop smoking. Well, at least it used to be!

I have found the real cause behind unbearable withdrawal symptoms relating to stopping smoking to be the non-nicotine ingredients in cigarettes.

I was suprised when I first discovered that I was experiencing withdrawal symptoms while using TarGuard and Nicorette to supplement nicotine levels (TarGuard reduces nicotine levels).

At first I thought I was going crazy, but this simply proves a majority of withdrawal symptoms come from the non-nicotine ingredients of cigarettes (tar, cyanide etc.).

It seems to me like smoking hurts the lungs and also numbs them at the same time, so when going without a cigarette for a while - your lungs start hurting again.

Using TarGuard for a week entirely reduced the pressure/pain withdrawal symptoms for me. Currently, I am only using Nicorette (4mg) and swapping to the Nicorette (2mg) later this week before I stop entirely.

Now the only withdrawal symptom remaining is a slight irritability which is easily conquered by staying busy.

If you're a smoker, at the very least consider using TarGuard to reduce the damage of smoking almost entirely to your lungs!

09/11/2011

ASP.NET MVC - Extending HtmlHelper

Today, we will be looking at extending the HtmlHelper for ASP.NET MVC in C# using .NET 3.5sp1/4.

Lets look at some introductory basics:
Syntax for creating Extension methods
public static class {extensionclassname}
{
  public static {returntype} {methodName}(this {objectToExtend} {name})
  {
  }
}
So lets say we want to create an input helper, we could do something like this
public static class HtmlHelperExtensions
{
  public static InputHelper<T> Input<t>(this HtmlHelper<T> htmlHelper)
  {
    return new InputHelper(htmlHelper);
  }
}

public class InputHelper<T>
{
  private readonly HtmlHelper<T> _htmlHelper;

  public InputHelper(HtmlHelper<T> htmlHelper)
  {
    _htmlHelper = htmlHelper;
  }
}

Although it's not necessary to create a separate class to hold the methods for the input helper, it is preferred because of separation of concerns (SoC).

Next, we would add the namespace wherein the HtmlHelperExtensions is located to the <namespaces> section under pages < system.web.webPages.razor in the Web.Config located in the Views directory.

To access our input helper, we would call @Html.Input() and from there on custom methods to render a MvcHtmlString (which is a string - already safe for use as razor output - a normal string would be html encoded).

Here is an interesting use case:
Lets say we want to wrap html in a <div class="input"><- html here -></div> without having to manually write out <div class="input">....</div> every time?

This is done pretty easily, lets add a method to our existing InputHelper<T> class:
public MvcHtmlString Wrap(Func<object, HelperResult> htmlToWrap)
{
  var htmlBuilder = new StringBuilder();

  htmlBuilder.Append("<div class='input'>");

  htmlBuilder.Append(htmlToWrap.Invoke(_htmlHelper));

  htmlBuilder.Append("</div>");

  return MvcHtmlString.Create(htmlBuilder.ToString());
}

Here is an example on how to use this method from within a view:
@Html.Input().Wrap(@<text><label for="name" />@Html.TextBox("name")</text>)

The @<text>...</text> being passed to the method can be seen as a view which gets 'compiled' to html. So instead of writing to ouput:
<label for="name" />@Html.TextBox("name")
  using  htmlToWrap.Invoke(_htmlHelper) compiles down to
<label for="name" /><input type="text" id="name" name="name" />

HtmlHelper extensions are miracilious in the sense they can give you extreme refratoring capabilities and can do much more than one expects.

For example, I have written input extensions that simply calls
@Html.Input().TextBoxFor(model => model.MobileNo)
which in turn adds a label and applies mask behavior and validation logic to the element (behavior and validation via unobtrusive data-* attributes that javascript applies).

All in one line of code - and you could do the same!