I currently work in the interactive department of a advertising agency, who started a whole new green initiative. Which gave me the excuse to make the process of our jsu(job status update) a little less annoying. This system would send out emails with job related information and also client reps would print them out and hand them to you. My decision….I don’t want paper and an alternative to email (since i have limited space they have to be deleted).

This gave way to the jsu widget, we created a easy to use and fast widget. No longer would i have to wait for outlook or login into the company portal and navigate to the information. The adoption rate for this widget was fast because other people would also share the same annoyance.

Technology: Javascript, XML, and SQLServer

JSU widget for A&G

JSU widget for A&G

The following code will give any page the ability to be used as an rss feed automatically

Public class BasePage : System.Web.UI.Page
{
	protected override void Render(HtmlTextWriter writer)
	{
		if (Request.QueryString["rss"] == "true")
		{
			System.Text.StringBuilder sb = new System.Text.StringBuilder();
			System.IO.StringWriter sw = new System.IO.StringWriter(sb);
			HtmlTextWriter nw = new HtmlTextWriter(sw);
			Response.Clear();
			writer.Write("");
			writer.Write("");
			writer.Write(" ");
			writer.Write(" " + this.Request.Url.AbsoluteUri.ToString() + "");
			writer.Write(" ");
			writer.Write(" en-us");
			writer.Write(" " + DateTime.Now.ToUniversalTime().ToString() + "");
			writer.Write(" " + DateTime.Now.ToUniversalTime().ToString() + "");
			writer.Write(" ");
			writer.Write(" Dynamic page generator");
			
			writer.Write(" ");writer.Write(" " + this.Request.Url.AbsoluteUri.ToString() + "");
			writer.Write(" ");
			RenderChildren(nw);
			if (sb.ToString().IndexOf(" ") > 0)
			writer.Write(Util.StripHTML(sb.ToString().Substring(sb.ToString().IndexOf(""))));
			else
			writer.Write(Util.StripHTML(sb.ToString()));
			writer.Write("");
			writer.Write(" " + DateTime.Now.ToUniversalTime().ToString() + "");
			Guid g = new Guid();
			writer.Write(" " + g.ToString() + "");
			writer.Write(" ");writer.Write(" ");
		}
		else
		{
			base.Render(writer);
		}
	}
	
}
	public static class Util
	{
		public static string StripHTML(string htmlString)
		{
			string pattern = @"<(.\n)*?>";
			return Regex.Replace(htmlString.Replace(" ", " "), pattern, string.Empty);
		}
	}

So I tend to use Dotnetnuke alot for my side projects and its just generaly a good portal. But the default solpartmenu was always a creative challange making it look good. And the Asp.net menu provider seems to have a lot of code in it. So i looked around and saw some free menus, but they where always quirky… and when i used reflector on them i could see why. 

Which led to this posting. As you can see my code is always very simple, i hate re inventing the wheel. What this control is doing is populating the menuitemcollection.

using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
namespace QuickMax.UI
{
public class DnnAspNetMenu : System.Web.UI.WebControls.Menu
{
DotNetNuke.Entities.Modules.PortalModuleBase _DnnBase;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
_DnnBase = new DotNetNuke.Entities.Modules.PortalModuleBase();
foreach (DotNetNuke.Entities.Tabs.TabInfo tab in _DnnBase.PortalSettings.DesktopTabs)
{
if (tab.IsVisible &amp;&amp; tab.Level == 0)
{
bool badd = false;
foreach (DotNetNuke.Security.Permissions.TabPermissionInfo tbi in tab.TabPermissions)
if (_DnnBase.UserInfo.IsInRole(tbi.RoleName))
badd = true;
if (badd)
{
MenuItem mnuItem = new MenuItem();
mnuItem.Text = tab.TabName;
mnuItem.NavigateUrl = tab.FullUrl;

mnuItem.Selected = tab.TabID.Equals(_DnnBase.PortalSettings.ActiveTab.TabID);FillChildren(ref mnuItem, tab);
this.Items.Add(mnuItem);
}
}
}
}
private void FillChildren(ref MenuItem mnuitem, DotNetNuke.Entities.Tabs.TabInfo parent)
{
foreach (DotNetNuke.Entities.Tabs.TabInfo tab in _DnnBase.PortalSettings.DesktopTabs)
{
if (parent.TabID == tab.ParentId)
{
bool badd = false;
foreach (DotNetNuke.Security.Permissions.TabPermissionInfo tbi in tab.TabPermissions)
if (_DnnBase.UserInfo.IsInRole(tbi.RoleName))
badd = true;
if (badd)
{
MenuItem mnuItem = new MenuItem();
mnuItem.Text = tab.TabName;
mnuItem.NavigateUrl = tab.FullUrl;

mnuItem.Selected = tab.TabID.Equals(_DnnBase.PortalSettings.ActiveTab.TabID);FillChildren(ref mnuItem, tab);
mnuitem.ChildItems.Add(mnuItem);
}
}
}
}
}
}

I was thinking about a couple things….yea i know “max you think?!?!?’

Did you know that the RaisePostDataChanged event is called after all your Load events are called, and this is right before Your postback event is called. This is so that you cant muck up your data on page_load() before it gets to your lets say Textbox.Click event.

Why is this help full to us, well this means that on page load or pre init we can see if the control has changed since its last postback. How?

Well you can still get to the new data from the Request object using the controls ClientID.

You can to this by Request.ServerVariables[Control.ControlID]

so we can create a method like:

public bool hasChanged(TextBox ctr)
{
return Request[Control.ControlID].Equals(ctr.Text);
}

its just the simple and we can subclass any control and do that.
we could also save the original loading value into viewstate.

I started to search for more information on what i was doing found a good posting from Steven Swafford On Using Application Cache for viewstate.

His post also refers to a asp.net podcast that talks about the same thing. It is good if your application is on one server or Your farm is using sticky session. But it is still a good idea, i emailed him asking permission to take some of the code and create a Viewstate Storage medium for ViewStateEliminator.

I have hit a small snag when it comes to the average life expectancy of and keeping its viewstate around. should I really keep it around anymore than a couple of hours. I understand that the point of viewstate was to have a way to rebuild the control tree with out having to keep the information on the server.

But the increasing size of viewstate to client is becoming alarmingly large on the complex and large web applications.

a solution that a friend of mine sugested is that if we use SQL server as a storage medium only keep viewstate up to 24 hours and then simply delete them. Or through a configuration in the web config

This is a solution for stripping out viewstate before it hits the client. The thought for making this utility was the following, viewstate has no real use fullness on they client besides reconstructing the control tree and as a state bag. Most of the time developers turn viewstate off on controls because it tends to become huge and slows down the streaming of content.

Even when using Ajax API’s such as Microsoft Ajax and Anthem.Net viewstate is still passed back and forth. So even though we get partial page updates we are still passing through that big chunk back and forth, watch we have done is we have disguised the problem but not solve it.

What has been done is eliminated viewstate being sent out to the client and being stored in another medium.

Current Supported mediums:

  1. SQL Database
  2. Session

SQLDatabase is inserting viewstate into a table given certain keys.

Session was chosen as a storage method also after a friend asked me “so what are you doing sticking it in session?”….I answered no. Then it got me to thinking well…what if i do store it in session…what would be so bad? Session…well what would be the impact of the different flavors of session..

  1. InProc Session: I would avoid a round trip to the server and it would be saved in memory…If i also compress it it shouldn’t be so bad.
  2. Session State Server: In this case i piggy back of the session state server and double it as a viewstate server as well.

The Session & Database methods helps the issue of retrieving the right viewstate from a web farm.

So I have put a W.I.P version on codeplex that i will be updating on the weekend….I know right now its not Pure OO … its not something that Jean-Paul S Boodhoo would approve lol

http://www.codeplex.com/ViewStateEliminator

What cause failure in a project from my point of view are a couple of small basic Issues.

  1. Sufficient Information.
  2. Leadership
  3. Talent

I know it seems like I’m over simplifying things, but I’m about the general case why projects tend to fail. Not because the company got sold, or one day you your systems collapse the day before ship or anything short of divine intervention.

1. Sufficient Information:

Providing proper documentation about the project is essential to the success, a lot of people are of the notion that the developer doesn’t need to everything about a project. While they don’t need to know everything it would be nice to know most of it. This means that the Analyst or PM must provide all work flows of how a user’s will be accessing and using the application. so that there are know gotcha’s in the end. I do not place most the blame on the Analyst or PM because the user might not at the time tell them everything. But that is there job… to quote Billy Hollis ” this is where prototyping with a rapid feedback loops is essential.”

2. Leadership:

There needs a to be a person providing the direction technical or non-technical direction, but someone with a vision of some sort. This is so that the project feels more than just that, making the people involved as part of something greater; giving them a sense of ownership in what there doing.

3. Talent:

There needs to be a person that pushes the envelope and set the bar. There something to be said about people who truly love what there doing, if you project is full of people that just want to be there 8 to 5 and just get there task done…well you gonna put out something that reflect 8 to 5 and just works, and feels like any other application.

.

I know i been away but here is part three, this version checks your Asp_net role and the roles for a current node. Veri simple but the menu looks very cool

[Serializable()]
public class CssMenu : Panel
{
private SiteMapDataSource xds;
private string[] userRoles;

private bool HasRoles(SiteMapNode item)
{

bool retval = false;
foreach (string item2 in item.Roles)
{
if (item2.ToString().Equals("*"))
retval = true;
foreach (string item1 in userRoles)
{
if (item1.Equals(item2.ToString()))
retval = true;
}
}
return retval;
}

public SiteMapDataSource DataSource
{
get
{
return xds;
}

set
{
xds = value;
}
}
///
///
///
public string CssId
{
get
{
if (ViewState["CssId"] == null)
ViewState["CssId"] = "";
return (string)ViewState["CssId"];
}
set
{
ViewState["CssId"] = value;
}
}
///
///
///
public bool StartAtRoot
{
get
{
if (ViewState["StartAtRoot"] == null)
return false;
return (bool)ViewState["StartAtRoot"];
}
set
{
ViewState["StartAtRoot"] = value;
}
}
///
///
///
public string CssCurrentClass
{
get
{
if (ViewState["CssCurrentClass"] == null)
ViewState["CssCurrentClass"] = "";

return (string)ViewState["CssCurrentClass"];
}
set
{
ViewState["CssCurrentClass"] = value;
}
}
///
///
///
public int ChildLevels
{
get
{
if (ViewState["ChildLevels"] == null)
ViewState["ChildLevels"] = 1;

return (int)ViewState["ChildLevels"];
}
set
{
ViewState["ChildLevels"] = value;
}
}
///
///
///
private void LoaChildsNodes(SiteMapNodeCollection smnc, ref Panel obj)
{
Literal lit = new Literal();
lit.Text = " ";
      obj.Controls.Add(lit);
      foreach (SiteMapNode item in smnc)
      {
      //if (this.HasRoles(item.Roles))
      // {
      lit = new Literal();
      lit.Text = "* ";
      obj.Controls.Add(lit);
      HyperLink lnk = new HyperLink();
      lnk.Text = item.Title;
      lnk.NavigateUrl = item.Url;
      if (Page.Request.RawUrl.ToLower().Contains(item.Url.ToLower()) && (CssCurrentClass.Length > 0))
      lnk.CssClass = CssCurrentClass;
      else
      lnk.CssClass = "";
      obj.Controls.Add(lnk);
      lit = new Literal();
      lit.Text = "  ";
      obj.Controls.Add(lit);
      // }

      }
      lit = new Literal();
      lit.Text = "";
obj.Controls.Add(lit);
}
protected override void OnDataBinding(EventArgs e)
{
base.Controls.Clear();
base.OnDataBinding(e);
SiteMapNodeCollection smnc;
userRoles = Roles.GetRolesForUser();
xds = this.DataSource;
if (StartAtRoot)
smnc = xds.Provider.GetChildNodes(xds.Provider.RootNode);
else
smnc = xds.Provider.GetChildNodes(xds.Provider.CurrentNode);

Literal lit = new Literal();
lit.Text = "";
      base.Controls.Add(lit);

      foreach (SiteMapNode item in smnc)
      {
      if (HasRoles(item))
      {
      lit = new Literal();
      lit.Text = " * ";
      base.Controls.Add(lit);
      HyperLink lnk = new HyperLink();
      lnk.Text = item.Title;
      lnk.NavigateUrl = item.Url;
      if (Page.Request.RawUrl.ToLower().Contains(item.Url.ToLower()) && (CssCurrentClass.Length > 0))
      {
      lnk.CssClass = CssCurrentClass;
      }
      else
      {
      lnk.CssClass = "";
      }
      base.Controls.Add(lnk);
      SiteMapNodeCollection smc2 = xds.Provider.GetChildNodes(item);
      if ((this.ChildLevels > 1) && (smc2.Count > 0))
      {

      Panel pn = new Panel();
      lit = new Literal();
      lit.Text = "";
      pn.Controls.Add(lit);
      this.LoaChildsNodes(xds.Provider.GetChildNodes(item), ref pn);
      lit = new Literal();
      lit.Text = "";
      pn.Controls.Add(lit);
      base.Controls.Add(pn);
      }
      lit = new Literal();
      lit.Text = "";
      base.Controls.Add(lit);
      }
      }
      lit = new Literal();
      lit.Text = "";
base.Controls.Add(lit);

}

}