<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-16697217</id><updated>2011-11-27T16:58:51.315-07:00</updated><category term='AppDomain'/><category term='SQL CTE Dynamic Join'/><category term='Linq to Entities'/><category term='SQL'/><category term='CTE'/><category term='Date Range'/><category term='Silverlight ContextMenu ContextMenuService'/><category term='Regular Expressions'/><category term='SQL Random'/><category term='cs453'/><category term='AJAX'/><category term='IP'/><category term='Lookup'/><category term='.net'/><category term='SQL HierarchyId Table-Valued Function Sort'/><category term='AutoCompleteExtender'/><category term='ATLAS'/><category term='AJAX Control Toolkit'/><category term='Assembly.LoadFrom'/><title type='text'>...and master of none</title><subtitle type='html'>Jack of all trades, master of none, though ofttimes better than master of one.
-Geffray Mynshul (1618)</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>43</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-16697217.post-1460786400782943558</id><published>2011-10-19T23:39:00.005-06:00</published><updated>2011-10-19T23:39:57.332-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cs453'/><title type='text'>Java and the Intrinsic Lock</title><content type='html'>I was working on converting a Java application to a multi-threaded application today and wanted to use the simplest means possible. This involves the following steps:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Make the class implement Runnable or descend from the Thread class&lt;/li&gt;&lt;li&gt;Put the previously sequential code into threads&lt;/li&gt;&lt;li&gt;Use the "synchronized" keyword on methods that should be critical sections&lt;/li&gt;&lt;li&gt;Join the threads before working on the results&lt;/li&gt;&lt;/ol&gt;Now, there are variations on this theme. Because each object in Java has an intrinsic lock, you can use any old Object as a mutex by calling synchronized(object){} around the critical section you want to protect.&lt;br /&gt;so this:&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;private synchronized foo(){&lt;br /&gt;  // critical section stuff&lt;br /&gt;}&lt;/pre&gt;is the same as this:&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;private foo(){&lt;br /&gt;  synchronized(this){&lt;br /&gt;    // critical section stuff&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;And when trying to synchronize multiple threads, &lt;strong&gt;both are wrong!!&lt;/strong&gt;&lt;br /&gt;&lt;br/&gt;The problem is that each &lt;strong&gt;object&lt;/strong&gt; has an intrinsic lock, not each class. This is easiest to see in the second case. Because each thread is a different object, or the different thread objects contain their own instance of our Runnable class, every single lock is different. The first case has the same problem, not because the method is different in each case, but because the method is logically different.&lt;br /&gt;&lt;br /&gt;So, what should we do?&lt;br/&gt;In each case, we need to make the intrinsic lock static (or global to all instances of the class). In the first case, this can be accomplished by making the method static:&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;static synchronized foo(){&lt;br /&gt;  // critical section stuff&lt;br /&gt;}&lt;/pre&gt;in the second&amp;nbsp; case, we need some other object that is static to use as a lock.&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;static object myLock = new Object();&lt;br /&gt;private foo(){&lt;br /&gt;  synchronize(myLock){&lt;br /&gt;    // critical section stuff&lt;br /&gt;  }&lt;br /&gt;}&lt;/pre&gt;Why would we use the second method? Probably because we want more fine grained protection over the locking than at the procedure level, or because we are referencing properties that should not be made static inside the function.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-1460786400782943558?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/1460786400782943558/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=1460786400782943558' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/1460786400782943558'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/1460786400782943558'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2011/10/java-and-intrinsic-lock.html' title='Java and the Intrinsic Lock'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-625865757417941578</id><published>2011-10-04T15:45:00.002-06:00</published><updated>2011-10-04T16:35:47.822-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cs453'/><title type='text'>Threaded Search</title><content type='html'>I spent a little bit of time threadifying the classic mergesort.This sort works by using recursively dividing the array to be sorted down to some depth, and then eventually merging the sorted members of the array. This sort also has the desirable characteristic that it sorts in-place. There is no additional memory location required. This is a *good thing* when you have hundreds of thousands of elements in your array. In this particular implementation, an insertion sort is used when the recursive division has less than 100 elements. Multi-threading *could* occur at the first n levels of bifurcation, at the bottom level only, or at some intermediary number of levels. Limiting the number of threads and making them a small multiple of the number of CPU cores causes the threading overhead and context switching to be limited as well. The optimal multiplier appears to be quite low, only about 2 threads per CPU core. For these reasons, I choose to thread only at one depth level.Let's look at the code:&lt;pre class="brush: c"&gt;&lt;br /&gt;#include &lt;unistd.h&gt;&lt;br /&gt;#include &lt;stdlib.h&gt;&lt;br /&gt;#include &lt;stdio.h&gt;&lt;br /&gt;#include &lt;values.h&gt;&lt;br /&gt;#include &lt;pthread.h&gt;&lt;br /&gt;#include "mergesort.h"&lt;br /&gt;&lt;br /&gt;#define TRUE 1&lt;br /&gt;#define FALSE 0&lt;br /&gt;&lt;br /&gt;#define THREADED&lt;br /&gt;&lt;br /&gt;// function prototypes&lt;br /&gt;void merge(int A[], int p, int q, int r);&lt;br /&gt;void insertion_sort(int A[], int p, int r);&lt;br /&gt;&lt;br /&gt;const int INSERTION_SORT_CUTOFF = 100; //based on trial and error&lt;br /&gt;const int THREAD_DEPTH = 1; //2^(n+1) threads created at this level&lt;br /&gt;&lt;br /&gt;struct sortstruct {&lt;br /&gt;	int p;&lt;br /&gt;	int r;&lt;br /&gt;	int d;	// depth&lt;br /&gt;	int *A;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt; * insertion_sort(int A[], int p, int r):&lt;br /&gt; *&lt;br /&gt; * description: Sort the section of the array A[p..r].&lt;br /&gt; */&lt;br /&gt;void insertion_sort(int A[], int p, int r)&lt;br /&gt;{&lt;br /&gt;	int j;&lt;br /&gt;&lt;br /&gt;	for (j=p+1; j&lt;=r; j++) {&lt;br /&gt;		int key = A[j];&lt;br /&gt;		int i = j-1;&lt;br /&gt;		while ((i &gt; p-1) &amp;&amp; (A[i] &gt; key)) {	&lt;br /&gt;			A[i+1] = A[i];&lt;br /&gt;			i--;&lt;br /&gt;		}&lt;br /&gt;		A[i+1] = key;&lt;br /&gt;	}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void * mergesort_function(void* arg){&lt;br /&gt;	struct sortstruct * s;&lt;br /&gt;	s = (struct sortstruct *) arg;&lt;br /&gt;	printf("In mergesort thread (%d, %d) \n", s-&gt;p, s-&gt;r);&lt;br /&gt;	mergesort(s-&gt;A, s-&gt;p, s-&gt;r, s-&gt;d);&lt;br /&gt;	return NULL;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt; * mergesort(int A[], int p, int r):&lt;br /&gt; *&lt;br /&gt; * description: Sort the section of the array A[p..r].&lt;br /&gt; * track depth d&lt;br /&gt; */&lt;br /&gt;void mergesort(int A[], int p, int r, int d)&lt;br /&gt;{&lt;br /&gt;	if (r-p+1 &lt;= INSERTION_SORT_CUTOFF)  {&lt;br /&gt;		insertion_sort(A,p,r);&lt;br /&gt;	} else {&lt;br /&gt;		int q = (p+r)/2;&lt;br /&gt;&lt;br /&gt;#ifdef THREADED&lt;br /&gt;		if(d &lt;= THREAD_DEPTH){&lt;br /&gt;			int status;&lt;br /&gt;			pthread_t thread1, thread2;&lt;br /&gt;			struct sortstruct *s1, *s2;&lt;br /&gt;&lt;br /&gt;			s1 =(struct sortstruct *) malloc(sizeof(struct sortstruct));&lt;br /&gt;			s1-&gt;A=A; s1-&gt;p=p; s1-&gt;r=q; s1-&gt;d=d+1;&lt;br /&gt;			status = pthread_create(&amp;thread1, NULL, mergesort_function, (void*) s1);&lt;br /&gt;			if(status) exit(status);&lt;br /&gt;&lt;br /&gt;			s2 = (struct sortstruct*)malloc(sizeof(struct sortstruct));&lt;br /&gt;			s2-&gt;A=A; s2-&gt;p=q+1; s2-&gt;r=r; s2-&gt;d=d+1;&lt;br /&gt;			status = pthread_create(&amp;thread2, NULL, mergesort_function, (void*) s2);&lt;br /&gt;			if(status) exit(status);&lt;br /&gt;&lt;br /&gt;			pthread_join(thread1, NULL);&lt;br /&gt;			pthread_join(thread2, NULL);&lt;br /&gt;&lt;br /&gt;			free(s1);&lt;br /&gt;			free(s2);&lt;br /&gt;		}else{&lt;br /&gt;#endif&lt;br /&gt;			mergesort(A, p, q, d+1);&lt;br /&gt;			mergesort(A, q+1, r, d+1);&lt;br /&gt;#ifdef THREADED&lt;br /&gt;		}&lt;br /&gt;#endif&lt;br /&gt;		merge(A, p, q, r);&lt;br /&gt;	}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt; * merge(int A[], int p, int q, int r):&lt;br /&gt; *&lt;br /&gt; * description: Merge two sorted sequences A[p..q] and A[q+1..r] &lt;br /&gt; *              and place merged output back in array A. Uses extra&lt;br /&gt; *              space proportional to A[p..r].&lt;br /&gt; */     &lt;br /&gt;void merge(int A[], int p, int q, int r) &lt;br /&gt;{&lt;br /&gt;	int *B = (int *) malloc(sizeof(int) * (r-p+1));&lt;br /&gt;&lt;br /&gt;	int i = p;&lt;br /&gt;	int j = q+1;&lt;br /&gt;	int k = 0;&lt;br /&gt;	int l;&lt;br /&gt;&lt;br /&gt;	// as long as both lists have unexamined elements&lt;br /&gt;	// this loop keeps executing.&lt;br /&gt;	while ((i &lt;= q) &amp;&amp; (j &lt;= r)) {&lt;br /&gt;		if (A[i] &lt; A[j]) {&lt;br /&gt;			B[k] = A[i];&lt;br /&gt;			i++;&lt;br /&gt;		} else {&lt;br /&gt;			B[k] = A[j];&lt;br /&gt;			j++;&lt;br /&gt;		}&lt;br /&gt;		k++;&lt;br /&gt;	}&lt;br /&gt;&lt;br /&gt;	// now only at most one list has unprocessed elements.&lt;br /&gt;&lt;br /&gt;	if (i &lt;= q) { &lt;br /&gt;		// copy remaining elements from the first list&lt;br /&gt;		for (l=i; l&lt;=q; l++) {&lt;br /&gt;			B[k] = A[l];&lt;br /&gt;			k++;&lt;br /&gt;		}&lt;br /&gt;	} else {&lt;br /&gt;		// copy remaining elements from the second list&lt;br /&gt;		for (l=j; l&lt;=r; l++) {&lt;br /&gt;			B[k] = A[l];&lt;br /&gt;			k++;&lt;br /&gt;		}&lt;br /&gt;	}&lt;br /&gt;&lt;br /&gt;	// copy merged output from array B back to array A&lt;br /&gt;	k=0;&lt;br /&gt;	for (l=p; l&lt;=r; l++) {&lt;br /&gt;		A[l] = B[k];&lt;br /&gt;		k++;&lt;br /&gt;	}&lt;br /&gt;&lt;br /&gt;	free(B);&lt;br /&gt;}&lt;br /&gt;,&lt;/pre&gt;We changed the signature of the Mergesort function to include a parameter "d", for depth. This requires the initial call to pass the number 0 to prime the recursive function.There is a wrapper function (mergesort_function) that is the threaded function call.  We used this call notation&lt;pre&gt;&lt;br /&gt;nice -n -20 ./mergesort 10000000 2&lt;br /&gt;&lt;/pre&gt;Here are the observed results:&lt;table&gt;&lt;tr&gt;&lt;th&gt;Number of Elements&lt;/th&gt;&lt;th&gt;Unthreaded Time (s)&lt;/th&gt;&lt;th&gt;Threaded Time&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1000000&lt;/td&gt;&lt;td&gt;4.330000&lt;/td&gt;&lt;td&gt;4.040000&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1000000&lt;/td&gt;&lt;td&gt;4.230000&lt;/td&gt;&lt;td&gt;4.150000&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1000000&lt;/td&gt;&lt;td&gt;4.150000&lt;/td&gt;&lt;td&gt;4.040000&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1000000&lt;/td&gt;&lt;td&gt;4.220000&lt;/td&gt;&lt;td&gt;4.060000&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt;average&lt;/th&gt;&lt;td&gt;4.232500&lt;/td&gt;&lt;td&gt;4.072500&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;There appears to be a slight advantage on my 2 CPU virtual machine when using the multi-threaded application. However, it does not approach anything like the multiplier that we would expect for an application that is using two cpus instead of one. This is probably due to the way that vmWare is managing the CPUs. I'd be interested to see how it works in a native machine.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-625865757417941578?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/625865757417941578/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=625865757417941578' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/625865757417941578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/625865757417941578'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2011/10/threaded-search.html' title='Threaded Search'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-6986944353123942524</id><published>2011-09-28T01:05:00.002-06:00</published><updated>2011-09-28T01:18:14.379-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cs453'/><title type='text'>The most efficient algorithm to scan a bitmap</title><content type='html'>&lt;p&gt;Yesterday in class, we were learning about the linux scheduler. How you can have several different algorithms for scheduling, etc. All very nice. The actual scheduler used in linux 2.6 has 140 FIFO queues; one for each possible priority. The scheduler takes the first job from the highest priority queue. The queues have a 140 bit bitmap. Because the bitmap gets scanned every single time there is a new quantum, the algorithm for scanning the bitmap needs to be very fast.&lt;/p&gt;&lt;p&gt;Our professor asked how we would go about scanning the bitmap. As an example, he put up an algorithm that would compare a single bit, then shift the bits left and keep track of the number of shifts. &lt;em&gt;Obviously room for improvement there.&lt;/em&gt; I suggested that the algorithm should be just an integer base 2 log function. To which the professor asked me how I would implement it. I wanted to say: "in hardware", but he was already moving forward. But really, the question of "what is the most significant bit?" is exactly the same question as "what is the integer base 2 log?", one of these two problems has been solved already, &lt;em&gt;in hardware&lt;/em&gt;. And actually, I'd solved a problem similar to this years ago, again using a little bit of assembler.&lt;/p&gt;&lt;p&gt;Then he presented how linux does it: by using a binary search algorithm on the highest integer, then on the second integer, etc, until all 140 bits have been found. To me this looks like a O(log n) algorithm because that's what a binary search does.&lt;/p&gt;&lt;p&gt;However, big O notation assumes that we are dealing with large numbers, and 140 is just not that large. A bit scan function is a 0(n) algorithm. However, if your lower order values are small enough, and the problem small enough, then you can consistently beat an 0(log n) algorithm.&lt;/p&gt;&lt;p&gt;Here is my approach:&lt;/p&gt;&lt;p&gt;I am going to specialize on the processor. I am working with a 64-bit Intel processor. I would expect any kernel code to have libraries that are platform specific. I am just implementing one for my platform. In this case, it is not that big of a deal, because I just have to implement a intLog2 function that takes a 64-bit int and returns one as well. Second, I am going to use an assembly code operation that performs a reverse bit scan to do my log function (thank you Intel). On a 64-bit machine, that means I only have 3 operations to perform on that 140-bit bitmap. I am also going to use the operations registers to perform the function. Finally, I am going to wrap that assembly operation in a #define so that it is executed inline. &lt;/p&gt;&lt;p&gt;Performing the scan on all three elements of the bitmap should simply take the most significant long (I'm calling it b[0], and verify that it has any values at all, if it does, return the scanned value, same for b[1] and b[2]. If none of them have any values, then simply return -1 (for no values in the queue).&lt;/p&gt;&lt;p&gt;Ok, here is the code:&lt;/p&gt;&lt;pre class="brush: c"&gt;&lt;br /&gt;/*&lt;br /&gt; ============================================================================&lt;br /&gt; Name        : ScanBitmap.c&lt;br /&gt; Author      : Aaron Wells&lt;br /&gt; Copyright   : Freely Distributable&lt;br /&gt; Description : C, Ansi-style&lt;br /&gt; ============================================================================&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;#include &lt;stdio.h&gt;&lt;br /&gt;#include &lt;stdlib.h&gt;&lt;br /&gt;&lt;br /&gt;/*&lt;br /&gt; * Integer Base 2 Log Function&lt;br /&gt; * The integer base 2 log is simply the number of the high bit that is set&lt;br /&gt; * This is accomplished by using the Intel bsr instruction (Bit Scan Reverse)&lt;br /&gt; * Command is available on 386 or better CPU&lt;br /&gt; * The values should be loaded and retrieved from registers&lt;br /&gt; */&lt;br /&gt;#define intlog2(x)       \&lt;br /&gt;		({ long __value, __arg = (x);   \&lt;br /&gt;		__asm__ ("bsr %1,%0": "=r" (__value): "r" (__arg));  \&lt;br /&gt;		__value; })&lt;br /&gt;&lt;br /&gt;// 3 longs is 3 * 64 bits = 192 bits (52 extra)&lt;br /&gt;#define BITMAP_SIZE 3&lt;br /&gt;&lt;br /&gt;/* &lt;br /&gt; * This is my "algorithm", not much to it, is there??&lt;br /&gt; */&lt;br /&gt;static long scanHiBit(unsigned long b[BITMAP_SIZE]){&lt;br /&gt;	if(b[0]) return intlog2(b[0]) + 128;&lt;br /&gt;	if(b[1]) return intlog2(b[1]) + 64;&lt;br /&gt;	if(b[2]) return intlog2(b[2]);&lt;br /&gt;	return -1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static void printBitmap(unsigned long b[BITMAP_SIZE]){&lt;br /&gt;	printf("%lx %lx %lx", b[0], b[1], b[2]);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int main(void) {&lt;br /&gt;	unsigned long b1[BITMAP_SIZE] = {-1, -1, -1};&lt;br /&gt;	unsigned long b2[BITMAP_SIZE] = { 0, -1, -1};&lt;br /&gt;	unsigned long b3[BITMAP_SIZE] = { 0,  0, -1};&lt;br /&gt;	unsigned long b4[BITMAP_SIZE] = { 0,  0,  1};	// almost worst case&lt;br /&gt;	unsigned long b5[BITMAP_SIZE] = { 0,  0,  0};	// worst case&lt;br /&gt;&lt;br /&gt;	printBitmap(b1);&lt;br /&gt;	printf(" :%ld\n",scanHiBit(b1));&lt;br /&gt;&lt;br /&gt;	printBitmap(b2);&lt;br /&gt;	printf(" :%ld\n",scanHiBit(b2));&lt;br /&gt;&lt;br /&gt;	printBitmap(b3);&lt;br /&gt;	printf(" :%ld\n",scanHiBit(b3));&lt;br /&gt;&lt;br /&gt;	printBitmap(b4);&lt;br /&gt;	printf(" :%ld\n",scanHiBit(b4));&lt;br /&gt;&lt;br /&gt;	printBitmap(b5);&lt;br /&gt;	printf(" :%ld\n",scanHiBit(b5));&lt;br /&gt;&lt;br /&gt;	return EXIT_SUCCESS;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;There is always room for improvement, and this code is no different. To really do this right, you would pass in the pointer to the start of the bitmap and do the whole thing in assembler. Not very portable, but very fast.&lt;/p&gt;&lt;p&gt;By the way, there would be no reason that you couldn't do a binary search as a fall-back algorithm for CPUs that don't have a reverse scan instruction. &lt;/p&gt;&lt;p&gt;As a follow-up, I may compare my approach (I can't take credit for the algorithm because it is basically a built-in instruction) to the scheduler scanner in linux... another day.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-6986944353123942524?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/6986944353123942524/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=6986944353123942524' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/6986944353123942524'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/6986944353123942524'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2011/09/most-efficient-algorithm-to-scan-bitmap.html' title='The most efficient algorithm to scan a bitmap'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-1124303168620633276</id><published>2011-09-22T20:55:00.002-06:00</published><updated>2011-09-22T21:23:14.436-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cs453'/><title type='text'>file_operations structure changes</title><content type='html'>Working on a device driver for Linux 3.0.4. In class we are modifying some existing code:&lt;br /&gt;&lt;pre class="brush: c"&gt;static struct file_operations simple_fops = {&lt;br /&gt;    .read =       simple_read,&lt;br /&gt;    .write =      simple_write,&lt;br /&gt;    .ioctl =      NULL,&lt;br /&gt;    .open =       simple_open,&lt;br /&gt;    .release =    simple_release,&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;However, this doesn't compile with the latest kernel source. The error is:&lt;br /&gt;&lt;code&gt;error: unknown field ‘ioctl’ specified in initializer&lt;/code&gt;&lt;br /&gt;The new structure, as defined in &lt;code&gt;&amp;lt;source&amp;gt;/include/linux/fs.h&lt;/code&gt; is:&lt;pre class="brush: c"&gt;struct file_operations {&lt;br /&gt;        struct module *owner;&lt;br /&gt;        loff_t (*llseek) (struct file *, loff_t, int);&lt;br /&gt;        ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);&lt;br /&gt;        ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);&lt;br /&gt;        ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);&lt;br /&gt;        ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);&lt;br /&gt;        int (*readdir) (struct file *, void *, filldir_t);&lt;br /&gt;        unsigned int (*poll) (struct file *, struct poll_table_struct *);&lt;br /&gt;        long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);&lt;br /&gt;        long (*compat_ioctl) (struct file *, unsigned int, unsigned long);&lt;br /&gt;        int (*mmap) (struct file *, struct vm_area_struct *);&lt;br /&gt;        int (*open) (struct inode *, struct file *);&lt;br /&gt;        int (*flush) (struct file *, fl_owner_t id);&lt;br /&gt;        int (*release) (struct inode *, struct file *);&lt;br /&gt;        int (*fsync) (struct file *, int datasync);&lt;br /&gt;        int (*aio_fsync) (struct kiocb *, int datasync);&lt;br /&gt;        int (*fasync) (int, struct file *, int);&lt;br /&gt;        int (*lock) (struct file *, int, struct file_lock *);&lt;br /&gt;        ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);&lt;br /&gt;        unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);&lt;br /&gt;        int (*check_flags)(int);&lt;br /&gt;        int (*flock) (struct file *, int, struct file_lock *);&lt;br /&gt;        ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);&lt;br /&gt;        ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);&lt;br /&gt;        int (*setlease)(struct file *, long, struct file_lock **);&lt;br /&gt;        long (*fallocate)(struct file *file, int mode, loff_t offset,&lt;br /&gt;                          loff_t len);&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;It appears that *ioctl has been replaced with *unlocked_ioctl and *compat_ioctl. Why? Well, according to &lt;a href="http://lwn.net/Articles/119652/"&gt;this post&lt;/a&gt;, the old structure was a security risk, and was deprecated. With the new 3.0 kernel, the call must now be completely missing from the headers. The correct thing to do is to use the unlocked_ioctl element instead of ioctl.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-1124303168620633276?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/1124303168620633276/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=1124303168620633276' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/1124303168620633276'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/1124303168620633276'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2011/09/fileoperations-structure-changes.html' title='file_operations structure changes'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-4436059800474368906</id><published>2011-08-09T14:33:00.001-06:00</published><updated>2011-08-09T14:35:10.428-06:00</updated><title type='text'>WCF Ria Services result set size limitation</title><content type='html'>While creating what should be a simple silverlight WCF RIA services application, the client returned the following error for some datasets:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;System.ServiceModel.DomainServices.Client.DomainOperationException: Load operation failed for query 'GetBins'. Value cannot be null.&lt;br /&gt;Parameter name: validationErrors ---&amp;gt; System.ArgumentNullException: Value cannot be null.&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;By using firebug and limiting the size of the return dataset, it became evident that after a certain size, the dataset wasn't returned at all with the http package.&lt;br /&gt;It turns out that this is a WCF RIA services configuration issue. The default value for &lt;em&gt;MaxItemsInObjectGraph&lt;/em&gt; was something way below the total number of records returned.&lt;br /&gt;The solution was to do one of two things: Set MaxItemsInObjectGraph to be some larger number either in the web.config, or in the domain service class definition itself as follows:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;[ServiceBehavior(MaxItemsInObjectGraph = 2147483647)] &lt;br /&gt;public class myDomainService : DomainService { ... }&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Add that little gem to your domain services, and your problems melt away...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-4436059800474368906?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/4436059800474368906/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=4436059800474368906' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/4436059800474368906'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/4436059800474368906'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2011/08/while-creating-what-should-be-simple.html' title='WCF Ria Services result set size limitation'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-3970063861562923904</id><published>2011-05-27T10:34:00.001-06:00</published><updated>2011-05-27T10:36:50.070-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight ContextMenu ContextMenuService'/><title type='text'>Silverlight Context Menu</title><content type='html'>Silverlight 4. I can't believe how many times I've had to search for this one and remembered what it was. So, it gets added to my permanent list of memories.&lt;br /&gt;The only real trick to get the right namespace is to drag a MenuItem onto the page, then delete it and add this code inside whatever you want to have a context menu.&lt;br /&gt;&lt;code&gt;&lt;span style="color: #a31515;"&gt;&lt;span style="color: #a31515;"&gt;&lt;/span&gt;&lt;span style="font-family: Consolas; font-size: x-small;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;toolkit&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;ContextMenuService.ContextMenu&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;/span&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;toolkit&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;ContextMenu&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;/span&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;toolkit&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;MenuItem&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: red; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: red; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: red; font-family: Consolas; font-size: x-small;"&gt; Header&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;="Add child"/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;/span&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;toolkit&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;MenuItem&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: red; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: red; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: red; font-family: Consolas; font-size: x-small;"&gt; Header&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;="Remove" /&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;/span&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&amp;nbsp; &amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;toolkit&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;ContextMenu&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;code&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;toolkit&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #a31515; font-family: Consolas; font-size: x-small;"&gt;ContextMenuService.ContextMenu&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: blue; font-family: Consolas; font-size: x-small;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-3970063861562923904?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/3970063861562923904/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=3970063861562923904' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/3970063861562923904'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/3970063861562923904'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2011/05/silverlight-context-menu.html' title='Silverlight Context Menu'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-5685891163277146004</id><published>2011-05-10T14:20:00.000-06:00</published><updated>2011-05-10T14:20:31.333-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL HierarchyId Table-Valued Function Sort'/><title type='text'>Sorting the results of a MS SQL table-valued function</title><content type='html'>For whatever reason, MS SQL table-valued functions don't get the respect they deserve. Linq to entities pretends that they don't exist at all. I mean, seriously, how hard would it be to allow you to import them in the same way that you can import stored procedures?&lt;br /&gt;Anyway, as a mechanism for abstracting your database schema, I like them. They are pre-compiled, strongly typed, and results cached, so they can get very fast. One thing they don't do well is return sorted values.&lt;br /&gt;The following code won't work well when contained in a table-valued function:&lt;br /&gt;&lt;code&gt;SELECT * FROM Table1 ORDER BY Column1&lt;/code&gt;&lt;br /&gt;This requires us to resort to doing something like this:&lt;br /&gt;&lt;code&gt;SELECT &lt;b&gt;TOP 100 PERCENT&lt;/b&gt; * FROM Table1 ORDER BY Column1&lt;/code&gt;&lt;br /&gt;And even that result can be ignored sometimes. Consider a table that consists of a key, &lt;b&gt;HierarchyId&lt;/b&gt;, and a description. We want to unwind the hierarchyId so that we have key, parent key, and description. This is necessary if we are working with the hierarchy outside of SQL because .net doesn't have any idea how to deal with hierarchyId, Geometry, Geography, and other newer (2008+) datatypes. It would sure be nice if Linq to Entities was updated to at least allow us to pass these items around as binary fields, if not the real .net types they are! But, I digress...&lt;br /&gt;The following function won't return the results in the order we'd like it to:&lt;br /&gt;&lt;code&gt;SELECT TOP 100 PERCENT&lt;br /&gt;t1.key, t2.key parentKey, t1.description &lt;br /&gt;from Table1 t1 join t2 on t1.Hier.GetAncestor(1) = h2.Hier &lt;br /&gt;join Table1 t3 on h1.Hier.IsDescendantOf(t3.Hier) = 1 &lt;br /&gt;and h3.key = @topKey&lt;br /&gt;ORDER BY t1.Hier&lt;/code&gt;&lt;br /&gt;One of the nice things about the HierarchyId data type is that when you sort by it, the parents and their children stay sorted in the right order; but not in this case.&lt;br /&gt;The solution is to use an alternate method of sorting the results:&lt;br /&gt;&lt;code&gt;SELECT&lt;br /&gt;ROW_NUMBER() OVER (ORDER BY h1.Hier) RowNumber,&lt;br /&gt;t1.key, t2.key parentKey, t1.description &lt;br /&gt;from Table1 t1 join t2 on t1.Hier.GetAncestor(1) = h2.Hier &lt;br /&gt;join Table1 t3 on h1.Hier.IsDescendantOf(t3.Hier) = 1 &lt;br /&gt;and h3.key = @topKey&lt;/code&gt;&lt;br /&gt;This sort is accepted by the function syntax, and will give us exactly the order we expect. And as a bonus, we can restore that order if we choose to sort the results by some other column. Otherwise, just ignore the RowNumber column that is returned.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-5685891163277146004?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/5685891163277146004/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=5685891163277146004' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/5685891163277146004'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/5685891163277146004'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2011/05/sorting-results-of-ms-sql-table-valued.html' title='Sorting the results of a MS SQL table-valued function'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-6100653995441604156</id><published>2010-09-23T12:26:00.004-06:00</published><updated>2011-09-22T21:20:34.889-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Date Range'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL'/><category scheme='http://www.blogger.com/atom/ns#' term='CTE'/><title type='text'>An infinite date table</title><content type='html'>&lt;p&gt;Here is the creation script for a neat function that will generate a table full of every date in the given range.&lt;/p&gt;&lt;br /&gt;&lt;pre class="brush: sql"&gt;&lt;br /&gt;-- =============================================&lt;br /&gt;-- Author:  Aaron D. Wells&lt;br /&gt;-- Create date: 9/23/2010&lt;br /&gt;-- Description: Get a list of dates in a range&lt;br /&gt;-- =============================================&lt;br /&gt;CREATE FUNCTION fn_Dates (@fromDate date, @toDate date)&lt;br /&gt;RETURNS @dateTable TABLE( [Date] Date NOT NULL, FiscalYear int NOT NULL, FiscalMonth int NOT NULL )&lt;br /&gt;AS &lt;br /&gt;BEGIN&lt;br /&gt;     WITH CTE_DatesTable([date])&lt;br /&gt;     AS (&lt;br /&gt;     SELECT @fromDate AS [date]&lt;br /&gt;          UNION ALL&lt;br /&gt;          SELECT DATEADD(dd, 1, [date]) FROM CTE_DatesTable&lt;br /&gt;          WHERE DATEADD(dd, 1, [date]) &lt;= @toDate)  &lt;br /&gt;          INSERT @dateTable&lt;br /&gt;               SELECT [date],&lt;br /&gt;                    CASE WHEN MONTH(date) &gt; 9 THEN YEAR(date) + 1 ELSE YEAR(date) END FiscalYear,&lt;br /&gt;                    CASE WHEN MONTH(date) &gt; 9 THEN MONTH(date) - 9 ELSE MONTH(date) + 3 END FiscalMonth&lt;br /&gt;               FROM CTE_DatesTable OPTION (MAXRECURSION 0)&lt;br /&gt;     RETURN &lt;br /&gt;END&lt;/pre&gt;Using the function is pretty simple, just give it a starting and ending date. By the way, the FiscalYear column is used to calculate the fiscal year for the company I was working with when i wrote this. Your mileage may vary.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-6100653995441604156?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/6100653995441604156/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=6100653995441604156' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/6100653995441604156'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/6100653995441604156'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2010/09/infinite-date-table.html' title='An infinite date table'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-3481170253167402159</id><published>2010-07-15T15:05:00.000-06:00</published><updated>2010-07-15T15:05:48.083-06:00</updated><title type='text'>Generic Dynamic Class Factory (.net)</title><content type='html'>This code provides a simple way to dynamically load all the assemblies in a directory (by default the bin directory in your project)&lt;br /&gt;&lt;pre class="brush: csharp"&gt;using System.Text;&lt;br /&gt;using System.Reflection;&lt;br /&gt;using System.IO;&lt;br /&gt;public class DynamicFactory&lt;T&gt; {&lt;br /&gt;   List&lt;Assembly&gt; allAssemblies = new List&lt;Assembly&gt;();&lt;br /&gt;   public DynamicFactory() { }&lt;br /&gt;   public void LoadAssemblies() {&lt;br /&gt;       Assembly thisAssembly = Assembly.GetExecutingAssembly();&lt;br /&gt;       Uri thisUri = new Uri(thisAssembly.CodeBase);&lt;br /&gt;       string path = Path.GetDirectoryName(thisUri.LocalPath);&lt;br /&gt;       LoadAssemblies(path);&lt;br /&gt;   }&lt;br /&gt;   public void LoadAssemblies(string path) {&lt;br /&gt;       allAssemblies.Clear();&lt;br /&gt;       foreach (string dll in Directory.GetFiles(path, "*.dll")) {&lt;br /&gt;           allAssemblies.Add(Assembly.LoadFile(dll));&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;   public IEnumerable&lt;Type&gt; EnumerateTypes() {&lt;br /&gt;       foreach (var assembly in allAssemblies) &lt;br /&gt;           foreach (Type type in assembly.GetExportedTypes())&lt;br /&gt;               if (typeof(T).IsAssignableFrom(type))&lt;br /&gt;                   yield return type;                               &lt;br /&gt;   }&lt;br /&gt;   public IEnumerable&lt;T&gt; EnumerateObjects() {&lt;br /&gt;       foreach (var assembly in allAssemblies)&lt;br /&gt;           foreach (Type type in assembly.GetExportedTypes())&lt;br /&gt;               if (typeof(T).IsAssignableFrom(type))&lt;br /&gt;                   yield return (T)Activator.CreateInstance(type);&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-3481170253167402159?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/3481170253167402159/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=3481170253167402159' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/3481170253167402159'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/3481170253167402159'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2010/07/generic-dynamic-class-factory-net.html' title='Generic Dynamic Class Factory (.net)'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-408091105751715022</id><published>2010-06-25T15:39:00.001-06:00</published><updated>2010-06-25T15:50:19.034-06:00</updated><title type='text'>Software Developers Do Not Build Widgets...</title><content type='html'>&lt;p&gt;This post will be quite different from my normal posts. It is not a quick how-to, or a design pattern, but a rebuttal...&lt;/p&gt;&lt;p&gt;I was recently reading the introduction to a book on enterprise architecture. And the author tried to make the point that software development is a cottage industry because the "widgets" we create (software) does not have the associated factories, structures, and automation that making cars or cookies has. He points out that the auto industry spends 80% of its time designing the factory and only 20% designing the cars. At the end of building a particular type of automobile, the factory line is thrown away (or massively retooled) for the next model of car.&lt;/p&gt;&lt;p&gt;That author, and almost every other like-minded author or speaker I've ever heard of is building a case for their "software creation" automation tools, process, or methodology (shudder). And their analogy is completely wrong.&lt;/p&gt;&lt;p&gt;The truth is, we don't build cars or cookies. Every custom developed piece of software is different, every car or cookie is the same. We are not the mindless robots in the production line.&lt;/p&gt;&lt;p&gt;We are the engineers designing both the car and the production line.&lt;/p&gt;&lt;p&gt;In the world of software development, the factory is the application or system. The car (product) is the data that is being processed. Whether for internal or external consumption.&lt;/p&gt;&lt;p&gt;The purpose of of the factory is to take in supplies (raw materials, parts, widgets) and to produce product (more parts, or processed materials, and widgets), our software takes inputs (user inputs, inputs from other systems) and produces product (more data, or outputs to other systems).&lt;/p&gt;&lt;p&gt;The efficiency of the factory is completely dependent upon the architect, the effectivity of the system is dependent upon the software architect and developers.&lt;/p&gt;&lt;p&gt;Our tools resemble those of the design engineer or the automation process engineer. We model flows and structures. We specify tolerances and dimensions and interfaces. We are concerned about parallel and serial processes. We are the engineers that we have euphamistically claimed to be.&lt;/p&gt;&lt;p&gt;So, no, dear author, we don't design and build widgets, we design and build factories. Our factories interact with and are operated by users. Do we need process? Yes. Do we need procedures? Yes. Do we need tools? Yes. &lt;/p&gt;&lt;p&gt;Compare the number of moving parts in enterprise software to the moving parts in the factory that builds cars if you must, but do not compare websites and say that they are as similar as two cars rolling off of an assembly plant&lt;/p&gt;&lt;p&gt;If anything at all, compare building entertainment software development and production to the production of movies, and the development of e-commerce software to the development of a new commercial franchise. &lt;/p&gt;&lt;p&gt;Is it any wonder that in an information age, we would need to build information factories?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-408091105751715022?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/408091105751715022/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=408091105751715022' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/408091105751715022'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/408091105751715022'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2010/06/software-developers-do-not-build.html' title='Software Developers Do Not Build Widgets...'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-4055054294553472374</id><published>2010-02-15T13:23:00.001-07:00</published><updated>2010-02-15T13:25:04.383-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Random'/><title type='text'>SQL random number column</title><content type='html'>&lt;p&gt;Here's a quickie. If you need to have a new random number on a column, this works really well.&lt;/p&gt;&lt;pre class="brush: sql"&gt;rand(cast(cast(NEWID() as varbinary) as int)) number&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Of course NEWID generates a random guid. Casting it as a varbinary first, then as an int gives you a random number which can then be used as a seed for the random number generator.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-4055054294553472374?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/4055054294553472374/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=4055054294553472374' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/4055054294553472374'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/4055054294553472374'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2010/02/sql-random-number-column.html' title='SQL random number column'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-522948926079404781</id><published>2010-02-15T09:50:00.006-07:00</published><updated>2010-02-15T10:00:03.464-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL CTE Dynamic Join'/><title type='text'>Dynamically Generated List of Dates Using Common Table Expressions (CTE)</title><content type='html'>&lt;p&gt;Here is a nice use for Common Table Expressions (CTEs) to generate a dates table or other list of stuff. I won't take credit for this technique since I saw it someplace else (but can't remember where). Of course my blog is for stuff I want to remember, so thanks to whoever you are...&lt;/p&gt;&lt;pre class="brush: sql"&gt;declare @loops int = 1000&lt;br /&gt;declare @StartDate date = '1/1/2000';&lt;br /&gt;&lt;br /&gt;WITH CountTable( RowNumber, [Month], [Year], FirstDay ) AS&lt;br /&gt;(&lt;br /&gt; SELECT&lt;br /&gt;  1 RowNumber,&lt;br /&gt;  MONTH(@StartDate) [Month],&lt;br /&gt;  YEAR(@StartDate) [Year],&lt;br /&gt;  -- compute the first day of the month from whatever day was provided&lt;br /&gt;  DATEADD(dd,-(DAY(@StartDate)-1),@StartDate) FirstDay   &lt;br /&gt; UNION ALL&lt;br /&gt; &lt;br /&gt; SELECT&lt;br /&gt;  RowNumber + 1 RowNumber,&lt;br /&gt;  MONTH(DATEADD(MONTH, 1, FirstDay)),&lt;br /&gt;  YEAR(DATEADD(MONTH, 1, FirstDay)),&lt;br /&gt;  DATEADD(MONTH, 1, FirstDay) FirstDay&lt;br /&gt;  &lt;br /&gt; FROM CountTable t&lt;br /&gt; WHERE RowNumber &lt; @loops&lt;br /&gt;)&lt;br /&gt;&lt;br /&gt;SELECT * &lt;br /&gt;FROM CountTable&lt;br /&gt;OPTION (maxrecursion 32767)&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The results look like this:&lt;/p&gt;&lt;pre&gt;&amp;nbsp;1  1 2000 2000-01-01&lt;br /&gt; 2  2 2000 2000-02-01&lt;br /&gt; 3  3 2000 2000-03-01&lt;br /&gt; 4  4 2000 2000-04-01&lt;br /&gt; 5  5 2000 2000-05-01&lt;br /&gt; 6  6 2000 2000-06-01&lt;br /&gt; 7  7 2000 2000-07-01&lt;br /&gt; 8  8 2000 2000-08-01&lt;br /&gt; 9  9 2000 2000-09-01&lt;br /&gt;10 10 2000 2000-10-01&lt;br /&gt;11 11 2000 2000-11-01&lt;br /&gt;12 12 2000 2000-12-01&lt;br /&gt;13  1 2001 2001-01-01&lt;br /&gt;14  2 2001 2001-02-01&lt;/pre&gt;&lt;small&gt;more rows here...&lt;/small&gt;&lt;pre&gt;&amp;nbsp;999 3 2083 2083-03-01&lt;br /&gt;1000 4 2083 2083-04-01&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;In this query, there are two parts to the CTE, the seed (top part) and the function (bottom part). The seed sets the initial values, and the function uses the seed values to create the next row of values, which are then used to create the following row of values (and so on, and so on...)&lt;/p&gt;&lt;p&gt;There are a couple of things to notice:&lt;ul&gt;&lt;li&gt;The function values must be based on the previous value (notice my recalculation of the next month)&lt;/li&gt;&lt;li&gt;You must use a semicolon before the CTE&lt;/li&gt;&lt;li&gt;the maxrecursion option defaults at 100 iterations and has a maximum value of 32767&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-522948926079404781?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/522948926079404781/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=522948926079404781' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/522948926079404781'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/522948926079404781'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2010/02/dynamically-generated-list-of-dates.html' title='Dynamically Generated List of Dates Using Common Table Expressions (CTE)'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-3742479206981368753</id><published>2010-02-06T15:59:00.000-07:00</published><updated>2010-02-06T15:59:47.624-07:00</updated><title type='text'>Recursively change unix permissions on a directory</title><content type='html'>On my freenas server I sometimes need to change the permissions of files that were uploaded via FTP. Here is the command that can be issued to make those changes:&lt;br /&gt;&lt;br /&gt;chmod -R 0777 "/mnt/Seagate650/FTP Root"&lt;br /&gt;&lt;br /&gt;The quotes are important because my ftp root directory contains a space.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-3742479206981368753?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/3742479206981368753/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=3742479206981368753' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/3742479206981368753'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/3742479206981368753'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2010/02/recursively-change-unix-permissions-on.html' title='Recursively change unix permissions on a directory'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-3981340384687346735</id><published>2010-01-25T15:37:00.009-07:00</published><updated>2010-01-25T15:50:19.807-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Assembly.LoadFrom'/><category scheme='http://www.blogger.com/atom/ns#' term='.net'/><category scheme='http://www.blogger.com/atom/ns#' term='AppDomain'/><title type='text'>Load a dll into an AppDomain for reflection or execution and Unload it</title><content type='html'>&lt;p&gt;.Net will allow you to easily load any dll you want to into the current AppDomain by simply calling Assembly.LoadFrom() with the path of the dll in question. However, this is only available for the current AppDomain, and as a result, the dll remains loaded for the duration of the AppDomain's lifetime.&lt;/p&gt;&lt;p&gt;This may be ok, but if you want to simply load a dll, inspect it, and run some one-time operations on it, that seems a bit wasteful. In web development, it means you must shut down your web server to recompile the dll you're loading.&lt;/p&gt;&lt;p&gt;So, the solution would seem to be to start up a new appDomain, load the dll in question, do your work, and then unload the appDomain.&lt;br /&gt;&lt;p&gt;Gentlemen, start your compilers...&lt;/p&gt;&lt;pre class="brush: csharp"&gt;namespace Utilities {&lt;br /&gt;  public class SomeClass{&lt;br /&gt;    public static void RegisterApplication(&lt;br /&gt;      string appPath) {&lt;br /&gt;      if (File.Exists(appPath)) {&lt;br /&gt;        var domainSetup = new AppDomainSetup() {&lt;br /&gt;        ApplicationBase = AppDomain.CurrentDomain&lt;br /&gt;          .BaseDirectory,&lt;br /&gt;        PrivateBinPath = AppDomain.CurrentDomain&lt;br /&gt;          .BaseDirectory + @"\bin"&lt;br /&gt;      };&lt;br /&gt;      var appDomain = AppDomain.CreateDomain(&lt;br /&gt;        "LoaderDomain", null, domainSetup);&lt;br /&gt;      try {&lt;br /&gt;        var loader = (Loader)appDomain&lt;br /&gt;          .CreateInstanceAndUnwrap(&lt;br /&gt;            Assembly.GetExecutingAssembly()&lt;br /&gt;              .FullName,&lt;br /&gt;            typeof(Loader).FullName);&lt;br /&gt;        loader.DoSomething(appPath);&lt;br /&gt;      }&lt;br /&gt;      finally { AppDomain.Unload(appDomain); }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public class Loader: MarshalByRefObject {&lt;br /&gt;    public void DoSomething(string appPath) {&lt;br /&gt;      var assembly = Assembly.LoadFrom(appPath);&lt;br /&gt;      foreach (var type in assembly.GetTypes()){&lt;br /&gt;      // Do something with the types we find&lt;br /&gt;      // like create some classes with known &lt;br /&gt;      // interfaces or examine attributes&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;What's going on?&lt;/p&gt;&lt;p&gt;Well, we create an app domain and seed the PrivateBinPath with a \bin subdirectory so that we can load our current dll in an IIS or cassini environment. Then we fire off the known object and have it call into Assembly.LoadFrom(). Assembly.LoadFrom will resolve dependencies using the standard resolution stuff for our other assemblies. Alternately, we could use a custom resolver event handler to get to our dlls.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-3981340384687346735?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/3981340384687346735/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=3981340384687346735' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/3981340384687346735'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/3981340384687346735'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2010/01/load-dll-into-appdomain-for-reflection.html' title='Load a dll into an AppDomain for reflection or execution and Unload it'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-1549667217128055156</id><published>2010-01-18T08:53:00.005-07:00</published><updated>2010-01-18T09:14:49.350-07:00</updated><title type='text'>CSRF (Cross-Site Request Forgery) Handling in MVC</title><content type='html'>Phil Haack's talk on asp.net reminded me of the importance of handling CSRF attacks. In MVC, this is simply handled with a one-two punch. In your posting form, you need to include the Html.AntiForgeryToken() in the form as follows:&lt;br /&gt;&lt;pre class="brush: html"&gt;&lt;content contentplaceholderid="MainContent" id="Content2" runat="server"&gt;&lt;br /&gt;  &lt;input type="submit" value="delete" /&gt;&lt;br /&gt;&lt;/content&gt;&lt;br /&gt;&lt;/pre&gt;The other thing is to add an [ValidateAntiForgeryToken] attribute to the targeted posting action in your controller as follows:&lt;br /&gt;&lt;pre class="brush: csharp"&gt;[ValidateAntiForgeryToken]&lt;br /&gt;[HttpPost] &lt;br /&gt;// or MVC 1.0 style [AcceptVerbs(HttpVerbs.Post)]&lt;br /&gt;public virtual ActionResult Delete(FormCollection form, int id) {&lt;br /&gt;  // code here to delete stuff&lt;br /&gt;  return View();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;Also don't forget that we want to make sure that any state-changing operations are always posts!&lt;br /&gt;My new syntax highlighting is accomplished via a method outlined &lt;a href="http://blog.cartercole.com/2009/10/awesome-syntax-highlighting-made-easy.html"&gt;on Carter Cole's most excellent blog.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-1549667217128055156?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/1549667217128055156/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=1549667217128055156' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/1549667217128055156'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/1549667217128055156'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2010/01/csrf-cross-site-request-forgery.html' title='CSRF (Cross-Site Request Forgery) Handling in MVC'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-1781080355333848835</id><published>2009-12-31T11:56:00.024-07:00</published><updated>2009-12-31T13:20:25.035-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linq to Entities'/><title type='text'>Linq to Entities and Custom Database Functions</title><content type='html'>&lt;p&gt;I've been using Linq to SQL since it came out. Linq to Entities didn't have any compelling functionality, and it was far less supported in the development community. Nobody seemed to be using it. For whatever reason, when the language group at Microsoft came out with Linq, the data group was slow on the uptake and that left the language group with the need for an actual database query layer, so Linq to SQL was born. There were rumors that Linq to SQL would not continue to evolve, but it certainly worked fine for what I needed.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The 2009 Microsoft PDC had all kinds of interesting things, but absolutely nothing regarding Linq to SQL. The language group became enammored with .NET 4 and the dynamic language features and have apparently orphaned Linq to SQL. Not so the data group. The improvements to Linq to Entities seem to breathe new life into what had previously been a "me too" implementation of Linq.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Certainly the biggest news about Linq to Entities relates to the new flexibility to use POCO objects, database first, or model first for defining your objects. I especially like the ability to use t4 templates for model generation. This development certainly takes away of the allure of NHibernate as an ORM. In fact, I think you can probably start calling Linq to Entities a nearly full-featured ORM in it's new incarnation. One potentially serious oversight is the lack of ability to perform dependancy injection on object creation, but let's hope that is rectified as soon as possible.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;However, the one piece that really gets me interested is the ability to call custom database functions from within your Linq statements. This is potentially huge. It is really too bad that Shyam and Chris weren't able to get the demo of this little gem to work in &lt;a href="http://microsoftpdc.com/Sessions/FT10"&gt;their presentation&lt;/a&gt;. There is also not a lot of &lt;a href="http://msdn.microsoft.com/en-us/library/dd456847(VS.100).aspx"&gt;documentation &lt;/a&gt;available for this feature. In fact, I only found &lt;a href="http://blogs.msdn.com/alexj/archive/2009/08/07/tip-30-how-to-use-a-custom-store-function.aspx"&gt;one useful article&lt;/a&gt; in the blogosphere.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The key thing that is unclear from the documentation and article is the thing that Shyam and Chris had problems with as well. So, here is how you fix the issue:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The namespace attribute in the schema entity in the Linq to Entities edmx file must match the namespace entry of the EdmFunction code attribute in your static method. This namespace is the value in the Model Browser namespace as shown here.&lt;/p&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_SAsEHVMNseo/Sz0F-bFcliI/AAAAAAAABrY/sYsqz497AOM/s1600-h/Capture1.PNG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 285px; height: 237px;" src="http://1.bp.blogspot.com/_SAsEHVMNseo/Sz0F-bFcliI/AAAAAAAABrY/sYsqz497AOM/s400/Capture1.PNG" border="0" alt=""id="BLOGGER_PHOTO_ID_5421496096404575778" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;pre style="BORDER-BOTTOM: #999999 1px dashed; BORDER-LEFT: #999999 1px dashed; PADDING-BOTTOM: 5px; LINE-HEIGHT: 14px; BACKGROUND-COLOR: #eee; PADDING-LEFT: 5px; WIDTH: 100%; PADDING-RIGHT: 5px; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; COLOR: #000000; FONT-SIZE: 12px; OVERFLOW: auto; BORDER-TOP: #999999 1px dashed; BORDER-RIGHT: #999999 1px dashed; PADDING-TOP: 5px"&gt;&lt;code&gt;&amp;lt;Schema Namespace="&lt;strong&gt;&lt;em&gt;Data.Store&lt;/em&gt;&lt;/strong&gt;" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl"&amp;gt;&lt;br /&gt;  &amp;lt;Function Name="IsAuthorized" ReturnType="bit" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo"&amp;gt;&lt;br /&gt;    &amp;lt;Parameter Name="Id" Type="int" Mode="In" /&amp;gt;&lt;br /&gt;  &amp;lt;/Function&amp;gt;&lt;br /&gt;&amp;lt;/Schema&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre style="BORDER-BOTTOM: #999999 1px dashed; BORDER-LEFT: #999999 1px dashed; PADDING-BOTTOM: 5px; LINE-HEIGHT: 14px; BACKGROUND-COLOR: #eee; PADDING-LEFT: 5px; WIDTH: 100%; PADDING-RIGHT: 5px; FONT-FAMILY: Andale Mono, Lucida Console, Monaco, fixed, monospace; COLOR: #000000; FONT-SIZE: 12px; OVERFLOW: auto; BORDER-TOP: #999999 1px dashed; BORDER-RIGHT: #999999 1px dashed; PADDING-TOP: 5px"&gt;&lt;code&gt;public static class LinqExtensions {&lt;br /&gt;  [EdmFunction("&lt;em&gt;Data.Store&lt;/em&gt;", "IsAuthorized")]&lt;br /&gt;  public static bool IsAuthorized(int? id) {&lt;br /&gt;    throw new Exception("Direct calls not supported");&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;This allows you to write the following Linq statement:&lt;/p&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;var result = from s in dc.SomeTable&lt;br /&gt;  where LinqExtensions.IsAuthorized(s.Id)&lt;br /&gt;  select s;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Another important thing is that &lt;em&gt;you don't have to manually edit the .edmx file.&lt;/em&gt; You can use the Model Browser or the design surface to select "update model from database" from the context menu. From there you can add an existing function to the model, and not have to deal with the XML in the .edmx file&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-1781080355333848835?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/1781080355333848835/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=1781080355333848835' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/1781080355333848835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/1781080355333848835'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2009/12/linq-to-entities-and-custom-database.html' title='Linq to Entities and Custom Database Functions'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_SAsEHVMNseo/Sz0F-bFcliI/AAAAAAAABrY/sYsqz497AOM/s72-c/Capture1.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-5707421227363595636</id><published>2009-04-29T20:31:00.026-06:00</published><updated>2010-07-15T15:11:16.531-06:00</updated><title type='text'>jQuery and MVC Autosuggest while saving the selected Id</title><content type='html'>Yea, I know, boring title. But I really want to make sure I can find the code for how to do this one.&lt;br /&gt;&lt;br /&gt;jQuery is very cool. All the eye candy is nice, the syntax is excellent, but the real benefit is AJAX...&lt;br /&gt;&lt;br /&gt;The autocomplete jQuery library is extremely nice. It allows you to take a Json result from some url and suggest results to a text box. What I want is for the selected value to populate another input field (hidden) so that I have a real foreign key relationship to the item they selected.&lt;br /&gt;&lt;br /&gt;here's the html:&lt;br /&gt;&lt;pre class="brush: html"&gt;&amp;lt;input class="location" id="LocationName"&amp;gt;&lt;br /&gt;&amp;lt;input id="LocationId" type="hidden" keyFor="LocationName"/&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Or alternately you can use Html Helpers&lt;/p&gt;&lt;pre class="brush: html"&gt;&amp;lt;%= Html.TextBox("LocationName", null, new {class = "location"}) %&amp;gt;&lt;br /&gt;&amp;lt;%= Html.Hidden("LocationId", null, new {keyFor = "LocationName"})%&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;and here is the supporting javascript:&lt;/p&gt;&lt;pre class="brush: jscript"&gt;$(document).ready(function() {&lt;br /&gt;$('.location).autocomplete("/location/JsonFind",&lt;br /&gt;{ dataType: 'json',&lt;br /&gt;parse: parseData,&lt;br /&gt;formatItem: formatItem,&lt;br /&gt;formatResult: formatItem&lt;br /&gt;}).result(autocompleteResult);&lt;br /&gt;});&lt;br /&gt;&lt;br /&gt;function parseData(data) {&lt;br /&gt;var rows = new Array();&lt;br /&gt;for (var i = 0; i &lt; data.length; i++) {&lt;br /&gt;rows[i] = { data: data[i], result: data[i].Description, value: data[i].Id };&lt;br /&gt;}&lt;br /&gt;return rows;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function formatItem(row, i, n) { return row.Description; }&lt;br /&gt;&lt;br /&gt;function autocompleteResult(event, data, formatted) {&lt;br /&gt;var TargetId = "[keyFor=" + event.currentTarget.id + "]";&lt;br /&gt;$(TargetId).val(data.Id);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;and finally, the code in the Location controller&lt;/p&gt;&lt;pre class="brush: jscript"&gt;public ActionResult Find(string q, int limit) {&lt;br /&gt;return Json(Repository.GetAll&lt;location&gt;().Where(l =&gt; l.LocationName.StartsWith(q)).Take(limit));&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;What's going on here?&lt;/p&gt;&lt;p&gt;Well, we simply have an input control and a hidden intput control on our html page. The important convention I have is that the hidden input control has a non-standard "locationidfor" tag so that we can identify where to put the selected value.&lt;/p&gt;&lt;p&gt;The "location" controller is providing a method that returns complete Location records from our Linq to SQL table through a repository. The exercise of setting up Linq to SQL is left to the reader. The linq code at the end simply grab all the Locations where the location names start with the text the user typed in, and we only take "limit" elements from the list. Your method will probably be different.&lt;/p&gt;&lt;p&gt;jQuery is the glue that binds the whole thing together. Our applyLocationAutosuggest function may be applied in the page ready just as easily, but here I've encapsulated the functionality so it can be applied to jQuery templates as well!&lt;/p&gt;&lt;p&gt;In its simplest form Autocomplete just needs a list of strings (simple matching), but here we use the formatItem and formatResult parameters to make sure that the user doesn't see the entire Location row, just the text we want. Mix in a check to make sure that there was at least one result. There are also two undocumented parameters we need to use, the dataType parameter is set to 'json' because autocomplete expects plain text by default; parse gives us the opportunity to take our json data and change it into the autocomplete internal array format. &lt;/p&gt;&lt;p&gt;Finally, when the result function allows us to take the selected Json result, decode it into an object, and put the id in the hidden field.&lt;/p&gt;&lt;p&gt;Mission Accomplished.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-5707421227363595636?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/5707421227363595636/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=5707421227363595636' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/5707421227363595636'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/5707421227363595636'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2009/04/jquery-and-mvc-autosuggest.html' title='jQuery and MVC Autosuggest while saving the selected Id'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-4791904276679623205</id><published>2009-01-21T13:28:00.005-07:00</published><updated>2009-01-21T13:34:21.600-07:00</updated><title type='text'>It's all about presentation...</title><content type='html'>My last post, you may notice has code snippets that look somewhat professional. I found a cool online tool called &lt;a href="http://www.palfrader.org/code2html/code2html.html"&gt;Code2html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;It turns this:&lt;/h3&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Linq;&lt;br /&gt;using System.Web;&lt;br /&gt;using System.Web.UI;&lt;br /&gt;using System.Web.UI.WebControls;&lt;br /&gt;using System.Net.Mail;&lt;br /&gt;public partial class _Default : System.Web.UI.Page &lt;br /&gt;{&lt;br /&gt;    protected void Page_Load(object sender, EventArgs e)&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;    protected void Button1_Click(object sender, EventArgs e)&lt;br /&gt;    {&lt;br /&gt;        MailMessage message = new MailMessage("FROM@domain.foo", "TO@domain.foo", "SYNCHRONOUS MESSAGE", "MESSAGE BODY");&lt;br /&gt;        SmtpClient smtp = new SmtpClient();&lt;br /&gt;        smtp.Send(message);&lt;br /&gt;    }&lt;br /&gt;    protected void Button2_Click(object sender, EventArgs e)&lt;br /&gt;    {&lt;br /&gt;        MailMessage message = new MailMessage("FROM@domain.foo", "TO@domain.foo", "ASYNCHRONOUS MESSAGE", "MESSAGE BODY");&lt;br /&gt;        SmtpClient smtp = new SmtpClient();&lt;br /&gt;        smtp.SendAsync(message, null);&lt;br /&gt;    }&lt;br /&gt;    protected void Button3_Click(object sender, EventArgs e)&lt;br /&gt;    {&lt;br /&gt;        System.Web.Mail.SmtpMail.Send("FROM@domain.foo", "TO@domain.foo", "OLD MESSAGE", "MESSAGE BODY");&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;to this:&lt;/h3&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;strong&gt;using&lt;/strong&gt; &lt;font color="#2040a0"&gt;System&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;using&lt;/strong&gt; &lt;font color="#2040a0"&gt;System&lt;/font&gt;.&lt;font color="#2040a0"&gt;Collections&lt;/font&gt;.&lt;font color="#2040a0"&gt;Generic&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;using&lt;/strong&gt; &lt;font color="#2040a0"&gt;System&lt;/font&gt;.&lt;font color="#2040a0"&gt;Linq&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;using&lt;/strong&gt; &lt;font color="#2040a0"&gt;System&lt;/font&gt;.&lt;font color="#2040a0"&gt;Web&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;using&lt;/strong&gt; &lt;font color="#2040a0"&gt;System&lt;/font&gt;.&lt;font color="#2040a0"&gt;Web&lt;/font&gt;.&lt;font color="#2040a0"&gt;UI&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;using&lt;/strong&gt; &lt;font color="#2040a0"&gt;System&lt;/font&gt;.&lt;font color="#2040a0"&gt;Web&lt;/font&gt;.&lt;font color="#2040a0"&gt;UI&lt;/font&gt;.&lt;font color="#2040a0"&gt;WebControls&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;using&lt;/strong&gt; &lt;font color="#2040a0"&gt;System&lt;/font&gt;.&lt;font color="#2040a0"&gt;Net&lt;/font&gt;.&lt;font color="#2040a0"&gt;Mail&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;public&lt;/strong&gt; &lt;font color="#2040a0"&gt;partial&lt;/font&gt; &lt;strong&gt;class&lt;/strong&gt; &lt;font color="#2040a0"&gt;_Default&lt;/font&gt; &lt;font color="4444FF"&gt;:&lt;/font&gt; &lt;font color="#2040a0"&gt;System&lt;/font&gt;.&lt;font color="#2040a0"&gt;Web&lt;/font&gt;.&lt;font color="#2040a0"&gt;UI&lt;/font&gt;.&lt;font color="#2040a0"&gt;Page&lt;/font&gt; &lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;    &lt;strong&gt;protected&lt;/strong&gt; &lt;strong&gt;void&lt;/strong&gt; &lt;font color="#2040a0"&gt;Page_Load&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;object&lt;/font&gt; &lt;font color="#2040a0"&gt;sender&lt;/font&gt;, &lt;font color="#2040a0"&gt;EventArgs&lt;/font&gt; &lt;font color="#2040a0"&gt;e&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;    &lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;    &lt;strong&gt;protected&lt;/strong&gt; &lt;strong&gt;void&lt;/strong&gt; &lt;font color="#2040a0"&gt;Button1_Click&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;object&lt;/font&gt; &lt;font color="#2040a0"&gt;sender&lt;/font&gt;, &lt;font color="#2040a0"&gt;EventArgs&lt;/font&gt; &lt;font color="#2040a0"&gt;e&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;        &lt;font color="#2040a0"&gt;MailMessage&lt;/font&gt; &lt;font color="#2040a0"&gt;message&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;strong&gt;new&lt;/strong&gt; &lt;font color="#2040a0"&gt;MailMessage&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#008000"&gt;&amp;quot;FROM@domain.foo&amp;quot;&lt;/font&gt;, &lt;font color="#008000"&gt;&amp;quot;TO@domain.foo&amp;quot;&lt;/font&gt;, &lt;font color="#008000"&gt;&amp;quot;SYNCHRONOUS MESSAGE&amp;quot;&lt;/font&gt;, &lt;font color="#008000"&gt;&amp;quot;MESSAGE BODY&amp;quot;&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;        &lt;font color="#2040a0"&gt;SmtpClient&lt;/font&gt; &lt;font color="#2040a0"&gt;smtp&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;strong&gt;new&lt;/strong&gt; &lt;font color="#2040a0"&gt;SmtpClient&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;        &lt;font color="#2040a0"&gt;smtp&lt;/font&gt;.&lt;font color="#2040a0"&gt;Send&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;message&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;    &lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;    &lt;strong&gt;protected&lt;/strong&gt; &lt;strong&gt;void&lt;/strong&gt; &lt;font color="#2040a0"&gt;Button2_Click&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;object&lt;/font&gt; &lt;font color="#2040a0"&gt;sender&lt;/font&gt;, &lt;font color="#2040a0"&gt;EventArgs&lt;/font&gt; &lt;font color="#2040a0"&gt;e&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;        &lt;font color="#2040a0"&gt;MailMessage&lt;/font&gt; &lt;font color="#2040a0"&gt;message&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;strong&gt;new&lt;/strong&gt; &lt;font color="#2040a0"&gt;MailMessage&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#008000"&gt;&amp;quot;FROM@domain.foo&amp;quot;&lt;/font&gt;, &lt;font color="#008000"&gt;&amp;quot;TO@domain.foo&amp;quot;&lt;/font&gt;, &lt;font color="#008000"&gt;&amp;quot;ASYNCHRONOUS MESSAGE&amp;quot;&lt;/font&gt;, &lt;font color="#008000"&gt;&amp;quot;MESSAGE BODY&amp;quot;&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;        &lt;font color="#2040a0"&gt;SmtpClient&lt;/font&gt; &lt;font color="#2040a0"&gt;smtp&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;strong&gt;new&lt;/strong&gt; &lt;font color="#2040a0"&gt;SmtpClient&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;        &lt;font color="#2040a0"&gt;smtp&lt;/font&gt;.&lt;font color="#2040a0"&gt;SendAsync&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;message&lt;/font&gt;, &lt;font color="#2040a0"&gt;null&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;    &lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;    &lt;strong&gt;protected&lt;/strong&gt; &lt;strong&gt;void&lt;/strong&gt; &lt;font color="#2040a0"&gt;Button3_Click&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;object&lt;/font&gt; &lt;font color="#2040a0"&gt;sender&lt;/font&gt;, &lt;font color="#2040a0"&gt;EventArgs&lt;/font&gt; &lt;font color="#2040a0"&gt;e&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;    &lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;        &lt;font color="#2040a0"&gt;System&lt;/font&gt;.&lt;font color="#2040a0"&gt;Web&lt;/font&gt;.&lt;font color="#2040a0"&gt;Mail&lt;/font&gt;.&lt;font color="#2040a0"&gt;SmtpMail&lt;/font&gt;.&lt;font color="#2040a0"&gt;Send&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#008000"&gt;&amp;quot;FROM@domain.foo&amp;quot;&lt;/font&gt;, &lt;font color="#008000"&gt;&amp;quot;TO@domain.foo&amp;quot;&lt;/font&gt;, &lt;font color="#008000"&gt;&amp;quot;OLD MESSAGE&amp;quot;&lt;/font&gt;, &lt;font color="#008000"&gt;&amp;quot;MESSAGE BODY&amp;quot;&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;    &lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-4791904276679623205?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/4791904276679623205/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=4791904276679623205' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/4791904276679623205'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/4791904276679623205'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2009/01/its-all-about-presentation.html' title='It&apos;s all about presentation...'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-3566027528179104406</id><published>2009-01-21T12:46:00.015-07:00</published><updated>2009-02-02T09:38:47.886-07:00</updated><title type='text'>You had me at ehlo!</title><content type='html'>It seems that a lot of websites send users email for lots of reasons. This introduces a bit of a problem when you are developing applications because as developers we don't necessarily want to put an smtp server on our development machine and network administrators are fairly selective about the open SMTP relays that they want on their network.&lt;br /&gt;&lt;br /&gt;ASP.net has a solution, and I have a solution.&lt;br /&gt;&lt;br /&gt;The asp.net solution is that the web server where your application will eventually live can (will) have a single machine configuration for the smtp settings. Every application can override this setting in the web.config file, but should actually just comment out the &lt;span style="color:#2040a0;"&gt;&lt;strong&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;mailsettings&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt; section.&lt;br /&gt;&lt;br /&gt;During development, however, this configuration is useful:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color:#2040a0;"&gt;&lt;strong&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;configuration&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#2040a0;"&gt;&lt;strong&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;system.net&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:#2040a0;"&gt;&lt;strong&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;mailSettings&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:#2040a0;"&gt;&lt;strong&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;smtp&lt;/span&gt; &lt;span style="color:#2040a0;"&gt;from=&lt;/span&gt;&lt;span style="color:#008000;"&gt;"admin@foo.bar"&lt;/span&gt; &lt;span style="color:#2040a0;"&gt;deliveryMethod=&lt;/span&gt;&lt;span style="color:#008000;"&gt;"SpecifiedPickupDirectory"&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;    &lt;span style="color:#2040a0;"&gt;&lt;strong&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;specifiedPickupDirectory&lt;/span&gt; &lt;span style="color:#2040a0;"&gt;pickupDirectoryLocation=&lt;/span&gt;&lt;span style="color:#008000;"&gt;"C:\pickup" /&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;   &lt;span style="color:#2040a0;"&gt;&lt;strong&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;/smtp&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:#2040a0;"&gt;&lt;strong&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;/mailSettings&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#2040a0;"&gt;&lt;strong&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;/system.net&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#2040a0;"&gt;&lt;strong&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;&amp;lt;&lt;/strong&gt;&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;/configuration&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;&amp;gt;&lt;/strong&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This will just dump the emails in the C:\pickup directory of your development machine. No need to install the SMTP service on your computer at all! This only works with the email classes in System.Net.Mail.&lt;br /&gt;&lt;br /&gt;If you use System.Web.Mail.SmtpMail you are out of luck because it defaults to using a network delivery and localhost as the server. That is where my other solution comes in...&lt;br /&gt;&lt;br /&gt;I wrote a quickie program a few years ago that I call "Black Hole" because it sucks up everything you send at it and doesn't let anything out. It is a stand alone SMTP server that just can either silently eat messages, or it can log the communication with your smtp client, and optionally dump the email messages do a directory.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_SAsEHVMNseo/SXeBnSZGhGI/AAAAAAAAA9o/LvMOoNJL-Ys/s1600-h/BlackHole.JPG"&gt;&lt;img id="BLOGGER_PHOTO_ID_5293842398949311586" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; WIDTH: 272px; CURSOR: hand; HEIGHT: 320px" alt="" src="http://1.bp.blogspot.com/_SAsEHVMNseo/SXeBnSZGhGI/AAAAAAAAA9o/LvMOoNJL-Ys/s320/BlackHole.JPG" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can download it &lt;a href="http://www.incwells.com/GetFile.aspx?File=BlackHole2.zip"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The zip file contains a stand-alone executable (written in Delphi) that will listen on whatever port you tell it and whatever ip addresses you want. Then, just configure your web.config (or app.config for that matter) settings to point to localhost with no credentials needed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-3566027528179104406?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/3566027528179104406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=3566027528179104406' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/3566027528179104406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/3566027528179104406'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2009/01/you-had-me-at-ehlo.html' title='You had me at ehlo!'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_SAsEHVMNseo/SXeBnSZGhGI/AAAAAAAAA9o/LvMOoNJL-Ys/s72-c/BlackHole.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-3435719836719666868</id><published>2008-12-09T13:46:00.006-07:00</published><updated>2009-01-05T12:07:32.568-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ATLAS'/><category scheme='http://www.blogger.com/atom/ns#' term='Lookup'/><category scheme='http://www.blogger.com/atom/ns#' term='AutoCompleteExtender'/><category scheme='http://www.blogger.com/atom/ns#' term='AJAX Control Toolkit'/><title type='text'>ATLAS AJAX Control Toolkit AutoCompleteExtender with Key Lookup</title><content type='html'>I like the ATLAS AJAX Control Toolkit. It integrates with Visual Studio and has useful if not basic javascript functions that can help a website be much more interactive.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://www.asp.net/AJAX/AjaxControlToolkit/Samples/AutoComplete/AutoComplete.aspx"&gt;AutoComplete&lt;/a&gt; Extender is used to provide auto-complete functionality to a text box. To use it, you simply add an extender and a web service method that provides a list of strings based on the text that the user started typing. So, if you are trying to provide the exact string that the user is typing (ala google search help), you can use it out of the box.&lt;br /&gt;&lt;br /&gt;However, sometimes you want more list-ish functions, that is, you want to present the user with a list of valid choices that represent objects, not just the descriptions. One alternative is to use a Listbox with a &lt;a href="http://www.asp.net/AJAX/AjaxControlToolkit/Samples/ListSearch/ListSearch.aspx"&gt;ListSearch&lt;/a&gt; Extender. This extender is used to find an existing value within the listBox. The downside to this approach is that every item you are looking for has to be in the list. This can be rather unwieldy if the list has more than a couple dozen items.&lt;br /&gt;&lt;br /&gt;The other alternative is to use the AutoComplete extender, but have it return a text string and a key that may be used to load the found item. This function is available, but not well documented (or at least where I can find it easily), so, in conformity with the &lt;a href="http://andmasterofnone.blogspot.com/2005/09/jack-of-all-trades.html"&gt;purpose of this blog&lt;/a&gt;, I'm putting sample code here.&lt;br /&gt;&lt;br /&gt;First of all, we need a hidden field and a text box (with the extender). The bolded properties in the extender point to the web method and the javascript methods that we'll need later.&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&amp;lt;asp:hiddenfield id="AccountNumber" runat="server"&amp;gt;&lt;br /&gt;&amp;lt;asp:TextBox ID="AccountNumberTextBox" runat="server" Width="20em"/&amp;gt;&lt;br /&gt;&amp;lt;cc1:AutoCompleteExtender ID="AccountNumberTextBox_AutoCompleteExtender"&lt;br /&gt;runat="server" CompletionInterval="200" DelimiterCharacters="" Enabled="True"&lt;br /&gt;FirstRowSelected="True" MinimumPrefixLength="1" &lt;br /&gt;&lt;strong&gt;ServiceMethod="GetCompletionList"&lt;/strong&gt; ServicePath=""&lt;br /&gt;TargetControlID="AccountNumberTextBox" UseContextKey="True"&lt;br /&gt;&lt;strong&gt;OnClientItemSelected="AutoCompleteSelected"&lt;/strong&gt; /&amp;gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;The next thing that has to be done is to return a specially encoded list of label/values in the string array from your web service:&lt;br /&gt;&lt;blockquote&gt;[System.Web.Services.WebMethodAttribute(), System.Web.Script.Services.ScriptMethodAttribute()]&lt;br /&gt;public static string[] GetCompletionList(string prefixText, int count, string contextKey)&lt;br /&gt;{&lt;br /&gt;myDataContext dc = new DataContext();&lt;br /&gt;var r = (from le in dc.Entities&lt;br /&gt;where (le.AccountNumber.Contains(prefixText) le.Name.Contains(prefixText))&lt;br /&gt;select le).Take(count);&lt;br /&gt;List&lt;string&gt; results = new List&lt;string&gt;();&lt;br /&gt;foreach (var item in r)&lt;br /&gt;{&lt;br /&gt;results.Add(AjaxControlToolkit.AutoCompleteExtender.CreateAutoCompleteItem(&lt;br /&gt;string.Format("{0} ({1})", item.Name, item.AccountNumber), item.AccountNumber));&lt;br /&gt;}&lt;br /&gt;return results.ToArray();&lt;br /&gt;}&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The AjaxControlToolkit.AutoCompleteExtender.CreateAutoCompleteItem takes a description and a key value and munges them into a string that can easily parse out the account number.&lt;/p&gt;&lt;p&gt;With that done, we need to add a javascript block to our ASPX that will populate the hidden field with the key value when it is selected from the list.&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;script type="text/javascript"&gt;&lt;br /&gt;var acctNo =&lt;br /&gt;'&lt;%=AccountNumber.ClientID%&gt;';&lt;br /&gt;function&lt;br /&gt;AutoCompleteSelected(source,&lt;br /&gt;eventArgs)&lt;br /&gt;{&lt;br /&gt;document.getElementById(acctNo).value =&lt;br /&gt;eventArgs.get_value();&lt;br /&gt;//alert(eventArgs.get_text() + " " +&lt;br /&gt;eventArgs.get_value());&lt;br /&gt;}&lt;br /&gt;&lt;/script&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;This script (and constant) do a couple of things. First, we capture the Id of the hidden control so we can use it later to know where to put the id. Next, we disassemble the special text by using the eventArgs.get_Text() and eventArgs.get_Value() functions. These functions are included by the same library that defined our extender.&lt;br /&gt;&lt;br /&gt;Add this script to the header section of your page&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;var acctNo = '&amp;lt;%=AccountNumber.ClientId%&amp;gt;';&lt;br /&gt;function AutoCompleteSelected(source,eventArgs)&lt;br /&gt;{&lt;br /&gt;   document.getElementById(acctNo).value = eventArgs.get_value();&lt;br /&gt;}&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-3435719836719666868?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/3435719836719666868/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=3435719836719666868' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/3435719836719666868'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/3435719836719666868'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2008/12/atlas-ajax-control-toolkit.html' title='ATLAS AJAX Control Toolkit AutoCompleteExtender with Key Lookup'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-2452554587643228647</id><published>2008-08-11T09:27:00.000-06:00</published><updated>2008-08-11T09:54:48.600-06:00</updated><title type='text'>IBM x335 and Windows 2008 installation</title><content type='html'>I love the fact that IBM stops supporting its hardware long before Microsoft does; this means that lots of top-tier companies have to decommission their *somewhat* old hardware and you can pick up a server cheap (or free) to play with at home.&lt;br /&gt;&lt;br /&gt;It may mean, however, that your installation mileage may vary. Such has been the case for my IBM x335 (of which I have three). I've been on a quest to do an installation of Windows Server 2008 on said boxen. (plural of ox is oxen, plural of box is...)&lt;br /&gt;&lt;br /&gt;How fickle a lover are antique hardware and modern operating systems? How doest thou vex me, let me count the ways...&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Windows 2008 only comes on DVD while an IBM x335 has only a CD and will not boot from USB.&lt;/li&gt;&lt;li&gt;Windows 2008 will not install from any sort of DOS utility disk. So Bart's Network boot disk is out, likewise a network boot to anything based on DOS.&lt;/li&gt;&lt;li&gt;The IBM x335 has an internal IDE that is used by its CD Rom. You can crack the case and use an internal DVD drive from some other computer to install the os. This feels like cheating on an exam.&lt;/li&gt;&lt;li&gt;VMWare ESXi runs well on an IBM x335, and will allow installation of Windows 2008 from a DVD image (.iso file). This is also cheating, and ultimately not as satisfying as beating the beast at it's own game.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;So, you aren't reading this to find out the problems that you probably already know, right? So, let's give some credit here to &lt;a href="http://blog.geekeleet.com/"&gt;GeekEleet &lt;/a&gt;and two articles that helped me to solve this issue:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://blog.geekeleet.com/post/2008/02/27/Windows-Server-2008-Only-Comes-on-DVD.aspx"&gt;Windows 2008 only comes on DVD&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://blog.geekeleet.com/post/2008/02/27/Windows-Server-2008-Hangs-After-Loading-crcdisksys.aspx"&gt;Windows Server 2008 hangs...&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I also want to thank redmutt.com for their article on &lt;a href="http://redmutt.com/?p=119"&gt;Installing Windows 2008 on an IBM xSeries 335&lt;/a&gt; that included the link to the appropriate raid driver.&lt;/p&gt;&lt;p&gt;The key points of the articles are that:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Windows 2008 only installs from a WinPE 2.0 disk&lt;/li&gt;&lt;li&gt;You can make a WinPE 2.0 disk by using the &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=c7d4bc6d-15f3-4284-9123-679830d629f2&amp;amp;displaylang=en"&gt;Windows Automated Installation Kit&lt;/a&gt;&lt;/li&gt;&lt;li&gt;WinPE 2.0 allows you to map a network drive (containing your Windows 2008 install files) using net use...&lt;/li&gt;&lt;li&gt;You might also be able to make CD installation media using the WAIK and do away with the network install all together.&lt;/li&gt;&lt;li&gt;You might need to update your bios using the &lt;a href="http://www-304.ibm.com/systems/support/supportsite.wss/docdisplay?lndocid=MIGR-5069874&amp;amp;brandind=5000008"&gt;IBM UpdateXpress CD 4.05a for System x&lt;/a&gt;&lt;/li&gt;&lt;li&gt;You also need the &lt;a href="https://www-304.ibm.com/systems/support/supportsite.wss/docdisplay?brandind=5000008&amp;amp;lndocid=MIGR-52747"&gt;LSI Logic PCI SCSI/FC MPI Minoport driver v1.25.10 for Microsoft Windows Server 2008&lt;/a&gt; that you can load from a floppy, usb drive, or network drive during installation&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;One further observation is that you can do an in-place upgrade or install of Windows 2003 server if you specify the driver during installation.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-2452554587643228647?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/2452554587643228647/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=2452554587643228647' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/2452554587643228647'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/2452554587643228647'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2008/08/ibm-x335-and-windows-2008-installation.html' title='IBM x335 and Windows 2008 installation'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-7820022172917748364</id><published>2008-03-10T16:12:00.001-06:00</published><updated>2008-03-10T16:15:32.640-06:00</updated><title type='text'>New cool tool</title><content type='html'>Oh, by the way, I have to give some credit to Notepad++ for that last post. The asp.net was HTML encoded using Notepad++ (TextFX  TextFX Convert  Encode HTML). I keep Notepad++ on a USB drive using &lt;a href="http://portableapps.com/"&gt;PortableApps&lt;/a&gt;. It has lots of cool tools that are handy to keep with you or keep personal like KeyPass portable, but that's another post!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-7820022172917748364?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/7820022172917748364/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=7820022172917748364' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/7820022172917748364'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/7820022172917748364'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2008/03/new-cool-tool.html' title='New cool tool'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-4000087801610245225</id><published>2008-03-10T15:51:00.001-06:00</published><updated>2009-08-12T11:31:32.050-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='IP'/><category scheme='http://www.blogger.com/atom/ns#' term='AJAX'/><category scheme='http://www.blogger.com/atom/ns#' term='Regular Expressions'/><title type='text'>AJAX and IP Addresses</title><content type='html'>I realize you are disappointed, but the only clever title I could think of for IP Address reminded me of a stupid joke from kindergarten... Never the less.&lt;br /&gt;&lt;br /&gt;Here is a cool formula for a client-validated IP address using the AJAX Control Toolkit and asp.net.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;&lt;blockquote&gt;&lt;p&gt;&lt;br /&gt;&amp;lt;asp:TextBox ID="TextBox1" runat="server" Text='&amp;lt;%# DataValue %&amp;gt;'&amp;gt;&amp;lt;/asp:TextBox&amp;gt;&lt;br /&gt;&amp;lt;cc1:MaskedEditExtender ID="MaskedEditExtender1" runat="server" TargetControlID="TextBox1"&lt;br /&gt;Mask="NNNNNNNNNNNNNNN" MaskType="None" ClearMaskOnLostFocus="true" Filtered=". " PromptCharacter="" /&amp;gt;&lt;br /&gt;&amp;lt;cc1:MaskedEditValidator ID="MaskedEditValidator1" runat="server" ControlToValidate="TextBox1"&lt;br /&gt;InvalidValueMessage="IP Address required (192.168.1.1)" ControlExtender="MaskedEditExtender1" ValidationExpression="^([01]?\d\d?2[0-4]\d25[0-5])\.([01]?\d\d?2[0-4]\d25[0-5])\.([01]?\d\d?2[0-4]\d25[0-5])\.([01]?\d\d?2[0-4]\d25[0-5])$" /&amp;gt;&lt;br /&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;/blockquote&gt;&lt;br /&gt;It's really not that involved.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;The first control is a normal text box. I happen to be using the new dynamic data stuff from Microsoft. It's pretty cool, but you could bind or not as you want.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;The MaskedEditExtender is important because it limits the characters somebody can type to numbers (the N characters in the mask) and the filtered characters (period and space). With 15 spaces maximum, this means the user can't type in too much stuff&lt;/p&gt;&lt;p&gt;Finally, the MaskedEditValidator control has a regular expression that accepts all the valid number mixes from 0-255 for each digit, and only four octets&lt;/p&gt;&lt;br /&gt;Once you add it up, you get a client-side filtered IP address with Javascript validation.&lt;br /&gt;&lt;br /&gt;Update:&lt;br /&gt;&lt;br /&gt;The regular expression could also be written as:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;^([01]?\d\d?2[0-4]\d25[0-5])(\.([01]?\d\d?2[0-4]\d25[0-5])){3}$ &lt;/span&gt;&lt;br /&gt;It works something like this:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The carat (^)  and dollar sign ($) mean that the expression matches stuff that start and end the input.&lt;/li&gt;&lt;li&gt;The first subsection (first set of paranthesis) has three rules: the first "[01]?\d\d?" will match the numbers from 0 to 199 with or without leading zeroes (000 or 0), the second "2[0-4]d" matches numbers from 200 through 249, and the third "25[0-5]" matches values from 250 to 255&lt;/li&gt;&lt;li&gt;the next subsection prepends the previous rule with a period (or dot)  exactly three more times.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The end result is that you have exactly four numbers from 0-255 separated by three dots.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-4000087801610245225?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/4000087801610245225/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=4000087801610245225' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/4000087801610245225'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/4000087801610245225'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2008/03/ajax-and-ip-addresses.html' title='AJAX and IP Addresses'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-6269350858520430026</id><published>2007-12-17T10:55:00.000-07:00</published><updated>2007-12-17T10:59:05.205-07:00</updated><title type='text'>Expand your mind</title><content type='html'>The only hassle of working with Virtual Machines is being omniscient: how in the world am I supposed to know how big to make the virtual drive when I don't know what stuff I'm going to install on the machine?&lt;br /&gt;&lt;br /&gt;Solution: &lt;a href="http://www.vmware.com/download/converter/download.html"&gt;VMWare Converter&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This little beauty non only lets you convert physical machines to VMs, or Microsoft VMs to VMWare VMs, it also lets you convert VMWare VM's to another version &lt;em&gt;and resize the disk along the way!&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;sweet!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-6269350858520430026?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/6269350858520430026/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=6269350858520430026' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/6269350858520430026'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/6269350858520430026'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2007/12/expand-your-mind.html' title='Expand your mind'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-8739246285480633854</id><published>2007-12-05T15:29:00.000-07:00</published><updated>2007-12-05T15:34:05.042-07:00</updated><title type='text'>If I could get connected, I could tell who you are</title><content type='html'>Playing with Visual Studio 2008, .net 3.5 and SQL Linq today and decided to make the thing a real application. That means using a membership database. I really like using sql express for development (and deployment) of little applications. It's a shame that my hosting provider doesn't let you use an express database, but I digress...&lt;br /&gt;&lt;br /&gt;Anyway, how do you go about creating membership in an existing database...&lt;br /&gt;&lt;br /&gt;You twiddle with the command line parameters until you figure out that this is how:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;aspnet_regsql -A all -C "Data Source=.\SQLEXPRESS;Integrated&lt;br /&gt;Security=True;User Instance=True" -d "C:\MyProject\APP_DATA\aspnetdb.mdf"&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-8739246285480633854?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/8739246285480633854/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=8739246285480633854' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/8739246285480633854'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/8739246285480633854'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2007/12/if-i-could-get-connected-i-could-tell.html' title='If I could get connected, I could tell who you are'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-864006765331361934</id><published>2007-06-06T15:59:00.000-06:00</published><updated>2007-06-06T16:10:46.964-06:00</updated><title type='text'>You've been very helpful, can you just go away now.</title><content type='html'>Sometimes when dealing with a typed dataset (a good idea) you have a problem with constraints, or with nullable fields, or with other stuff. Microsoft gives you a less-than-helpful exception that says "Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints."&lt;br /&gt;Right...&lt;br /&gt;Well, if you use:&lt;br /&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;ds.EnforceConstraints = false;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;then you can call this method which will output the table, row, column, and exact constraint that was violated.&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;blockquote&gt;&lt;p&gt;&lt;br /&gt;public void GetDataSetErrors(DataSet ds){ &lt;/p&gt;&lt;p&gt;try { ds.EnforceConstraints = true; } &lt;/p&gt;&lt;p&gt;catch(Exception ex) { &lt;/p&gt;&lt;p&gt;foreach&lt;br /&gt;(DataTable table in ds.Tables) { &lt;/p&gt;&lt;p&gt;foreach (DataRow row in table.GetErrors()){ System.Diagnostics.Trace.WriteLine("Table: "+&lt;br /&gt;table.TableName); System.Diagnostics.Trace.WriteLine(ex.Message&lt;br /&gt;); System.Diagnostics.Trace.WriteLine("Row: "&lt;br /&gt;+row.RowError); foreach (DataColumn col in&lt;br /&gt;row.GetColumnsInError())&lt;br /&gt;{ System.Diagnostics.Trace.WriteLine("Column&lt;br /&gt;" +&lt;br /&gt;col.ColumnName); System.Diagnostics.Trace.WriteLine(&lt;br /&gt;row.GetColumnError(col)); } } } } }&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;br /&gt;It just makes you feel all warm and fuzzy inside, doesn't it?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-864006765331361934?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/864006765331361934/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=864006765331361934' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/864006765331361934'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/864006765331361934'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2007/06/youve-been-very-helpful-can-you-just-go.html' title='You&apos;ve been very helpful, can you just go away now.'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-116319540976932912</id><published>2006-11-10T14:41:00.002-07:00</published><updated>2010-01-22T14:51:13.469-07:00</updated><title type='text'>Does this dress make me look fat?</title><content type='html'>Here's a nice little bit of code that can be used to dynamically theme a website that has multiple domains at the same site.&lt;br /&gt;&lt;pre class="brush: csharp"&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Text;&lt;br /&gt;using System.Web;&lt;br /&gt;using System.Web.UI;&lt;br /&gt;&lt;br /&gt;namespace URLThemeHandler {&lt;br /&gt;public class ThemeHandler : IHttpModule {&lt;br /&gt;#region IHttpModule Members&lt;br /&gt;&lt;br /&gt;public void Dispose() {&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void Init(HttpApplication context) {&lt;br /&gt;context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void context_PreRequestHandlerExecute(object sender, EventArgs e) {&lt;br /&gt;HttpContext currentContext = HttpContext.Current;&lt;br /&gt;if (!(currentContext.Handler is System.Web.UI.Page)) return;&lt;br /&gt;System.Web.UI.Page myPage = currentContext.Handler as System.Web.UI.Page;&lt;br /&gt;string strHost = currentContext.Request.Url.Host;&lt;br /&gt;if(ThemeExists(strHost))&lt;br /&gt;myPage.Theme = strHost;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;bool ThemeExists(string theme) {&lt;br /&gt;string strPath = HttpContext.Current.Server.MapPath("~/App_Themes/" + theme);&lt;br /&gt;return System.IO.Directory.Exists(strPath);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;#endregion&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You can register it in the httpModules section of the Web.config.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-116319540976932912?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/116319540976932912/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=116319540976932912' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/116319540976932912'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/116319540976932912'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2006/11/does-this-dress-make-me-look-fat.html' title='Does this dress make me look fat?'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-115318404825785231</id><published>2006-07-17T18:50:00.000-06:00</published><updated>2006-07-17T18:54:08.270-06:00</updated><title type='text'>Can you hear me NOW?!?!</title><content type='html'>My wife is very disgusted with our packet8 telephone. Part of the issues we're facing are that our Belkin router will block the outbound voice (thinking that it is a DOS attack). In the security log, there was this entry:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;07/17/2006 18:35:57 **UDP Flood to Host** 192.168.1.10, 8006-&gt;&gt;&lt;br /&gt;209.247.23.73, 62602 (from WAN Outbound)&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;So, thanks to a technical article I found, there is a support page that references this URL: http://192.168.1.1/firewall_spi_h.stm which allows you to turn off the "SPI and Anti-DoS firewall protection:"&lt;br /&gt;&lt;br /&gt;It should be easier to turn off a feature like this than an undocumented feature.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-115318404825785231?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/115318404825785231/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=115318404825785231' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/115318404825785231'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/115318404825785231'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2006/07/can-you-hear-me-now.html' title='Can you hear me NOW?!?!'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-115220475295448481</id><published>2006-07-06T10:41:00.007-06:00</published><updated>2010-01-22T14:49:26.192-07:00</updated><title type='text'>It's about time...</title><content type='html'>Time and space. Two of my favorite things. Time keeps everything from happening all at once. Space keeps everything from happening to you. Time AND Space keep everything from happening all at once to you!&lt;br /&gt;The problem to be solved today is this: Create a .net object that has it's XML serialization saved to an XML column in a database table. Now, have a trigger (add/update) that takes that XML field and denormalizes its content to some additional columns. In this way, you have the denormalized data that you might want to use for joins and filtering without having to parse the XML field over and over. &lt;br /&gt;You'd create a class something like this:&lt;br /&gt;&lt;pre class="brush: csharp"&gt;public class Foo {&lt;br /&gt;Guid _id = Guid.NewGuid(); //This is our object's database identifier&lt;br /&gt;DateTime _updated= DateTime.Now; //This was the last time the object was changed&lt;br /&gt;string _description = string.empty;&lt;br /&gt;&lt;br /&gt;public Guid Id{ get{return _id;} set{_id = value;} }&lt;br /&gt;public string Description { &lt;br /&gt;get{return _description;} &lt;br /&gt;set{_description = value; Update();} }&lt;br /&gt;public DateTime Updated { get{return _updated;} set{} }&lt;br /&gt;private void Update(){ _updated = DateTime.Now; }&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;You remember how to serialize an object as XML, right? Ok, just for reference, here is how we would get our object as XML text:&lt;br /&gt;&lt;pre class="brush: csharp"&gt;XmlSerializer serializer = new XmlSerializer(typeof(Foo));&lt;br /&gt;System.Text.StringBuilder sb = new System.Text.StringBuilder();&lt;br /&gt;TextWriter writer = new StringWriter(sb);&lt;br /&gt;serializer.Serialize(writer, this);&lt;br /&gt;writer.Close();&lt;br /&gt;string XMLText = sb.ToString();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;You would also have a table that looks like this:&lt;br /&gt;&lt;pre class="brush: sql"&gt;CREATE TABLE [dbo].[TableXML](&lt;br /&gt;[Id] [uniqueidentifier] ROWGUIDCOL  NOT NULL CONSTRAINT &lt;br /&gt;[XML] [xml] NOT NULL,&lt;br /&gt;[Description] [nvarchar](max) )&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then you'd add a trigger to the table that looks like this:&lt;br /&gt;&lt;pre class="brush: sql"&gt;CREATE TRIGGER [TableXML_InsUpd] ON  [dbo].[TableXML] AFTER INSERT,UPDATE AS &lt;br /&gt;BEGIN&lt;br /&gt;SET NOCOUNT ON;&lt;br /&gt;IF UPDATE([XML]) -- Only update the table if the XML field was updated.&lt;br /&gt;BEGIN&lt;br /&gt;UPDATE [MWI].[dbo].[TableXML] SET &lt;br /&gt;[Description] = INSERTED.XML.value('(//Description)[1]','nVarchar(MAX)'),&lt;br /&gt;[Updated] = INSERTED.XML.value('xs:dateTime((//Updated)[1])','DateTime')&lt;br /&gt;FROM INSERTED WHERE [PromotionXML].PromotionId = INSERTED.PromotionId&lt;br /&gt;END&lt;br /&gt;END&lt;/pre&gt;&lt;br /&gt;With these things in place, you could serialize the class to XML with code that looks like this:&lt;br /&gt;&lt;pre class="brush: csharp"&gt;public static void SaveFooDB(Foo foo) {&lt;br /&gt;// Put the XML representation of the object into the database&lt;br /&gt;SqlConnection conn = GetDataConnection(); //you'll have to write GetDataConnection&lt;br /&gt;SqlCommand cmd = new SqlCommand("foo_InsertOrUpdate", conn);&lt;br /&gt;using (cmd) {&lt;br /&gt;cmd.CommandType = System.Data.CommandType.StoredProcedure;&lt;br /&gt;cmd.Parameters.AddWithValue("@fooXML", promotion.ToString());&lt;br /&gt;cmd.ExecuteNonQuery();&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;The stored procedure "foo_InsertOrUpdate" simply checks if the id already exists in the database and updates the existing record if it does, otherwise it is a new record, so it is inserted. Why SQL server doesn't have this sort of query is a mystery to me. Notice, however that we only have to pass one parameter (the serialized XML from our object) and we extract the Id from that XML.&lt;br /&gt;&lt;pre class="brush: sql"&gt;CREATE PROCEDURE [dbo].[foo_InsertOrUpdate]( @FooXML XML ) AS&lt;br /&gt;BEGIN &lt;br /&gt;DECLARE @IdUniqueIdentifier&lt;br /&gt;select @Id= @FooXml.value('(//Id)[1]','UniqueIdentifier')&lt;br /&gt;IF Exists (Select FooId from [MWI].[dbo].[FooXML] WHERE Id= @Id) &lt;br /&gt;BEGIN&lt;br /&gt;UPDATE [MWI].[dbo].[FooXML] SET [XML] = @FooXML WHERE Id= @Id&lt;br /&gt;END&lt;br /&gt;ELSE &lt;br /&gt;BEGIN &lt;br /&gt;INSERT INTO [MWI].[dbo].[PromotionXML]([PromotionID],[XML])&lt;br /&gt;VALUES (@PromotionID, @PromotionXML)&lt;br /&gt;END&lt;br /&gt;END&lt;/pre&gt;&lt;br /&gt;Now you might argue that since we have our insert/update procedure, we could do all the work of populating the additional columns here rather than in the trigger. You are right of course IF all of your table updates come through this procedure. Me, I'd rather not assume that everyone will play nicely, especially since it is possible to update the xml directly and in bulk. So, the trigger works for my needs, your mileage may vary.&lt;br /&gt;Now everything works very well until we introduce another DateTime property in our class. If we (for example) bind that value to a DateTimePicker component, the XML extraction formatting will break. What is up with that?&lt;br /&gt;It turns out that the DateTime format in .NET is far more robust than in many other systems (notibly SQL Server's DateTime). In fact, there is a property called "kind" on .net DateTime objects. The DateTimePicker uses the DateTimeKind.Unspecified kind which doesn't have time zone information. We can remedy this little problem by creating a new DateTime object in the set accessor of our new FooDate Property like this:&lt;br /&gt;&lt;pre class="brush: csharp"&gt;DateTime _fooDate = DateTime.Today;&lt;br /&gt;&lt;br /&gt;public DateTime FooDate{&lt;br /&gt;get { return _fooDate; }&lt;br /&gt;set { _fooDate = new DateTime(value.Year, value.Month, value.Day, 0, 0, 0, 0, DateTimeKind.Local);}&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;Another thing that we can do here is to strip out the time infomation that is often provided by a calendar picker or other unreliable DateTime mechanism. One of my favorite tricks here is to specify the end of the day when people are picking a date range, so that we don't end up with that annoying "pick the next day really mean the end of today. Do something like this:&lt;br /&gt;&lt;pre class="brush: csharp"&gt;DateTime _fooEndDate= DateTime.Today;&lt;br /&gt;&lt;br /&gt;public DateTime FooEndDate{&lt;br /&gt;get { return _fooEndDate; }&lt;br /&gt;set { _fooEndDate= new DateTime(value.Year, value.Month, value.Day, 23, 59, 59, 0, DateTimeKind.Local);}&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;And finally (wow, this was a long post) you don't want to put in 999 for the milliseconds if you are going to put this value into SQL server, someplace along the way, the milliseconds are rounded up to tomorrow and our SQL column representation becomes different from the XML representation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-115220475295448481?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/115220475295448481/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=115220475295448481' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/115220475295448481'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/115220475295448481'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2006/07/its-about-time.html' title='It&apos;s about time...'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-115212866114181024</id><published>2006-07-05T13:42:00.002-06:00</published><updated>2010-01-22T14:42:59.009-07:00</updated><title type='text'>U-Turn (Going the other way)</title><content type='html'>So, here's a way to get back a delimited list of items from a table. In other words, concatenate values into one column (that you can then take together to pass to my parse table function).&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: sql"&gt;--Setup a sample data to demonstrate the concept&lt;br /&gt;declare @Table1 as Table (id int, Item varchar(100))&lt;br /&gt;insert into @Table1 values (1, 'a')&lt;br /&gt;insert into @Table1 values (1, 'b')&lt;br /&gt;insert into @Table1 values (2, 'c')&lt;br /&gt;-- show the table data&lt;br /&gt;select * from @Table1&lt;br /&gt;&lt;br /&gt;--retrieve the data from @Table1 as a concatinated list&lt;br /&gt;Select distinct id, (&lt;br /&gt;Select upper(Item)+' ' as [text()] from @Table1 S &lt;br /&gt;where id = T1.id &lt;br /&gt;for xml path('')) Items  from @Table1 T1&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-115212866114181024?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/115212866114181024/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=115212866114181024' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/115212866114181024'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/115212866114181024'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2006/07/u-turn-going-other-way.html' title='U-Turn (Going the other way)'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-114910374525188987</id><published>2006-05-31T13:19:00.000-06:00</published><updated>2006-05-31T13:37:57.146-06:00</updated><title type='text'>A mighty conversion</title><content type='html'>I recently ran into a situation where I needed to create an array of integers to a comma-delimited string in .Net. This *should* be easily accomplished by some sort of intrinsic function (like .toString()). But alas, no. So, you can do this (and other sorts of arrays in the following manner:&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;string strCSV = string.Join(",", Array.ConvertAll&amp;lt;int,string&amp;gt;(SkuList, new Converter&amp;lt;int,string&amp;gt;(Convert.ToString)));&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;Going the other way you can use something similar to turn the whole thing inside out:&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;int[] result = Array.ConvertAll&amp;lt;string,int&amp;gt;(strCSV.Split(new char[] { ',' }), new Converter&amp;lt;string,int&amp;gt;(Convert.ToInt32));&lt;/code&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-114910374525188987?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/114910374525188987/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=114910374525188987' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/114910374525188987'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/114910374525188987'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2006/05/mighty-conversion.html' title='A mighty conversion'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-114556309017159652</id><published>2006-04-20T13:35:00.000-06:00</published><updated>2006-04-20T14:09:00.610-06:00</updated><title type='text'>X-Men Code 127</title><content type='html'>One of the more interesting things about SQL Server 2005 is the support for the XML datatype. Instead of playing around with wierd and funky stored procedures to manipulate XML, you get validation and a bunch of other features just by specifying a field or a parameter as XML.&lt;br /&gt;Now, as nice as it is to be able to serialize a .net object and store the entire thing in one field in the database, I have my feelings that there is significant overhead to querying into that XML on a more than ad-hoc basis. So, you *might* want to add some additional fields to the table containing the xml. For example if you had the following XML:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;&amp;lt;OrderID&amp;gt;0a4fc0f8-6106-467f-ae10-45dcbfe4cefa&amp;lt;/OrderID&amp;gt;&lt;br /&gt;&amp;lt;CustomerNumber&amp;gt;1234&amp;lt;/CustomerNumber&amp;gt;&lt;br /&gt;&amp;lt;Status&amp;gt;Active&amp;lt;/Status&amp;gt;&amp;lt;Lines&amp;gt;&lt;br /&gt;&amp;lt;OrderLine ItemId="123" Quantity="2" Taxable="false" Price="12.34"&lt;br /&gt;DateChanged="2006-04-20T12:16:20.8942144-06:00"&lt;br /&gt;IsReadOnly="false"&amp;gt;&amp;lt;/OrderLine&amp;gt;&lt;br /&gt;&amp;lt;OrderLine ItemId="234" Quantity="2" Taxable="false" Price="56.78"&lt;br /&gt;DateChanged="2006-04-20T12:16:20.8942144-06:00"&lt;br /&gt;IsReadOnly="false"&amp;gt;&amp;lt;/OrderLine&amp;gt;&lt;br /&gt;&amp;lt;/Lines&amp;gt;&lt;br /&gt;&amp;lt;DateChanged&amp;gt;2006-04-20T12:16:20.8942144-06:00&amp;lt;/DateChanged&amp;gt;&amp;lt;/Order&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;br /&gt;You *might* want to have the top-level elements like "DateChanged" "CustomerNumber" and "OrderID" in redundant fields. Your data table might look like this:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;OrderID UniqueIdentifier&lt;br /&gt;DateChanged DateTime&lt;br /&gt;CustomerNumber Int&lt;br /&gt;OrderXML xml&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;/blockquote&gt;If you did this, you could create an Insert/Update trigger on the table that would automatically update the (non-key) fields (Thanks Scott!) that used the built-in XML features to update the duplicate fields whenever the xml (or any other field) was updated.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;ALTER TRIGGER [OrderXML_InsUpd]&lt;br /&gt;ON [dbo].[OrderXML]&lt;br /&gt;AFTER INSERT,UPDATE AS BEGIN&lt;br /&gt;SET NOCOUNT ON;&lt;br /&gt;UPDATE [MWI].[dbo].[OrderXML]&lt;br /&gt;SET&lt;br /&gt;[CustomerNumber] = INSERTED.XML.value('(//CustomerNumber)[1]','Int'),&lt;br /&gt;[DateChanged] = INSERTED.XML.value('xs:dateTime((//DateChanged)1])','DateTime'),&lt;br /&gt;[Status] = INSERTED.XML.value('(//Status)[1]','nVarchar(50)')&lt;br /&gt;FROM INSERTED &lt;br /&gt;WHERE [OrderXML].OrderId = INSERTED.OrderId&lt;br /&gt;END&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;br /&gt;Anyway, the whole thing is interesting, but pay close attention to the line that moves the date field into the DateTime column of the database table.&lt;br /&gt;&lt;p&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;[DateChanged] = INSERTED.XML.value('&lt;b&gt;xs:dateTime&lt;/b&gt;((//DateChanged)1])','DateTime')&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;The key to importing a .NET DateTime field into SQL server is to make sure to use the XML to cast the field as dateTime before SQL server gets it. Of course, this may not be necessary if you have a schema associated with the field that is already strongly typed in the XML.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-114556309017159652?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/114556309017159652/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=114556309017159652' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/114556309017159652'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/114556309017159652'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2006/04/x-men-code-127.html' title='X-Men Code 127'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-114435176171132073</id><published>2006-04-06T13:24:00.000-06:00</published><updated>2006-04-06T13:31:00.573-06:00</updated><title type='text'>What!?? No clever title?!??</title><content type='html'>No clever title for this one. Just a reminder that you can turn on tracing in an asp.net web page by including the following in your page directive:&lt;br /&gt;&lt;blockquote&gt;&amp;lt;%@ page trace="true" %&amp;gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;And, lest you tire of remembering which specific pages you have this enabled on, you can turn on tracing for an entire application by including the following in the web.config:&lt;br /&gt;&lt;blockquote&gt;&amp;lt;trace enabled="true" localonly="true" tracemode="SortByTime" pageoutput="true" requestlimit="10"&amp;gt;&amp;lt;trace enabled="true"&amp;gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-114435176171132073?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/114435176171132073/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=114435176171132073' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/114435176171132073'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/114435176171132073'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2006/04/what-no-clever-title.html' title='What!?? No clever title?!??'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-114425936567619898</id><published>2006-04-05T10:49:00.000-06:00</published><updated>2006-04-05T11:49:26.460-06:00</updated><title type='text'>Apple Core...Baltimore...Who's your friend?</title><content type='html'>I've always had a soft spot in my heart for Apple. While it wasn't my "first" computer, (that was a Commodore Pet), The Apple II was the computer where I learned about data structures, graphics, and really did some useful programming. In college when I needed to get a computer, I bought a Macintosh IIsi. While my computer programming career has been mostly Windows-centric, I still like the elegance and simplicity of products from Apple; especially when they are free.&lt;br /&gt;&lt;br /&gt;After playing with Music Match and other music programs, I've pretty much decided to use iTunes in my home as a music library management and MP3 player. I like it's playlist management features, the fact that it is easy to rip and burn physical CDs and the user interface is simple and elegant. The visualizations are cool too. I don't buy much music through the iTunes store (only one to date), but I do buy music on CD and want to be able to listen to it without physically handling the CDs; or more precisely, I don't want my children handling my CDs.&lt;br /&gt;&lt;br /&gt;Enter the problem. ITunes is great as a personal mp3 player for a single person. It can automatically organize your music and it sounds good. If I had an iPod, I'm sure that it would be really nice to be able to listen to the music there too. However, the one person - one computer paradigm that it is built around is really limiting. I'm not talking about circumventing DRM here, just being able to have everyone in my household listen to music while protecting my investment in CDs.&lt;br /&gt;&lt;br /&gt;Take, for example, my scenario. I am married with seven children. We have four computers in our home. I have a NT domain and each person can log into any of the computers. That means that if I install iTunes on each computer that there are potentially 36 copies of the music around my network! Ok, that is a worst case, but you can begin to see the issues.&lt;br /&gt;&lt;br /&gt;Now, iTunes has music sharing capabilities. Using some really cool network technology, you can make your music available over the network to other people in your local subnet. Great, but the person sharing the music must be logged in and running iTunes for that to work. That is no help to me. If my wife has some music that I want to listen to, she has to be logged in. Worse than that, apple has an artificial limit of five users connected to your music in a 24 hour period. Apparently a family should only have five people in it, each with their own personal computer.&lt;br /&gt;&lt;br /&gt;What about using my network to have a common music share? Well, here we begin to make some real progress. If I have a common directory for the music folder, then there is only one copy of the music on the network, but because iTunes keeps its database and configuration file in a user directory that is separate from the music directory, each user has to re-import all the music every time anyone imports a new CD. Still not good.&lt;br /&gt;&lt;br /&gt;An ideal solution would be to have iTunes use the registry to point to the configuration file and database file (that could be shared) and then have the music stored on a file share from the server. But that is not what they did. Each user's music database and configuration file live in a hard-coded "iTunes" folder that exists in the users "my Music" directory. You can change the name of the "my Music" directory in the registry, but it must always be in the "my Documents" folder which is unique for each user on each machine. If anyone from apple reads this, they might take this into consideration.&lt;br /&gt;&lt;br /&gt;Ok, Solution time.&lt;br /&gt;&lt;br /&gt;The first part of the solution is something that I already had in place. That is to create a user policy that mapps everyone's "my Documents" folder to a file share (mine is the p: drive). You can accomplish this using a login.bat file with the following line in it:&lt;br /&gt;&lt;blockquote&gt;net use p: \\server\%USERNAME% /PERSIST:NO&lt;/blockquote&gt;&lt;br /&gt;Next, in the policy, remap each users "my Documents" directory to their p: drive. &lt;br /&gt;&lt;br /&gt;I'm not going to go into the details of how to create user policies here. There are lots of resources available that cover this.&lt;br /&gt;&lt;br /&gt;If I stopped at this point, I would have achieved one really cool feature. All of the documents for every person in my family would follow them around from computer to computer. So Daniel could work on his essay on any computer in the house. &lt;br /&gt;&lt;br /&gt;Windows does this by using "offline folders" to synchronize the "my Documents" folder and its contents from one machine to another at logon, on demand, and at logoff. One downside is that there are copies of the files on every computer that the person uses. Most people don't have that many working files, however, so this isn't too big a deal, most of the time; as we shall see later.&lt;br /&gt;&lt;br /&gt;At this point, we still have the iTunes problem, however. That is that everyone has their own music, configuration, and database. The music issue can go away if we put all the music on a network file share. This is very important because without this, there will be a copy of each song on every computer. Now I know that hard drive space is cheap, but I have about 5 gb of mp3s, multiply that times 4 computers and 9 people and you'll agree that is a huge waste of space. &lt;br /&gt;&lt;br /&gt;Once you have a network share for media, you can configure iTunes to point to that directory.&lt;br /&gt;&lt;br /&gt;Final problem. Because iTunes doesn't automatically scan it's music folder for changes, you have to manually "refresh" each person's music database when anyone imports a new CD. This is a pain, because it isn't the most intuitive process. You have to re-import the directory. Well, my 9 year old likes to listen to music, but she really isn't going to run the music import function.&lt;br /&gt;&lt;br /&gt;What would be really good is to be able to share the iTunes folder...&lt;br /&gt;&lt;br /&gt;Enter the Symbolic Link. Microsoft has provided a feature called a symbolic link. A symbolic link allows you to make one directory available at multiple locations in your directory tree. Unix afficionatos will recognize this feature. Unfortunately, there is no built-in way to actually create these links. Do not confuse these with "Shortcuts". Lets say that I have folders "C:\iTunes", "C:\Aaron", and "C:\Daniel". If I create a symbolic link of the "C:\iTunes" directory under both the Aaron and Daniel folders, I will have paths "C:\iTunes", "C:\Aaron\iTunes", and "C:\Daniel\iTunes" that all have the same space on my disk. Or in other words, if I were to put a coniguration file in any of those directories, they would all be the same file, albeit with three different ways to access that one file. &lt;br /&gt;&lt;br /&gt;That is exactly what I did. On my server, I created a symbolic link for the iTunes directory (with the config and database files) in each of the users "my Music" folders. That configuration file says that the "iTunes Music" folder is located in my M: drive. You just have to give all users full access to the directory.&lt;br /&gt;&lt;br /&gt;Now, whenever any user adds music, all the users configuration files are updated and there is only one copy of the music.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-114425936567619898?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/114425936567619898/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=114425936567619898' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/114425936567619898'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/114425936567619898'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2006/04/apple-corebaltimorewhos-your-friend.html' title='Apple Core...Baltimore...Who&apos;s your friend?'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-114045334296414655</id><published>2006-02-20T09:33:00.000-07:00</published><updated>2006-02-20T09:36:52.603-07:00</updated><title type='text'>Master and Commander</title><content type='html'>I just thought I'd put my favorite registry hack here. Create a text file with a .reg extension with this text:&lt;br /&gt;&lt;blockquote&gt;Windows Registry Editor Version 5.00&lt;br /&gt;&lt;br /&gt;[HKEY_CLASSES_ROOT\Directory\shell\Command]&lt;br /&gt;@="Command &amp;Prompt"&lt;br /&gt;[HKEY_CLASSES_ROOT\Directory\shell\Command\command]&lt;br /&gt;@="cmd.exe"&lt;/blockquote&gt;&lt;br /&gt;Once you have the file saved, just double-click it and merge it with the registry. This adds a context menu that can be used in the explorer to open a command prompt window to the highlighted folder.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-114045334296414655?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/114045334296414655/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=114045334296414655' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/114045334296414655'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/114045334296414655'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2006/02/master-and-commander.html' title='Master and Commander'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-113813237196423092</id><published>2006-01-24T12:49:00.002-07:00</published><updated>2010-01-22T14:30:28.652-07:00</updated><title type='text'>How to skin a Turkey</title><content type='html'>Here is a very useful function created to parse a delimited list in TSQL. It is fairly straight forward. Pass the string to be parsed and the delimiter (defaults to a comma) and it returns a table with a single column containing the strings that were delimited together. Why Microsoft doesn't have something like this built in is beyond me.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: sql"&gt;CREATE FUNCTION dbo.fn_ParseDelimitedList&lt;br /&gt;(&lt;br /&gt;@DelimitedList varchar(8000),&lt;br /&gt;@Delimiter char(1) = ","&lt;br /&gt;)&lt;br /&gt;RETURNS @TableVar TABLE (Item varchar(100) NOT NULL ) &lt;br /&gt;AS&lt;br /&gt;BEGIN&lt;br /&gt;DECLARE @IDListPosition int &lt;br /&gt;DECLARE @IDList varchar(8000)&lt;br /&gt;DECLARE @ArrValue varchar(8000) &lt;br /&gt;DECLARE @Pattern char(3)&lt;br /&gt;SET @IDList = COALESCE(@DelimitedList, '') &lt;br /&gt;IF @IDList &lt;&gt; '' &lt;br /&gt;BEGIN &lt;br /&gt;-- Add Trailing delimiter to end of list so user doesn't have to &lt;br /&gt;IF RIGHT(@DelimitedList,1) &lt;&gt; @Delimiter&lt;br /&gt;begin&lt;br /&gt;SET @IDList = @IDList + @Delimiter &lt;br /&gt;END&lt;br /&gt;&lt;br /&gt;SET @Pattern = '%' + @Delimiter + '%'&lt;br /&gt;-- Loop through the comma demlimted string list &lt;br /&gt;WHILE PATINDEX(@Pattern , @IDList ) &lt;&gt; 0 &lt;br /&gt;BEGIN &lt;br /&gt;SELECT @IDListPosition = PATINDEX(@Pattern , @IDList) &lt;br /&gt;SELECT @ArrValue = LEFT(@IDList, @IDListPosition - 1) &lt;br /&gt;-- Insert parsed ID into TableVar for "where in select"&lt;br /&gt;INSERT INTO @TableVar (Item) VALUES (@ArrValue) &lt;br /&gt;-- Remove processed string &lt;br /&gt;SELECT @IDList = STUFF(@IDList, 1, @IDListPosition, '') &lt;br /&gt;END &lt;br /&gt;END&lt;br /&gt;RETURN &lt;br /&gt;END&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-113813237196423092?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/113813237196423092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=113813237196423092' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/113813237196423092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/113813237196423092'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2006/01/how-to-skin-turkey.html' title='How to skin a Turkey'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-113157043127877273</id><published>2005-11-09T13:56:00.000-07:00</published><updated>2005-11-11T11:08:06.933-07:00</updated><title type='text'>You liquidated her, eh? Very resourceful...</title><content type='html'>Long time, no blog. What can I say? I've been to the "Happiest Place On Earth"&lt;br /&gt;&lt;br /&gt;But, now that I'm back, here's a neat little trick that I learned about how to embed and use graphic resources in a Visual Studio .NET application. For my example, I'm assuming that I have an icon file named "Test.ico".&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Using visual studio or another tool, you can create a bitmap, jpeg, gif, or Icon. &lt;/li&gt;&lt;li&gt;Put that file in the same directory as the rest of your project. &lt;/li&gt;&lt;li&gt;Then Add the file to the project (Add Existing Item...) and add the file. &lt;/li&gt;&lt;li&gt;Change the Build Action of the file to be "Embedded Resource"&lt;/li&gt;&lt;li&gt;When you want to use the file, simply add the following code (or something similar):&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;Dim _icon as Icon = New Icon(Me.GetType(),"Test.ico")&lt;/span&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;br /&gt;Now you have a real icon that can be used for any number of things (application icon, status icon, etc.)&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-113157043127877273?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/113157043127877273/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=113157043127877273' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/113157043127877273'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/113157043127877273'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2005/11/you-liquidated-her-eh-very-resourceful.html' title='You liquidated her, eh? Very resourceful...'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-112983020813881341</id><published>2005-10-20T11:31:00.000-06:00</published><updated>2005-10-20T11:43:28.143-06:00</updated><title type='text'>Am I Blue?</title><content type='html'>&lt;a href="http://photos1.blogger.com/blogger/2772/1592/1600/Blue2.jpg"&gt;&lt;img style="FLOAT: right; MARGIN: 0px 0px 10px 10px; CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/2772/1592/320/Blue2.jpg" border="0" /&gt;&lt;/a&gt;Just a quickie post with a picture for those of you who may not know what I look like. Actually, you still won't know what I look like because this was my Halloween 2005 costume. A "Blue Man"&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/2772/1592/1600/Blue1.jpg"&gt;&lt;img style="FLOAT: right; MARGIN: 0px 0px 10px 10px; CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/2772/1592/320/Blue1.jpg" border="0" /&gt;&lt;/a&gt;&lt;a href="http://photos1.blogger.com/blogger/2772/1592/1600/Blue3.jpg"&gt;&lt;img style="FLOAT: right; MARGIN: 0px 0px 10px 10px; CURSOR: hand" alt="" src="http://photos1.blogger.com/blogger/2772/1592/320/Blue3.jpg" border="0" /&gt;&lt;/a&gt; This whole effect was accomplished using simple make-up items from "The Costume Shop" in Garden City, Idaho.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;I prepped myself with a good shave and a haircut&lt;/li&gt;&lt;li&gt;The skin-head wig was prepared using Caster Sealer. This helped it to have a less streaky appearance than it would have had otherwise. This is bascally castor oil, but it makes the latex skin less slippery.&lt;/li&gt;&lt;li&gt;I positioned the skin-head over my hair and ears and then glued it in place with stage glue. &lt;/li&gt;&lt;li&gt;We applied Cobolt Blue Greasepaint to my entire head and neck.&lt;/li&gt;&lt;li&gt;I'm wearing a black turtleneck shirt with black pants, shoes and socks.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The entire process took about an hour.&lt;/p&gt;&lt;p&gt;Total cost: $20&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-112983020813881341?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/112983020813881341/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=112983020813881341' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/112983020813881341'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/112983020813881341'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2005/10/am-i-blue.html' title='Am I Blue?'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-112897800759499401</id><published>2005-10-10T14:55:00.000-06:00</published><updated>2005-10-10T15:00:07.600-06:00</updated><title type='text'>Loss of Focus</title><content type='html'>It would appear that the venerable GDI routine "DrawFocusRect" and the MFC routine "DrawFocusRectangle" have lost a bit of functionality in their .net contemporary function "DrawFocusRectangle". &lt;br /&gt;In the old world, you could draw the focus rectangle once to draw it, and then again to erase it because it uses an XOR pen to draw the familiar dashed box. Under the .net version "ControlPaint.DrawFocusRectangle", it doesn't use an XOR pen, so you can't erase it with another call. &lt;br /&gt;There is a function called "DrawReversableFrame", that will erase itself, but it doesn't take a parameter containing the graphics object, so you have to manually transform the coordinates to screen coordinates.&lt;br /&gt;A change like this is really not very understandable because it means that somebody had to create a function from scratch rather than wrapping the windows functions (as they did most of the time).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-112897800759499401?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/112897800759499401/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=112897800759499401' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/112897800759499401'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/112897800759499401'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2005/10/loss-of-focus.html' title='Loss of Focus'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-112895957771507487</id><published>2005-10-10T09:48:00.000-06:00</published><updated>2005-10-10T09:58:57.963-06:00</updated><title type='text'>Brent: Programmer. Gamer. Cheapskate. All around good guy.</title><content type='html'>So... not being one that can leave a sore spot alone, when Brent Brown sent me an email &lt;a href="http://brentbrown.org"&gt;Brent&lt;/a&gt; his "preferred" blog link so that I could update the link I had created to &lt;a href="http://brentbrown.org/Stubenville/"&gt;Stubenville&lt;/a&gt;, I naturally couldn't just update my previous blog entry. I needed to take the opportunity to pour lemon juice, salt, and vinegar into the wound until it became a pulp of agonized flesh. It may be because that's the way I am, but it may also be because Brent really needs this kind of opposition in his life. After all, he has a wonderful wife and cute kids, but as far as I can see, nobody that really gives him the harassing that he needs to keep his life in balance. That's where I come in.&lt;br /&gt;I don't know what the big deal is... after all, I liked the Stubenville (not Stupid-ville, that's a whole other wound that needs opening from time to time) thread. However, since he isn't there any more, I suppose that it has a limited shelf life. So, if &lt;em&gt;anyone&lt;/em&gt; actualy reads my blog, you should also read &lt;a href="http://brentbrown.org"&gt;his&lt;/a&gt; because he has far more time on his hands to talk about cool stuff like the "Using" statement in C# and dot net 2.0.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-112895957771507487?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/112895957771507487/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=112895957771507487' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/112895957771507487'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/112895957771507487'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2005/10/brent-programmer-gamer-cheapskate-all.html' title='Brent: Programmer. Gamer. Cheapskate. All around good guy.'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-112682302270749723</id><published>2005-09-15T16:04:00.000-06:00</published><updated>2005-09-15T16:23:42.713-06:00</updated><title type='text'>(Tool)Band Aid</title><content type='html'>So, I recently completed writing a Desk band for windows. &lt;strong&gt;What&lt;/strong&gt; is a desk band, you ask? Well, your windows start bar is the home for several desk band objects. These are basically COM objects that support a bunch of interfaces and register themselves in appropriate places so that windows knows to load them.&lt;br /&gt;&lt;br /&gt;In short, you register your windows class and it gets put in the toolbar. Nearly the same code can work in multiple places in IE, Explorer, and in the Start Bar. So, I learned a few lessons:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It is far easier to do your initial development so the band will work in the IE toolbar than in the start bar. This lets just run the COM object (and automatically start IE) rather than manually starting up the desk band, and attaching to the Explorer process. When you get most of what you need done, you can test it in the Start bar. &lt;/li&gt;&lt;li&gt;A conditional compilation switch in your code will make sure that you don't accidentally register the release version of your desk band object to run in IE (if you don't intend it to).&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So, I based my deskband on the sample SDK code from Microsoft. But it has a few problems.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;It registers fine. The normal "regsvr32 myobj.dll" works great, but it doesn't implement any &lt;strong&gt;unregister&lt;/strong&gt; functions. You have to write those yourself. Now, I know that if you use ATL or MFC that you can get that for basically free, but it seems a bit of an overkill if you are doing just a small simple COM object. And besides, you have to do custom registration for it to get loaded automatically anyway.&lt;/li&gt;&lt;li&gt;The window with the text is kind of ugly. I really wanted a desk band that didn't have a big square box. &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So, here's what I did to get rid of the box...&lt;/p&gt;&lt;p&gt;First of all, I registered the window class with a background color of NULL. That way, it won't automatically erase the background with blue. I also changed the flags so that there isn't a black border around the window contents.&lt;/p&gt;&lt;p&gt;The next thing I did was implement a handler for the Erase method that windows will call whenever the window needs to be erased. MSDN says that you should do this. If you don't do this, you'll get text that writes on top of itself over and over, works fine until your text changes. Then it looks like some kid scribbled on the screen. But at least you have the same background that the toolbar has. (there &lt;em&gt;are &lt;/em&gt;some people that don't use the blue jelly toolbar, they must like grey).&lt;/p&gt;&lt;p&gt;So, how do we keep the nice gradient, or the grey background, or whatever they have as a background while we're drawing on it all the time? StretchBitBlt. Enough said. &lt;/p&gt;&lt;p&gt;... What? That wasn't enough said?&lt;/p&gt;&lt;p&gt;Ok, so here's what I did. realizing that the gradient is vertical, when my erase event gets invoked, I just stretch bit blit whatever is on the left hand side of the draw window all the way across my drawing rect. Then, I text out on top of that. It's easy once you figure it out.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-112682302270749723?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/112682302270749723/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=112682302270749723' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/112682302270749723'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/112682302270749723'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2005/09/toolband-aid.html' title='(Tool)Band Aid'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-112672185827159364</id><published>2005-09-14T10:44:00.000-06:00</published><updated>2005-09-14T16:27:09.540-06:00</updated><title type='text'>Windows XP ala' Burger King (have it your way)</title><content type='html'>I got my Shuttle SN25P XPC on Monday from NewEgg and immediately put it together. The components that I had delivered with it are:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;AMD Athlon X2 64 3800+ processor&lt;/li&gt;&lt;li&gt;2 GB Crucial pc-3200 memory (2x 1GB)&lt;/li&gt;&lt;li&gt;Samsung SATA2 250 GB drive&lt;/li&gt;&lt;li&gt;Gigabyte Nvidia GeForce 6600GT 128 MB video card&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Then I spent most of the evening installing Windows XP, service packs, and all kinds of hot fixes. Not to mention the drivers needed by my machine (like everything!) Well, to make a long story short, the UN-service packed version of XP doesn't recognize drives over 130 GB or so, so it formatted the drive smaller than it should have been. So now I'm faced with resizing the drive with partition magic or something similar.&lt;/p&gt;&lt;p&gt;I could have saved myself a lot of time using the following utilities and programs:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://unattended.msfn.org/index.htm"&gt;Unattended XP CD&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.nliteos.com/"&gt;nLite&lt;/a&gt; - Tool for slipstreaming and customizing windows installations&lt;/li&gt;&lt;li&gt;&lt;a href="http://ryanvm.msfn.org/updatepack.html"&gt;RyanVM's Windows XP Post-SP2 Update Pack&lt;/a&gt; - latest hotfixes all together in one install or separately&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.driverpacks.net/"&gt;DriverPacks &lt;/a&gt;- up-to date drivers for slipstreaming, by category&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The Unattended XP CD link has links to everything else that you need, but also is a good reference by itself. However, for casual use, I recommend just using nLite's options along with your own Windows XP sp2 CD and RyanVM's update pack and the DriverPacks. &lt;/p&gt;&lt;p&gt;And of course, once you have minimized the size of the installation, you can also install it from a USB memory stick using a &lt;a href="http://h18007.www1.hp.com/support/files/hpcpqdt/us/download/20306.html"&gt;free utility &lt;/a&gt;from HewlettPackard&lt;/p&gt;&lt;p&gt;Most excellent!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-112672185827159364?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/112672185827159364/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=112672185827159364' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/112672185827159364'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/112672185827159364'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2005/09/windows-xp-ala-burger-king-have-it.html' title='Windows XP ala&apos; Burger King (have it your way)'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-16697217.post-112664092160448013</id><published>2005-09-13T13:36:00.000-06:00</published><updated>2005-10-10T09:47:31.663-06:00</updated><title type='text'>Jack of all trades...</title><content type='html'>I guess if &lt;a href="http://brentbrown.org"&gt;Brent can do it&lt;/a&gt;, so can I. After much coaxing and goading, I am going to keep a blog of cool stuff that I figured out. This is not so much a vanity site, I really don't believe that anyone will read what I have to say as it is my anti-altzheimers mechanism of choice.&lt;br /&gt;Or, to put it another way...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;"Cool. Why don't you put that in a blog so that when I ask you how you did it a year from now you won't just give me a blank expression" - Brent&lt;/span&gt; &lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;span style="font-size:0;"&gt;&lt;/span&gt;&lt;p&gt;&lt;span style="font-size:0;"&gt;Oh, yea, and Scott has said almost the same thing from time to time. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Now, for those of you who don't know me... What are &lt;strong&gt;you&lt;/strong&gt; doing here? You must &lt;em&gt;really&lt;/em&gt; be bored.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/16697217-112664092160448013?l=andmasterofnone.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://andmasterofnone.blogspot.com/feeds/112664092160448013/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=16697217&amp;postID=112664092160448013' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/112664092160448013'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/16697217/posts/default/112664092160448013'/><link rel='alternate' type='text/html' href='http://andmasterofnone.blogspot.com/2005/09/jack-of-all-trades.html' title='Jack of all trades...'/><author><name>Aaron D. Wells</name><uri>http://www.blogger.com/profile/10529970353511545763</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
