Tuesday 13 April 2010

MVC DateTime Suffix HTMLHelper

Recently I have been working on an MVC Project, and tonight I got to the point where I wanted to output a date in a specific format, for example Tuesday 13th April 2010. Sadly DateTime formatting still doesn't allow you to specify output a suffix, you can do Tuesday 13 April 2010 but not what I wanted.


I decided that I could achieve what I wanted by writing a quick HTMLHelper, this would then allow me to specify a datetime format string with a magic / special character which I could then replace for the appropriate suffix.


Writing the helper was very quick and easy, if you want to learn about HTMLHelpers and how to write your own I recommend looking at Stephen Walther's Post on HTMLHelpers .

The code for my datetimehelper is below:


using System;
using System.Web.Mvc;

namespace mjjames.MVCHelpers
{
 public static class DateTimeExtensions
 {
  public static string DateTimeFormat(this HtmlHelper helper, string dateTimeFormat, DateTime dateTime){
            var dateTimeOutput = dateTime.ToString(dateTimeFormat);
            if (dateTimeFormat.Contains("~"))
            {
                dateTimeOutput = dateTimeOutput.Replace("~", GenerateDaySuffix(dateTime.Day));
            }
      return dateTimeOutput;
  }

        /// <summary>
        /// Generates a Day Suffix from the Day Number
        /// </summary>
        /// <param name="day">Day Number</param>
        /// <returns>Suffix String</returns>
     private static string GenerateDaySuffix(int day)
     {
         var suffix = "";
            //find out if the day matches a suffix which isn't th
         switch(day)
         {
             case 1:
                case 21:
                case 31:
                 suffix = "st";
                    break;
                case 2:
                case 22:
                 suffix = "nd";
                 break;
                case 3:
                case 23:
                 suffix = "rd";
                    break;
                default:
                 suffix = "th";
                 break;
         }
         return suffix;
     }
 }
}

Then to use it first include the namespace in your view:


<%@ Import Namespace="mjjames.MVCHelpers" %>

And then to use it call Html.DateTimeFormat passing the format string and the DateTime value. To use the day suffix include the ~ character. Note you can use it with.


<%= Html.DateTimeFormat("dddd d~ h", Model.StartDate) %>
<%= Html.DateTimeFormat("dddd d h", Model.EndDate) %>

There we go, nice and easy, if you want to use this feel free I hope it helps

Tuesday 6 April 2010

Using DOTRas - An Overview and some things I've learnt

Yesterday I decided to starting knocking together a quick application to help me backup my server to some local storage. The idea being that at any point I have a local copy of my server setup a maximum of a day old. The point of this application and how I've gone about writing it, what libraries I'm using etc will be part of a future blog post.


I decided early on that I however I wanted to transfer files I wanted to do this over a VPN to the server. I had several reasons for this, being able to expose my files over a network share, more secure etc. My Application will be running on an old laptop, so I first thought about just always having it connected to a VPN using windows, and run the application as normal. However I then thought what if the VPN disconnects and I don't notice, how long would it take until I noticed etc. So I decided to make the application create a VPN Connection at start up and then disconnect from it upon completion.


I figured that there would be a good library that would help with this and it turns out there is. DotRAS provides remote access service (RAS) components for .NET languages , it's tag line is "WindowsRAS made easy" and I have to say so far it has lived up to that.


A quick example of how to open the computers RAS PhoneBook :


using(var phoneBook = new RasPhoneBook())
{
     phoneBook.Open();
}
You could then find an existing entry within the phonebook to make a connection too and open a connection:

var entry = phoneBook.Entries.FirstOrDefault(e => e.Name.Equals("mikes test entry");
if(entry != null){
    entry.Open();
}

Now there's obviously alot you can do with it, create and manage connections programatically etc, use phone dialers but so far I'm just tinkering with VPN's.


Tips and Tricks

Now to what I wanted to post about, tips and tricks. Sadly whilst working with DOTRas I found a few gotcha's that I wanted to post about. I will also update this list as I find more. It's worth noting that all of these apply to DotRAS 1.1 and I'm using the Win2k8 build, some of these I know also apply to the XPSP2 build. And my development machine is Windows 7 x64.

Invalid Default PhoneBook Location

The default phonebook location, which is called when you just do phonebook.Open(), is set to use RasPhoneBookType.AllUsers, now this maps to : C:\ProgramData\Microsoft\Network\Connections\Pbk\rasphone.pbk which for me doesn't exist. The folders exist up to connections, I have no Pbk folder.


I could obviously check for this and then create the phonebook entry but really you should always use RasPhoneBookType.User which uses the phonebook located within the current users AppData.

The entry is not associated with a phone book

Actually quite an obvious issue but worth commenting on, If you create a new phonebook entry


var entry = RasEntry.CreateVpnEntry(_connectionName, IPAddress.Loopback.ToString(), RasVpnStrategy.Default,                                 RasDevice.GetDeviceByName("(PPTP)", RasDeviceType.Vpn));

And then try to set the user's credentials without first adding the entry to the phonebook:


entry.UpdateCredentials(new NetworkCredential(authenticationDetails.UserName, authenticationDetails.Password));

Everything goes horribly wrong, instead add the entry to the phonebook and then set the credentials.


phoneBook.Entries.Add(entry);
entry.UpdateCredentials(new NetworkCredential(authenticationDetails.UserName, authenticationDetails.Password));

Keep an eye on this post, I'll update it as I continue to use DotRAS and then on a later date post about my application in full.