SiteMapLite, Adding Html helpers

This might actually be my first open source project coming to fruition. I have created a lot of special Abandon-ware (Special in that they were abandoned before completion).

Anyway, things are looking good with SiteMapLite. In today’s iteration I have added a nice MenuHelper to help us render the main navigation bar. It also has a nice Cached SiteMap service which wraps around the actual SiteMap service and caches it nicely, so that the text files are not read and parsed for each request.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

public static class MenuHelper {


public static string RenderMainNav(this HtmlHelper helper) {
return RenderMainNav(helper, null);
}

public static string RenderMainNav(this HtmlHelper helper, object htmlAttributes) {

var nodes = CachedSiteMapService.Service.GetNodesForRole("Administrator");
StringBuilder sb = new StringBuilder();

sb.Append("<ul ");

AppendHtmlAttributes(sb, htmlAttributes);

sb.Append(">");

foreach (var node in nodes) {
sb.AppendFormat("<li><a href='/{0}/{1}' title={2}>{2}</a></li>\r\n", node.Controller, node.Action, node.Title);
}
sb.Append("</ul>");
return sb.ToString();
}

private static void AppendHtmlAttributes(StringBuilder sb, object htmlAttributes) {
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(htmlAttributes);
foreach (PropertyDescriptor property in properties) {
sb.AppendFormat(" {0}='{1}' ", property.Name.Trim('@')/* Remove the @ if the attribute is @class */, property.GetValue(htmlAttributes));
}
}
}

If you see, this MenuHelper just uses the CachedSiteMapService.Service instance to get the nodes for the role Administrator. As of now, we have hard coded the role to Administrator. In a future iteration, We’ll write code so that it uses the role of current session. This code creates a simple list of urls and it appends any html attributes passed in input parameter to the ul html attribute. [Checkout the updated SiteMapLite code at GitHub][1].

Till next time

[ [@minhajuddin][2] ] [1]: http://github.com/minhajuddin/sitemaplite [2]: http://twitter.com/minhajuddin

The Birth of SiteMapLite (ASP.NET MVC Sitemap provider)

Alright, the last post about the json sitemap provider got some people interested in this utility. So, I thought of improving the code a bit more before actually coding up the Html helpers to render the navigation links. So, here we go. ( I named this utility SiteMapLite so that it’s easy to reference it, If you’ve got a better name leave it in the comments ;) )

When you think about a sitemap there are a few things which come to mind

  1. The Nodes: Sitemaps are all about nodes, where each node is a hyperlink pointing to a resource, In our code we have a class called the SiteMapNode which represents a single node in a SiteMap.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

public class SiteMapNode {
public virtual int Id { get; set; }
public virtual string Action { get; set; }
public virtual string Controller { get; set; }
public virtual string Title { get; set; }
public virtual string Role { get; set; }
public int ParentId { get; set; }
public IEnumerable<SiteMapNode> Children;

public virtual bool IsInRole(string role) {
if (Role == null || Role.Trim().Length == 0) {
return true;
}
int count = Role.Split(',').Count(x => x.Trim().Equals(role, StringComparison.OrdinalIgnoreCase));
return count != 0;
}
public virtual bool IsRootNode {
get { return ParentId == 0; }
}
}

  1. The Hierarchy: Once you have all the nodes you would want the SiteMap to be laid out in a hierarchical fashion, So you would have a root node(s) which would then have children nodes, and those children nodes might have their own children. In our project, this hierarchy is represented by a simple list of SiteMapNodes. This list would have just the root nodes.

  2. You might be thinking how we can fashion the whole hierarchy by just using a simple list of root nodes, where do the children nodes go? The answer to that, is, every root node has a it’s own list of children nodes, that is how we store the hierarchy in SiteMapLite. Now the HtmlHelper which is to be created just has to take the list of root nodes and render the main navigation bar. And then based on the current node, render it’s second level navigation and so on.

Now that we understand the basics of sitemaps, we can take a look at the architecture of our code. I have applied a few [SOLID][1] techniques to make the code more extensible. Take a look at the following class diagram to get a feel of the architecture.

 

SiteMapLite

We have made the code more generic and flexible by moving the responsibility of reading the sitemap data to an interface called ISiteMapReader, Now, we can create any custom implementation of the ISiteMapReader which could read data from a json flat file or an XML file or a database or a webservice, and the code in the SiteMapService doesn’t have to change even by a tiny bit to utilize these SiteMapReaders. Now the responsibility of the SiteMapReader is just to retrieve all the SiteMapNodes from the persistence medium and return them in their raw form (without any grouping). The job of Grouping the nodes into a set of root nodes and wiring up their child references is done by the ISiteMapService. The only method which the Html helper would use would be the GetNodesForRole method. This method would return a list of root nodes which are accessible to the input role. This gives us a solid foundation to create our HtmlHelpers and extend the code base as we like without changing existing code. I know I haven’t explained the whole code, but by now you should have have a big picture of the whole project. To understand the code further, download the code from [http://github.com/minhajuddin/sitemaplite][2] . In a future blog post, I’ll create a few HtmlHelpers to render a basic navigation dashboard.

Till next time

[ [@minhajuddin][3] ] [1]: http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod [2]: http://github.com/minhajuddin/sitemaplite [3]: http://twitter.com/minhajuddin

Enter the JSON SiteMap provider for ASP.NET MVC

The other day (a week ago) I was trying to get a nice menu show up in one of my ASP.NET MVC projects, I had seen Maarten Balliauw‘s ASP.NET MVC SiteMap provider before. I thought I could just download the binaries, do some configuration and be done with it. But it turned out to be a lot more than that ;) . Well for starters, the asp.net mvc sitemap provider used the Authorize attribute to do the security trimming. Now in our application we used a different way to do authorization. In fact we had all the url’s mapped to authorized roles using in database table. So, there was no easy way for me to get this working in our project (I guess today the mvc sitemap provider has a way to customize the way the role based trimming is done). That’s when I thought I should come up with my own mvc sitemap, I said to myself “How hard can it really be?” :)

To get an idea of what I was after, I downloaded the code of the mvc sitemap provider from codeplex and got coding on my new sitemap provider. I don’t really like XML and all the gunk it comes with so I planned to use a different medium to store info about mvc sitemap nodes (.. part of the reason for not using XML is that I am not an expert at parsing XML ;) ). I really like JSON, so I decided to use a JSON file to store the info about the urls and their associated roles. I came up with a simple layout and saved the file as sitemap.json, the file initially looked like this:

1
2
3
4
5
6
7
8
9
10
11
12


[ {'Id':1,'Action':'Index','Controller':'Home','Title':'HOME','ParentId':0,'Role':'Anonymous,Administrator,Dashboard'},
{'Id':2,'Action':'About','Controller':'Home','Title':'About Us','ParentId':1,'Role':'Anonymous,Administrator,Dashboard'},
{'Id':3,'Action':'Faq','Controller':'Home','Title':'Faqs','ParentId':1,'Role':'Anonymous,Administrator,Dashboard'},
{'Id':4,'Action':'Contact','Controller':'Home','Title':'Contact Us','ParentId':1,'Role':'Anonymous,Administrator,Dashboard'},
{'Id':5,'Action':'Index','Controller':'Dashboard','Title':'Dashboard','ParentId':0,'Role':'Administrator'},
{'Id':6,'Action':'FunkyReport','Controller':'Dashboard','Title':'Funky Report','ParentId':5,'Role':'Administrator'},
{'Id':7,'Action':'Stats','Controller':'Dashboard','Title':'My Stats','ParentId':5,'Role':'Administrator'},
{'Id':8,'Action':'Stats','Controller':'Administrator','Title':'My Stats','ParentId':0,'Role':'Administrator'} ]


As you can see, each object in this array is a node. And each node has information about the ‘Action’, the ‘Controller’, the ‘Title’, a comma separated list of ‘Roles’, an ‘Id’ (to uniquely identify a node) and a ‘ParentId’ (to create a parent child relationship among the nodes. I know it doesn’t look good but I’ve chosen this so that it’s easy to parse stuff. I am using the JSON.NET library to do the JSON parsing, it’s a very easy to use library to serialize or deserialize objects. With that aside, I created a couple of methods which would read the file and create a list of nodes and group them up. Take a look at them:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

private void Init(string rawJsonData) {
JsonNodes = DeSerialize(rawJsonData);
}
protected virtual IList<JsonNode> DeSerialize(string rawJson) {
var nodes = JsonConvert.DeserializeObject<IList<JsonNode>>(rawJson);
return nodes;
}

protected virtual IEnumerable<JsonNode> GroupNodes(IList<JsonNode> nodes) {
//get root nodes
var rootNodes = nodes.Where(x => x.ParentId == 0).ToList();
//WL("Grouping {0} nodes in total and {1} root nodes", nodes.Count, rootNodes.Count());
//populate child nodes for each root node
foreach (var node in rootNodes) {
var children = nodes.Where(x => x.ParentId == node.Id).ToList();
//WL("Assigning {0} children to {1} node", children == null ? -1 : children.Count(), node.Title);
node.Children = children;
}
return rootNodes;
}

The code is pretty self explanatory. All I am doing is getting a list of nodes, and then grouping them up. Once I group them it’s just a matter of getting all the nodes, formatting them and printing it out to the screen, I’ll post another blog entry about the menu rendering in a couple of days, This is where you can grab the code for the JsonSiteMapProvider

Quick and Dirty way to get an ASP.NET website offline

I never thought that I was gonna write code for an ASP.NET Webforms project again. I’ve been creating all my projects in ASP.NET MVC since it hit beta. But, I guess Webforms is really good at some stuff, Coming up with quick and dirty web apps :)

Alright, So, I’ve got a web application which was created in ASP.NET MVC. The administrators of this web app want to control when the site is up. It’s basically a webapp for processing some stuff which happens only at day time. So, they don’t want the users (their agents) to go around and mess with the site during the night time or as soon as they get out of the office. We already had a nice web app with an administrator console through which the admins can do a lot of stuff like adding/de-activating users etc,. The administrators wanted a feature through which they could bring the site down or up using their admin page. A simple search showed up a lot of interesting articles, This one by Rick Strahl documents how you can take down an app, and bring it up without using “app_offline.htm” files. I didn’t want to take that route, because I think the app_offline way is the best, because it shuts down the application and unloads the application domain, You can find some more interesting info about it in this post by Scott Gu. Now, the downside of using this kind of approach is that, once the application is down, there is no way to bring it up using the same site.

Now, let’s see how we can use this nifty little feature which is available for asp.net 2.0+ apps to come up with an admin page through which we can take the site down or bring it back up.

1) The first thing you need to do is create a basic Webforms website or Web application from Visual Studio. On the default page you would want a few textboxes, radio buttons and a submit button, which looks like

site_admin_blog_post1

1
2
3
4
5
6
7
8
9
10
11
12
13
14

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs"
Inherits="Cosmicvent.SiteAdmin._Default" %>
Site Admin
<form id="form1">
<div>

<label for="UserName">
UserName:</label>

<label for="Password">
Password:</label></div>
</form>

2) This is the fragment of code which creates this GUI, Nothing too fancy.

3) Once we have that, it’s basically an exercise in creating some code which does the user/password matching and creates an app_offline.htm file in the right location.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

using System;
using System.IO;
using System.Web.Security;

namespace Cosmicvent.SiteAdmin {
public partial class _Default : System.Web.UI.Page {
private const string VALID_USERNAME = "administrator";
private const string VALID_HASHED_PASSWORD = "8D31D551A44B2DE3DFFA85842ABF38A8ACF14775";
private const string APP_OFFLINE_PATH = @"C:\";
private const string APP_OFFLINE_BACKUP_NAME = "app_offline.htm.bak";
private const string APP_OFFLINE_FILE_NAME = "app_offline.htm";
private const string APP_OFFLINE_CONTENT = @"
The site has been taken offline for Maintenance
<h2>The site has been taken offline for maintenance</h2>
We are sorry for the incovenience. Please check back again some time later

<!--
Here is some junk data for you IE !!!
Go to http://minhajuddin.com
Go to http://minhajuddin.com
Go to http://minhajuddin.com
Go to http://minhajuddin.com
Go to http://minhajuddin.com
Go to http://minhajuddin.com
Go to http://minhajuddin.com
Go to http://minhajuddin.com
Go to http://minhajuddin.com
Go to http://minhajuddin.com
Go to http://minhajuddin.com
Go to http://minhajuddin.com
Go to http://minhajuddin.com
Go to http://minhajuddin.com
Go to http://minhajuddin.com
Go to http://minhajuddin.com
-->
";

protected void Page_Load(object sender, EventArgs e) {
}

protected void SubmitButton_Click(object sender, EventArgs e) {
if (UserIsValid()) {
string backupFilePath = Path.Combine(APP_OFFLINE_PATH, APP_OFFLINE_BACKUP_NAME);
string appOfflineFilePath = Path.Combine(APP_OFFLINE_PATH, APP_OFFLINE_FILE_NAME);
if (TakeOfflineRadioButton.Checked) {
//create or rename the backup file
if (File.Exists(backupFilePath) && !File.Exists(appOfflineFilePath)) {
//rename
RenameFile(backupFilePath, appOfflineFilePath);
} else if (!File.Exists(appOfflineFilePath)) {
//create
CreateAppOffline(appOfflineFilePath);
}
output.InnerText = &amp;quot;Site taken down successfully&amp;quot;;
} else if (BringUpOnlineRadioButton.Checked) {
//rename the app_ofline file
if (File.Exists(appOfflineFilePath)) {
//rename
RenameFile(appOfflineFilePath, backupFilePath);
}
output.InnerText = "Site brought up successfully";
}
} else {
output.InnerText = "Invalid username or password";
}
}

private void CreateAppOffline(string appOfflineFilePath) {
using (StreamWriter streamWriter = File.CreateText(appOfflineFilePath)) {
streamWriter.Write(APP_OFFLINE_CONTENT);
}
}

private void RenameFile(string backupFilePath, string appOfflineFilePath) {
File.Move(backupFilePath, appOfflineFilePath);
}

private bool UserIsValid() {
return VALID_USERNAME.Equals(UserName.Text, StringComparison.OrdinalIgnoreCase) &&
VALID_HASHED_PASSWORD.Equals(Hash(Password.Text), StringComparison.OrdinalIgnoreCase);
}

private string Hash(string text) {
return FormsAuthentication.HashPasswordForStoringInConfigFile(text, "SHA1");
}
}
}

The code is pretty much self explanatory, Hope it helps someone. You just have to be careful about a couple of things:

  1. You still have to run this on a different website
  2. You need to give the right privileges on the directory APP_OFFLINE_PATH to the user which runs the IIS worker process. For IIS7 this is the NETWORK SERVICE user by default.

And before I forget, You can get the source code for this project from my git repository hosted on github at http://github.com/minhajuddin/blog_demos/tree/master

MBlog a light weight blogging engine created in asp.net mvc

Alright, I have posted a couple of meta blog posts, not very interesting to many. But, anyway, I just wanted to rant away on a few topics. With that aside. I’ll start a series of blog posts on developing web applications using asp.net mvc. I know there is a lot of information on the web already about asp.net mvc. This is just something which I am planning to do to better … myself.

I am planning to wake up a dormant open source project of mine called MBlog. It already has some code in it. But I am planning to start anew. And just to keep things a little interesting I will try to target the Mono framework. I’ve always wanted to see if I could get my apps to run on Mono. I have heard a lot of good stuff about it. If I can get this project working on Mono, I’ll definitely create more apps on Mono. Because Mono stands for everything free ;) I’ll try to stick to the following stack:

  1. ASP.NET MVC
  2. NHibernate
  3. Spark View Engine
  4. StructureMap for IoC
  5. Mono

Let’s see how this one goes ;)

Traits of great and the not so great bloggers

I am new to the blogosphere. That is in terms writing blog posts. However, as I tread my way through blogville, I have been discovering an old truth all over again. This was pounded home vigorously by [Dale Carnegie][1] in his best selling book [How to Win Friends and Influence People][2]. That principle is, if you really want others to listen to you (in this case read your blog posts ;) ) You’ve gotta stop treating them as idiots. Now, I hear people saying “hah, no blogger treats their readers as idiots”. But, I’ve seen it happen on a lot of blogs. Some bloggers just don’t give a damn about the readers, and they go on and on about how their new book has hit the book stores, How you can attend their new session (and give them some money) etc,. The problem with these kind of bloggers is that they are consumed by their own self. To hell with these kinda bloggers. The funny thing is they never succeed and wonder why their blog does not have as many subscribers as the blogs of so many successful bloggers.

And there are those other bloggers, the successful ones ([Phil Haack of haacked.com][2], [Jeff Atwood of codinghorror.com][4], [Scott Hanselman of hanselman.com][5] and others). It’s interesting to see what these guys do differently. They just don’t take their readers for granted. They post good content, which at the end of the day is any content which is gonna help the readers. It doesn’t matter how trivial or how obvious the stuff written on the blog post is. This is what all the bloggers should aspire to do. Do something positive which helps other people. And you know what, if you successfully do this; money, success and glory are all just byproducts. You’ll get all of them as a frigging byproducts.

Let me wrap up the whole thing by quoting from one of my favorite books ([How to Win Friends and Influence People][6] by [Dale Carnegie][7] emphasis is mine):

I spent an evening in the dressing room of Howard Thurston the last time he appeared on Broadway- Thurston was the acknowledged dean of magicians. For forty years he had traveled all over the world, time and again, creating illusions, mystifying audiences, and making people gasp with astonishment. More than 60 million people had paid admission to his show, and he had made almost $2 million in profit.

I asked Mr. Thurston to tell me the secret of his success. His schooling certainly had nothing to do with it, for he ran away from home as a small boy, became a hobo, rode in boxcars, slept in haystacks, begged his food from door to door, and learned to read by looking out of boxcars at signs along the railway.

Did he have a superior knowledge of magic? No, he told me hundreds of books had been written about legerdemain and scores of people knew as much about it as he did. But he had two things that the others didn’t have. First, he had the ability to put his personality across the footlights. He was a master showman. He knew human nature. Everything he did, every gesture, every intonation of his voice, every lifting of an eyebrow had been carefully rehearsed in advance, and his actions were timed to split seconds. But, in addition to that, Thurston had a genuine interest in people. He told me that many magicians would look at the audience and say to themselves, Well, there is a bunch of suckers out there, a bunch of hicks; I’ll fool them all right. But Thurston’s method was totally different. He told me that every time he went on stage he said to himself: I am grateful because these people come to see me, They make it possible for me to make my living in a very agreeable way. I’m going to give them the very best I possibly can. He declared he never stepped in front of the footlights without first saying to himself over and over: I love my audience. I love my audience. Ridiculous? Absurd? You are privileged to think anything you like. I am merely passing it on to you without comment as a recipe used by one of the most famous magicians of all time.

There you have it, one of the best guys on people management telling you how to write good blog posts and be a good blogger ( I am referring to [Dale Carnegie][8] of course ;) ) [1]: http://en.wikipedia.org/wiki/Dale_Carnegie [2]: http://en.wikipedia.org/wiki/How_to_Win_Friends_and_Influence_People “How to Win Friends and Influence People” [3]: http://haacked.com “Phil Haack” [4]: http://codinghorror.com “Jeff Atwood” [5]: http://hanselman.com “Scott Hanselman” [6]: http://en.wikipedia.org/wiki/How_to_Win_Friends_and_Influence_People “How to Win Friends and Influence People” [7]: http://en.wikipedia.org/wiki/Dale_Carnegie [8]: http://en.wikipedia.org/wiki/Dale_Carnegie

Tip #1 to become a <del>good</del> blogger

Hey all, My last post was about three months ago and that was the time when I! thought that I would start blogging full time. I meant every word of what I said. But, hey, that’s not what happened! I didn’t blog for a full 3 months, that is like a .. decade in the blogosphere.

Anyway, the reasons for this are quite simple. Being a programmer, I thought it would be awesome if I had my own blogging application. And how hard can a blogging app be. Well, it’s not as easy as it sounds. So, my first tip to become a good blogger, Nah a blogger is, don’t try to build your own blogging application to host your blog. Even if you think you are the smartest man on this planet ( I never thought I was ). Try to make posting blogs as simple as it can be. Ridiculously simple. Only then you’ll be able to post blog posts frequently.

That’s what I did, I setup wordpress on one of my linux servers. Made a few tweaks and bam, there was my blog. I am hopeful that I will be able to post more often. But, anyway, that’s Tip #1 to become a blogger.

Till next time!

[@minhajuddin ]

Hello world!

Well, that sounds too cliched, But what the heck I am a programmer!

Now, after listening to @shansxelman’s presentation on social media for developers at neuronspark.com, I have planned to try blogging. This is not a new thing for me, I have already done some blogging (@ http://minhajuddin.blogspot.com) when I was working on a tool called datastage. But that was on some thing which was, let’s say not that fun. I quit blogging right when I dumped Datastage.

After jumping into the exciting world of web applications, there was so much to learn! I kept thinking that I would start blogging once things got a bit steady (read “when I had learnt everything”). But, now it seems that things never get steady and you never stop learning in the “.com world”. All I needed was a little push, which Scott thankfully provided. You aren’t supposed to put in a lot of code in your “Hello, World!” code, so I am gonna end this post right away! On a side note I created this web page blog post using a simple text editor. In the future I’ll be posting blogs using a more advanced framework which I am working on @MBlog. It’s being developed using ASP.NET MVC w00t!