Rendering Step 1 of … (ASP.NET)

The MultiView control, Wizard control or even a custom panel-based control is very useful to collect large sets of data in wizard form; and it’s often useful to give visual ques to the user as to which step he/she is in. Something similar to:

StepMaker-Screenshot

The following ASP.NET code/C# allows us to build a dynamic step control which grows or shrinks automatically given the number of views you have in a MultiView control, or the number of steps in a wizard control.

ASPX

        <asp:Repeater ID="StepMarker" runat="server">
            <headerTemplate>
                <div class="steps">
                    <h2>Step</h2>
                    <ol>
            </headerTemplate>
            <itemTemplate>
                <li<%#ReportingPanel.ActiveViewIndex==Int16.Parse(DataBinder.Eval(Container, "ItemIndex").ToString())?" class=\"active\"":""%>><%#Int16.Parse(DataBinder.Eval(Container, "ItemIndex").ToString())+1%></li>
            </itemTemplate>
            <footerTemplate>
                </ol>
                </div>
                <br style="clear:both" />
            </footerTemplate>
        </asp:Repeater>

Code Behind

/* if we have arrived at the last step we no longer need to display the step markers */
if (ReportingPanel.ActiveViewIndex + 1 == ReportingPanel.Views.Count) {
	StepMarker.Visible = false;
}
else {
	StepMarker.Visible = true;
	int[] i = new int[ReportingPanel.Views.Count - 1];
	StepMarker.DataSource = i;
	StepMarker.DataBind();
}

CSS

.steps ol {
	margin:0px;
	padding:0px;
	font-family:'arial narrow',sans-serif;
}
.steps h2 {
	font-size:19pt;
	font-weight:normal;
	color:#0066cc;
	float:left;
	padding-right:20px;
}
.steps ol li {
	float:left;
	list-style-type:none;
	font-size:19pt;
	color:White;
	background:url(../images/step-shadow.gif);
	background-repeat:no-repeat;
	background-position:left top;
	padding:0px 0px 0px 10px;
	width:43px;
	height:40px;
}
.steps ol li.active {
	font-weight:bold;
	background-image:url(../images/step-glow.gif);
}

Images

Presentation on jQuery

I presented a topic on jQuery at our campus web publishers meeting. Here are the sample pages and the PowerPoint presentation. I will talk more discussions on jQuery and how it has helped us to build a powerful web-application next week.

Automatic Documentation

Generally all programmers are lazy–and specially when it comes to documentation because it takes so much time and doesn’t necessarily produce any material benefit. GhostDoc1, designed by Roland Weigelt, is a plugin for Visual Studio 2005 that automates the generation of XML comments. For example if you have the following C#1 function:

public User GetByUserName(string userName);

GhostDoc will automatically generate:

/// <summary>
/// Gets the name of the by user.
/// </summary>
/// <param name="userName">Name of the user.</param>
/// <returns></returns>
public User GetByUserName(string userName);</code>

That’s pretty amazing. Notice how GhostDoc recognizes Camel and Pascal case variables names. And best of all once the basic structure of the comment is prepared it’s actually not very difficult to type in few words that essentially sums up what the function does if GhostDoc hasn’t already done it.

Finally, since GhostDoc integrates directly with Visual Studio all you have to do is right click the function signature and click on: “Document this” and done! GhostDoc also supports: enums, getters and setters, inheritance, interfaces and so on…

[1] GhostDoc currently only suports C#

Using SSIS to Access Network Resources

SSIS (SQL Server Integration Services) is the replacement for DTS in SQL 2005. One of the more deceitful concepts in SSIS is it’s security context. When you run a SSIS package form your Visual Studio Environment, it obviously runs under a different security context (most possibly as you–the developer) than it would run if it was run as a scheduled service on the SQL server itself. So let’s say you’ve developed a SSIS package that uses resources within your domain, such as accessing a network drive. How will SSIS access such a resource? As you may know, SSIS packages are executed by the SQL server agent, which by default uses the native [NT AUTHORITY\SYSTEM] account1 to execute your packages. Since this is a local account you cannot use it when you need access to resources external to the SQL server box.

In order to access domain level resources, you need to use a domain proxy. A domain proxy allows the SQL agent to proxy on an existing domain account when it executes a package.

The first step is to create a credential. Connect to your SQL server, expand security, right click credentials and new credential. Fill-in the dialog box to something like this:

SQL 2005 - Credentials

The second step is to create a domain proxy, expand SQL Server Agent, right click proxies and click new proxy. Fill in the dialog box something similar to the image shown on the left. Identity is the domain account you are going to use and the password to the domain account.


SQL 2005 - Proxy Accounts

Once this is done, expand SQL Server Agent, right click Proxies and click on New Proxy. The resulting dialog box should look something like the image on the left. For the credential name use the credential you just made.



SQL 2005 - SSIS Run As

Now the last step is to modify the SSIS package to use this proxy account. So right click Jobs under SQL Server Agent, right click the job that you want to run using this proxy account, click properties, go to the steps tab, click on edit at the bottom of the screen. Change Run As to the new proxy account you just created. The resulting dialog box should look something like the image on the left. Make sure the domain account, which you are using during the step when you created the credential, has access to all the network resources this package needs access to.


[1] SQL Agent actually does not use the system account but runs in the context of the SQLAgentUser group on the local machine, the [NT AUTHORITY\SYSTEM] account is by default part of the SQLAgentUser group.

Script Task reading/returning data

When you are using the Script Task in SSIS it’s often useful to have the script task return data, and also at times useful to have access to external data.

Once you drop a Script Task onto the designer and go to it’s editor, under the script tab you’ll find two attributes:
ReadOnlyVariables, ReadWriteVariables. The first allows the script to access external user variables for reading, while the latter allows write access. It’s important to realize that we are talking about user variables which is usually under the User:: namespace. So every variable you list must be prefixed by: User::. If you don’t the script assumes System::.

So here’s a screen shot of what a script task might look like:

Script Task (Variables)

Once you click on the design script you get an editor where you are allowed to type VB.NET code. At this point SSIS script tasks do not support C#. Here’s a sample of how you can access a user variable and set a value to it. As you can see from the sample code below, SSIS variables are not typed:

Public Class ScriptMain
	Public Sub Main()
		Dim Var As Variable = Dts.Variables("User::DataFiles")
		Var.Value = Table
		Dts.TaskResult = Dts.Results.Success
		...
	end Sub
end Class

Variables are read the same way:

Dts.Variables("User::LoadedFiles").Value

If you find yourself using the script task often then you might consider other ways of transforming and manipulating your data, as they can get extremely difficult to debug.

Google Analytics

The new version of Google Analytics is surprisingly good. It produces crisp, exportable, printable reports that friendly to send out to executives but at the same time allows you to drill down enough that it becomes useful for the most technical. Some of the landing pages preset information so beautifully that I simply haven’t seen in any other products (including commercial ones).

If you haven’t signed up already you should! You have no idea what you are missing out.

Reverse a linked list recursively

A question came up the other day while I was helping a friend of mine about recursively reversing a singly linked list. The moment I heard about it I came up with a solution, but turns out the solution requires the function to accept the following signature:

List* reverseList(List *l);

This actually poses a problem because there’s no way to keep track of the head, or maintain any back pointers which could’ve been done if the function accepted a second parameter. Anyway, so I thought about it and initially started with some of the base cases:

List* reverseList(List *l) {
	if(l==NULL) return NULL;
	if(l->next==NULL) return l;
	???

Now comes the tricky part. What do you do in the general case? If you think of two nodes, you realize that you have to change the next->next pointer to the current node, change the next pointer of the current node to the previous node (null if it’s the last node) and you are done! The idea is the same with nodes more than two, the only thing you have to be careful about is when you make the recursive call. One way to grasp the idea is to realize that you have to force the stack to get as deep as possible (get to the next to last node) and set it’s next node to null and then work yourself backwards.

With that thought, I came up with this:

List* reverseList(List *l) {
	if(l==NULL) return NULL;
	if(l->next==NULL) return l;
	reverseList(l->next);

Finally, I needed to reorder the next links as the stack returns back:

List* reverseList(List *l) {
	if(l==NULL) return NULL;
	if(l->next==NULL) return l;
	reverseList(l->next);

	l->next->next = l;
	l->next = null;
	return l;
}

There it was that was the solution. Notice I ignore the return statement in the recursive call. This perhaps isn’t very intuitive but since I am looking ahead one I don’t necessarily need a pointer to the last element, only until n-1.

Google launches: Universal Search

When you search for Steve Jobs, notice the result page contains, regular page results, image results, video results from YouTube, past and current news. Google is coining this new results page as Google Universal. Although this might seem like a natural extension to Google’s search engine, the development of Google Universal took almost two years with a team of hundred engineers.

One of the main reasons for Google’s success is they are able to present complex software behavior very simply so that it can be used by the general public.

Legacy code

I manage a good portion of legacy code, written by so called consultants, and I can’t believe how many places I have seen code like this:

bool flag;
if(x==y) {
	flag=true;
}
else {
	flag=false;
}

Or a variation of this

bool flag=false;

if(x==y) {
	flag=true;
}

Although the latter is better, you can write an equivalent statement as follows:

bool flag = (x==y);

How much easier is that to read? In my opinion a lot! I’ve seen arguments against that however, suggesting that it’s hard to read and not “extensible”. Meaning, if your if clause contains more than one action then my proposed statement wouldn’t work and would need to be rewritten. First of all, how’s that not readable? In fact, I feel it’s more readable than the other statements mainly because in a single line you see that flag is true if x equals y.

If you have more than one action under your if clause then you can’t use this method, but we are not talking about if clauses with more than one action, we are talking about if clauses with a single action; and if during your maintenance you realize you need to add a second action simply convert that statement to an expanded if, else clause and you are done!

Free Audio Editors

Audacity is one of the best free audio editors out there. Even though Audacity can manipulate MP3s, by default Audacity does not support exporting to MP3s. Using the Audacity – MP3 (DLL), however, you can even export your edits to MP3s. This is specially useful when you want to extract an MP3 into a separate file for other uses, such as ring tones. When you hit File | Export as MP3 the first time, Audacity will ask you to find lame_enc.dll simply download/extract the file, copy it to the default installation directory of Audacity (usually c:Program FilesAudacity) and point Audacity to the DLL file. And you are done!

Page 2 of 18«12345»...Last »