
<rss version="2.0">
	<channel>
		<title>KeyLimeTie RSS Feed</title>
		<link>http://keylimetie.com</link>
		<description>KeyLimeTie RSS Feed</description>
		<language>en-us     </language>
		<image id="_image">
			<title>KeyLimeTie</title>    
			<link>http://www.keylimetie.com/Blog/</link>
			<url>http://www.keylimetie.com/Common/Images/custom/KLT-Logo.gif</url>
			<width>220</width>
			<height>80</height>
		</image>
		
				<item>
					<title>KeyLimeTie visits the Illinois Institute of Technology KnappLab</title> 
					<link>http://keylimetie.com/blog/2010/3/9/keylimetie-visits-the-illinois-institute-of-technology-knapplab/</link> 
					<description><![CDATA[
On February 5, Peter Morano, Chris Grove and I attended the launch reception for the KnappLab at the Illinois Institute of Technology.  The Knapp Center, headed by Nik Rokop, has built out a mobile development lab to teach students how to develop real-world mobile applications.  The lab practices what it preaches; even the Lab's web site is a mobile site. 



At the KnappLab, students have access to two Macs and one Windows machine fully equipped with development environments for iPhone, Android, Blackberry, and Windows Mobile.  They have the chance to work on student projects or projects entrepreneurs bring to them.



We're excited to see a leading university make such an investment in young mobile app developers.  These students certainly have an open door at KeyLimeTie when they're looking for internships or full-time positions doing the work they love.



Here's a video we took giving a quick tour of the KnappLab:




]]></description> 
					<pubDate>Tue, 09 Mar 2010 21:56:07 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2010/3/9/keylimetie-visits-the-illinois-institute-of-technology-knapplab/</guid>
				</item>
			
				<item>
					<title>SocialDevCamp Chicago Video Highlights</title> 
					<link>http://keylimetie.com/blog/2010/3/7/socialdevcamp-chicago-video-highlights/</link> 
					<description><![CDATA[
In November of last year, KeyLimeTie sponsored the second annual SocialDevCamp conference in Chicago, co-produced by our very own Tim Courtney.  The event covers both  technical and business, strategic and cultural elements of developing social applications on the Internet, a significant part of KeyLimeTie's business.



The conference attracted notable speakers including David Recordon and Luke Shepard of Facebook, Harper Reed, Chris McAvoy, Blagica Bottigliero, Daliah Saper, and John R. Dallas, Jr.



KeyLimeTie CIO Peter Morano also led the developer Hackathon component of SocialDevCamp, a contest offering $2,000 in prizes to developers competing to build the best social applications over the course of the weekend.



Enjoy these video highlights from SocialDevCamp 2009.  We're happy to have had the opportunity to partcipate in the event.




]]></description> 
					<pubDate>Sun, 07 Mar 2010 22:19:55 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2010/3/7/socialdevcamp-chicago-video-highlights/</guid>
				</item>
			
				<item>
					<title>Pop&amp;quot;s Italian Beef &amp;amp; Sausage is fresh on the web with a side of KeyLimeTie</title> 
					<link>http://keylimetie.com/blog/2010/3/5/pops-italian-beef-sausage-fresh-with-side-of-keylimetie/</link> 
					<description><![CDATA[






Legendary Chicago and suburban sandwich shop Pop's Italian Beef & Sausage came to KeyLimeTie when the company needed a new web site.  They wanted a site that visually communicated the BIG taste of their adored sandwiches, and KeyLimeTie served up just what they ordered.



The new Pop's Italian Beef site proudly displays their classic features bold visuals with their featured items and provides an updated motif around their classic logo, bringing Frank Radochonski's vision up-to-date on the web.  As fans of Pop's Italian Beef ourselves, we're thrilled with the opportunity to give them a fresh look online.
]]></description> 
					<pubDate>Fri, 05 Mar 2010 21:46:15 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2010/3/5/pops-italian-beef-sausage-fresh-with-side-of-keylimetie/</guid>
				</item>
			
				<item>
					<title>Three Tech Events Next Week: SocialDevCamp Party, MobileX Chicago, and Day of Mobile</title> 
					<link>http://keylimetie.com/blog/2010/2/24/socialdevcamp-party-mobilex-chicago-and-day-of-mobile/</link> 
					<description><![CDATA[
KeyLimeTie is sponsoring both the SocialDevCamp TechThursday Mashup Party and the Day of Mobile conference next week.  We also recently learned of a second Mobile event for entrepreneurs and developers; MobileX Chicago. If you're in the area and interested in social applications and mobile development, you'll want to add these events to your calendar.

SocialDevCamp TechThursday Mashup Party
Thursday March 4, 6-9pm, OfficePort CHI






Organizers of the annual SocialDevCamp Conference (including KeyLimeTie's Tim Courtney and Peter Morano) are hosting an after-hours party for attendees to mingle, re-connect, see video highlights and hear from Hackathon teams who have continued developing the applications they built at the 2009 conference into something bigger.


KeyLimeTie is sponsoring the party.  Food and drinks will be provided, and a $5.00 cover charge will be donated to the YWCA TechGYRLS program, an innovative, after-school programs are designed to broaden girls' knowledge and interest in science, technology, engineering, and mathematics fields.



RSVP for the SocialDevCamp TechThursday Mashup Party Here.


MobileX Chicago
Friday March 5, 9:00am - 6:00pm, Doubletree Hotel






MobileX Chicago is a one-day conference aimed at entrepreneurs, developers, investors, industry professionals, and mobile enthusiasts.  It features four tracks of breakout sessions for the target audiences and topics of  “Mobile Developers”, “Entrepreneurs/Investors/Enthusiasts”, and “Mobile Marketing," along with an introductory iPhone development track.


Learn more and register to attend on the MobileX Chicago web site.

Day of Mobile
Saturday March 6, 8:00am - 6:00pm, Illinois Institute of Technology






Day of Mobile will focus on iPhone, Android, Blackberry, and Windows Mobile development.  Jay Freeman, creator of the Cydia Store will keynote, and KeyLimeTie's Chris Grove will present on "Strategies for multi-platform applications."  KeyLimeTie's Peter Morano is heading the Developer Hackathon, and the company is sponsoring Day of Mobile.


Learn more and register to attend on the Day of Mobile web site.

]]></description> 
					<pubDate>Wed, 24 Feb 2010 17:30:06 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2010/2/24/socialdevcamp-party-mobilex-chicago-and-day-of-mobile/</guid>
				</item>
			
				<item>
					<title>ScaleWell Grant Offers New Way to Look at Investing in Your Business</title> 
					<link>http://keylimetie.com/blog/2010/2/10/scalewell-grant/</link> 
					<description><![CDATA[






Are budgets tight at your company?  Many places they are.  Whether you're a Fortune company or a bootstrapped entrepreneur, chances are you have a list of things that you need and are holding off on purchasing something you need to grow your business.



ScaleWell, a new quarterly grant given by entrepreneurs for entrepreneurs, aims to change the way companies look at what it takes to gain traction for one's business.  By giving away $1000 per quarter (no strings attached) to one company, ScaleWell is encouraging companies to look at ways to grow by funding their experience.  According to the ScaleWell web site, it's a way to enable the recipient to answer questions like 'How many customers I acquire for $1000?' or 'How much closer to profitability can I get by investing this small amount?'



Moreover, the buzz ScaleWell is generating in the Chicago business community, the region KeyLimeTie calls home, can serve to inspire you no matter your role--whether you are a solo entrepreneur or an executive at a large company.  Take a fresh look at the how you can grow or improve by investing a small, finite amount of money to fund an action or make a purchase that will gain you traction.  Once you're done, measure the results.  Whether this particular experiment succeeds or fails, you're learning along the way and taking positive steps forward.



ScaleWell was founded by Andy Angelos, Ziad Hussain, and Sean Corbett--each entrepreneurs looking to scale their own businesses while helping others do the same.  ScaleWell is funded by Trustees; Trustees each donate $100 and volunteer to advise the grant recipient.  Trustees decide on the award recipient from applications received each quarter.



KeyLimeTie came to support ScaleWell through CIO Peter Morano.  Internally, Pete has been instrumental in applying similar ideas through the KeyLimeTie Labs innovation group, and saw this as an opportunity to lend support to another business in the larger community.



How could you scale your business by investing $1000?  You don't have to be a ScaleWell recipient to do this.  The budget constraint makes it realistic to think and act this way.  With $1000, here are some of the things you could do to scale:



Video camera to take videos and share online to attract more customers.
Purchase costly software or hardware that would enable you to do more, or increase efficiency.
Invest in a graphic design for your company or product that improves your presentation and allows you to sell more.
Build enhancements to your web site, or purchase hosting for a new web site for a year.
Hire a C-Level consultant to work with you on strategic alignment within your company or group.
Sponsor an event that will gain you exposure and put you on the map in a market or a community.



How will you scale your business well?  KeyLimeTie wants to know.  Leave a comment below!




Update: The first ScaleWell grant was given to Michael Una for his business, Unatronics, that sells handmade electronic musical instruments.  He will use the grant money to develop additional products he can sell.
]]></description> 
					<pubDate>Wed, 10 Feb 2010 16:45:50 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2010/2/10/scalewell-grant/</guid>
				</item>
			
				<item>
					<title>Apple&amp;quot;s iPad Opens Opportunities for New Applications and Interactions</title> 
					<link>http://keylimetie.com/blog/2010/1/29/apple-ipad-opens-opportunities/</link> 
					<description><![CDATA[




Wednesday's much anticipated iPad tablet device appears to be, at first glance, a scaled-up version of the iPhone.  By releasing the iPad, Apple is carving out a new category of device, and a new way people will interact with computers.  Over the past ten years, there have been many unsuccessful attempts at building a widely-adopted tablet PC, so of course there is skepticism.



It would be easy to dismiss this device as nothing special, before considering how the App Store made the iPhone and the iPod Touch into the outstandingly popular devices they are today.  At this point, we've just seen what Apple (and a select group from the developer community) have done with the iPad.  The real applications are yet to come, thanks to the limitless creativity of the iPhone&mdash;and now iPad&mdash;developer community, including companies like KeyLimeTie.



Further, industry reporters like TechCrunch's MG Seigler explain why the iPad will succeed; its target audience is the 75 million iPhone and iPod Touch users.  These people will know how to use the iPad right out of the gate.



Those people will also grow more and more accustomed to a web you can touch, with full web pages now practical on the iPad screen and people used to pinching and swiping their way around your site, making purchases, downloading documents, playing games, writing comments.  The web as we know it will evolve, interaction design will shift, as the iPad and other tablets capture our share of screen time.



Many people will opt to leave the laptop at home and use the iPad for communications, eBook reading, entertainment, and even productivity when larger screens and computing power aren't required.  But, imagine for a moment a restaurant menu displayed on an iPad, or iPads being used to process transactions in a retail store.  That, of course, is just the start.



Here are some others' thoughts on the iPad's viability:



TechCrunch: Top 10 Reasons The Apple iPad Will Put Amazon’s Kindle Out of Business
Arun Shroff: Top 10 Reasons Why the iPad will NOT Kill the Kindle
TechCrunch: The iPad Is Like Holding The Future. But Only Because I Graduated From iPhone School
TechCrunch: Pictures: The iPad Being Manhandled



Like what we have to say?  Follow @KeyLimeTie on Twitter or join our Facebook fan page for continued updates.
]]></description> 
					<pubDate>Fri, 29 Jan 2010 17:16:02 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2010/1/29/apple-ipad-opens-opportunities/</guid>
				</item>
			
				<item>
					<title>How to &quot;Pull a Groupon&quot; and make more of your existing business</title> 
					<link>http://keylimetie.com/blog/2010/1/25/how-to-pull-a-groupon/</link> 
					<description><![CDATA[




This past weekend I attended a lunch presentation by Andrew Mason of Groupon, which he gave to participants in the Chicago Urban League's NextONE Program.  I was invited by great friend John (JR) Dallas and welcomed by the Urban League staff.



Groupon, if you are not familiar, is widely regarded as Chicago's biggest tech success story of 2009.  The web site allows people to buy one steeply discounted offer each day, provided enough other people also buy the offer so the retailer has a critical mass of new customers.  They achieved profitability in the spring of 09 and closed on $25mm of funding late last year, when they admittedly didn't need the money.  Now they're on target for $100mm in revenues in 2010.



It would be too easy to romanticize the above.  Mason and team came up with an idea, coded it in a month, and it became a runaway success.  But just looking at their history as Groupon would be denying some important lessons about innovation and persistence.




ThePoint.com: Groupon's predecessor.



Before Groupon was (and still is) a web site called The Point, which Mason started in 2006.  The Point was built to allow people to achieve critical mass on a political or social issue before taking action, to ensure the action they take (a donation, a protest, a mass action, etc) had an impact.  The site itself didn't take off to the founders' expectations because of a lack of focus; they were providing a platform for an undefined audience to take action on any potential issue.



The software and concept that powered The Point now powers Groupon.  In late 2008, the team worked for a month to get the product off the ground, with very limited features and simple e-commerce capabilities, and the new, focused idea stuck.



Among many others, I was able to pull these lessons from Andrew's talk and knowing the Groupon story:



They weren't afraid to act, try something different, and risk failure.  Groupon was a 30-day diversion from working on The Point.  If it failed, they wouldn't be out a lot of time, money, or emotional investment.
They took an existing asset, the software engine powering The Point, and applied it in a different way.  They learned that this new application had considerably more monetary value than the original.
Mason and the team continually improve Groupon by creating a product they themselves want to use, and add features and improvements based upon problems they themselves have.  Their philosophy, 'If I have this problem, chances are someone else does, too.'



Take a look inside your business as we take a look inside ours.  Do you have the opportunity to 'Pull a Groupon?'  Perhaps you have software systems that are built for one purpose that you could refactor for a different one, or maybe you could deliver your services to a completely new audience.  Chances are you are creating a product or service right now that could either make better use of by-products created or could be applied in a completely different way.



If this article strikes a chord with you, please let us know in the comments.  If you see successes from 'pulling a Groupon,' please let us know (and Groupon too, I'm sure they'd appreciate it)!  Finally, if there is an opportunity for KeyLimeTie to assist developing the software needed for you to accomplish your goals, please drop us a line.
]]></description> 
					<pubDate>Mon, 25 Jan 2010 16:28:14 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2010/1/25/how-to-pull-a-groupon/</guid>
				</item>
			
				<item>
					<title>How the Haiti SMS fundraiser became a tipping point for text campaigns</title> 
					<link>http://keylimetie.com/blog/2010/1/22/how-the-haiti-sms-fundraiser-became-a-tipping-point-for-text-campaigns/</link> 
					<description><![CDATA[




In the aftermath of the Haiti earthquake last week, amidst the rescue effort headlines, is a robust discussion in the digital marketing industry around the power of text message campaigns to quickly mobilize people while creating an audience.  At one week after the earthquake, the American Red Cross's text message (SMS) campaign alone has raised over $24 million dollars for the relief effort.



The simple campaign asks people to text the word 'Haiti' to short code 90999.  Once the user answers the confirmation message, a $10 charge is added to their mobile bill that month.  After you confirm, you're again prompted; this time, asking if you would like to receive Red Cross alerts straight to your mobile phone.



That's right.  The Red Cross raised $24 million dollars in one week from 2.4 million individual $10 donations by people with mobile phones.  Why did it work?  The message got out when the disaster was getting the most coverage and offered donors instant gratification in donating via an unprecedentedly simple method.



The campaign itself is viral because it's short, timely, memorable, and actionable.  You can easily tell someone 'Text 'Haiti' to 90999 to donate $10 to the relief effort' in a text message, tweet, status update, a phone call, or an email.  Using text and social networking technology, the message has potential to spread exponentially, and this one did.  As a result, expect to see more charities and relief agencies using SMS for fundraisers when time is of the essence.



The larger lesson for businesses amidst the tragedy that prompted the campaign is great.  Text messaging campaigns have taken the 'impulse buy' and freed it from the four walls of a retail store.  Now people can respond to an ad campaign, make a quick purchase, or make a quick donation right where they are, with the same convenience of chatting with a friend.



Further, you can build opt-in lists and notify people of promotions, sales, or send news alerts that will reach them instantly in the future.  Many short code providers have CRM systems so you can manage customer relationships and even integrate their text profiles with their online profiles in your main e-commerce or CRM system.



While SMS short codes have been around for years, the tragedy in Haiti is being marked by the industry as an event that has now proven the critical mass--and the effectiveness--of SMS response campaigns.  If you are curious about ways your business can utilize short codes and integrate them with the rest of your digital strategy, talk to KeyLimeTie.  Or, if you'd like to read up on short codes, see this informative article on GigaOM.
]]></description> 
					<pubDate>Sat, 23 Jan 2010 00:01:41 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2010/1/22/how-the-haiti-sms-fundraiser-became-a-tipping-point-for-text-campaigns/</guid>
				</item>
			
				<item>
					<title>What Google&amp;quot;s Local &amp;amp; Mobile Search Push Means to Your Small Business</title> 
					<link>http://keylimetie.com/blog/2010/1/20/what-googles-local-mobile-search-push-means-to-your-small-business/</link> 
					<description><![CDATA[




Last week I found this decal on a store front while in San Francisco.  After searching the web to learn about the program, I learned Google is focusing more and more on local business and location-based search as a new revenue stream, and improving how companies advertise their businesses.



Google launched a pilot program where they sent out 100,000 of these window decals to the most popular local businesses listed on their web site.  The stickers contain a QR code (short for 'Quick Response') so passersby can snap a quick photo of the code and visit the Google Local listing for that company.  There they can find business information and aggregated reviews.



This helps people learn more about the businesses they walk by every day.  They might find a copy shop or a caf&eacute;, and be able to see what others think about the place before they buy.  Or, they could save information about a location for later, or share with a friend, by sharing the local search link that comes up in their phone's browser.




Google Local result for QR code.



What does this mean for small businesses?  It means people will be looking up your company more and more on their phones.  Here are two excellent ways to ensure they get the best information they can about you:



Sign up for and update your Google Local Business Center listings to add custom information to your local search listings, including local coupons.  Use this also to analyze who is searching for your business and where they are located, to aid in your marketing efforts.

Make sure your web site is mobile-optimized.  The best way to do this is to have your web development firm build a mobile stylesheet for your web site.  With a mobile stylesheet, people visiting your site via their phone's browser will see all of the text and images optimized for the small browser.  Mobile web sites are specifically designed to present relevant, location- and time-sensitive information to people seeking you via their phones.



If you would like KeyLimeTie to optimize your web presence for mobile, or if you have questions about Google's Local Business Center, give me a call or reach out to @KeyLimeTie on Twitter.  We'll be happy to help.
]]></description> 
					<pubDate>Wed, 20 Jan 2010 18:11:00 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2010/1/20/what-googles-local-mobile-search-push-means-to-your-small-business/</guid>
				</item>
			
				<item>
					<title>KeyLimeTie Sponsoring, Presenting at Day of Mobile Conference on Mobile Application Development</title> 
					<link>http://keylimetie.com/blog/2010/1/18/keylimetie-sponsoring-presenting-at-day-of-mobile-conference/</link> 
					<description><![CDATA[

We’re excited to play a part in Tech in the Middle’s upcoming Day of Mobile conference, to be held at IIT on Saturday, March 6th.  The conference will feature 100 and 300 level talks running concurrently covering four development platforms; Android, iPhone, Windows Mobile, and Blackberry, along with hands-on workshops by subject matter experts.




KeyLimeTie CIO Peter Morano is coordinating Day of Mobile’s Hackathon contest, with over $3,500 in prizes that will be awarded to people who develop the best mobile apps leading up to the event.  Presentations and judging will take place following the keynote speech in the afternoon.




Also, KeyLimeTie’s Chris Grove, CTO and senior mobile application developer, will give a talk entitled “Strategies for Developing Multi-Platform Apps.”  He’ll explain how careful planning can overcome differences in frameworks, operating systems, and languages, while sharing proven strategies for cross-platform mobile development that will guide your design process and maximize your ROI.



If you’re looking to accelerate your mobile development knowledge, visit the Day of Mobile site and register for the conference.  See you there!
]]></description> 
					<pubDate>Mon, 18 Jan 2010 17:35:36 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2010/1/18/keylimetie-sponsoring-presenting-at-day-of-mobile-conference/</guid>
				</item>
			
				<item>
					<title>Google Releases NexusOne, Adds Momentum and Focus for App Developers</title> 
					<link>http://keylimetie.com/blog/2010/1/6/google-releases-nexusone-adds-momentum-and-focus-for-app-developers/</link> 
					<description><![CDATA[
Yesterday, Google boldly released the Google-branded NexusOne phone (manufactured by HTC), the closest device to date to compete with the iPhone in terms of features and flexibility.  For those looking to enter the mobile application marketplace, this adds some serious momentum to Android OS's expansion into the smartphone market.



2010 will no doubt be a year of aggressive innovation as we start to see the power shift in the mobile market from the carriers like AT&T, Verizon, and T-Mobile to carriers and manufacturers like Apple, Google, Motorola, and HTC.


While the iPhone paved the way for consumers choose a handset first before a carrier, AT&T's exclusivity in the US limited choice.  The Motorola Droid created similar demand, and remains tethered to Verizon.  Now, Google has taken the next step by making the NexusOne available either subsidized (with a 2-year T-Mobile contract) or unlocked for any network (with the expectation of adding other networks in the future).


What does this mean for companies and brands looking to get into the app market?  Greater focus on Android and iPhone as the platforms of choice.  The Android Market's 20,000 apps, along with the iPhone's 90,000+ apps far overshadow both BlackBerry's and Palm's 4,000 and 1,000 apps, respectively (source: BlackBerry App World and BillShrink).  For companies and developers looking to build apps, focus on Android and iPhone.

]]></description> 
					<pubDate>Wed, 06 Jan 2010 17:35:10 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2010/1/6/google-releases-nexusone-adds-momentum-and-focus-for-app-developers/</guid>
				</item>
			
				<item>
					<title>New iPod Touch Users &amp;amp; Android Growth Represent Opportunities for Brands</title> 
					<link>http://keylimetie.com/blog/2010/1/4/new-ipod-touch-users-android-growth-represent-opportunities-for-brands/</link> 
					<description><![CDATA[

AdMob, the mobile analytics firm acquired by Google last year for $750 million, today reported that ad requests from iPod Touch users were up 96% on December 26.  This means that a lot of new people received iPod touches this year, increasing the potential user base for iPhone and iPod Touch applications by a significant amount.



At the same time, AdMob data indicates momentum is building around Android phones as they continue to penetrate the market.  While the iPhone remains wildly more popular, growth has slowed in the US while Android trends upward.  



If you’re looking to build an application that drives engagement and revenue, the iPhone and iPod Touch will continue to represent significant opportunities for a long time to come.  However, keep an eye on Android as we are sure to see significant competition in 2010.



Interested in either iPhone or Android applications?  Give us a call at KeyLimeTie to discuss your plans.  630.598.9000.
]]></description> 
					<pubDate>Mon, 04 Jan 2010 16:57:01 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2010/1/4/new-ipod-touch-users-android-growth-represent-opportunities-for-brands/</guid>
				</item>
			
				<item>
					<title>Sloan Valve receives press for Water Savings Calculator iPhone Application by KeyLimeTie</title> 
					<link>http://keylimetie.com/blog/2010/1/4/sloan-valve-receives-press-for-water-savings-calculator-iphone-application-by-keylimetie/</link> 
					<description><![CDATA[
Last week, client Sloan Valve received press in CONTRACTORmag.com for the new Water Savings Calculator iPhone application (iTunes Link), developed by KeyLimeTie.  The article discusses ways the manufacturer is allowing facilities managers, architects, engineers, plumbers, and others to immediately estimate water usage in a building and calculate potential savings they would incur by using Sloan products.



Sloan is using the app as a part of their continued effort to position the brand as a green manufacturer, concerned with ensuring customers and end users are making the most efficient use of water resources possible.



Read the CONTRACTORmag.com article here.
]]></description> 
					<pubDate>Mon, 04 Jan 2010 15:28:34 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2010/1/4/sloan-valve-receives-press-for-water-savings-calculator-iphone-application-by-keylimetie/</guid>
				</item>
			
				<item>
					<title>Sloan Valve releases Water Savings Calculator iPhone App</title> 
					<link>http://keylimetie.com/blog/2009/11/10/sloan-valve-releases-water-savings-calculator-iphone-app/</link> 
					<description><![CDATA[

In support of their continued focus on green initiatives, Sloan Valve contracted KeyLimeTie to design and develop a Water Savings Calculator for the iPhone platform.  We’re pleased to announce the app is now available through the iTunes App Store as the team at Sloan heads to Phoenix, AZ to exhibit at the GreenBuild Conference & Expo, where former Vice President Al Gore will be delivering the keynote address.



Sloan shared with us their desire to bring this unique utility app to the iPhone so that architects, engineers, and contractors who select plumbing fixtures will be informed of the water savings—both financial and volume—that Sloan products provide over industry benchmarks.  KeyLimeTie used this information to develop a simple iPhone application that allows users to enter criteria about a building and its occupants, along with preferred Sloan fixtures.  The app then generates statistical information regarding the amount of water and money that can be saved by utilizing the selected Sloan products.



This unique mobile application makes this information easily accessible in the field, and reinforces Sloan’s position as a leader in ecological building practices.



Sloan will be exhibiting the iPhone app this week at the GreenBuild Conference & Expo.  Congratulations, Sloan, on the release.  KeyLimeTie is honored to have been a part of this project.



Click here to download the free Water Savings Calculator on iTunes.
]]></description> 
					<pubDate>Tue, 10 Nov 2009 22:24:43 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2009/11/10/sloan-valve-releases-water-savings-calculator-iphone-app/</guid>
				</item>
			
				<item>
					<title>The Secret&amp;amp;trade; Daily Teachings App selected as &amp;amp;quot;New and Noteworthy&amp;amp;quot; on the App Store</title> 
					<link>http://keylimetie.com/blog/2009/11/4/the-secret-trade-daily-teachings-app-selected-as-quot-new-and-noteworthy-quot-on-the-app-store/</link> 
					<description><![CDATA[

We’ve enjoyed watching the continued success of an iPhone app we built, 'The Secret&trade; Daily Teachings,' in the iTunes store.  Yesterday the app was selected as 'New and Noteworthy' and now appears on the App Store homepage in iTunes.



This builds upon last week's success; within 48 hours of the app's release, it rose to the #1 app within the Lifestyle section.  Now a week after release, it still rests as the #2 app in the category.  



Congratulations again to the  team at The Secret and Prime Time Productions!  We're honored to be a part of this project and looking forward to a continued partnership.
]]></description> 
					<pubDate>Thu, 05 Nov 2009 05:26:23 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2009/11/4/the-secret-trade-daily-teachings-app-selected-as-quot-new-and-noteworthy-quot-on-the-app-store/</guid>
				</item>
			
				<item>
					<title>KeyLimeTie sponsors and jumps in feet-first to SocialDevCamp Chicago 2009</title> 
					<link>http://keylimetie.com/blog/2009/11/2/keylimetie-sponsors-and-jumps-in-feet-first-to-socialdevcamp-chicago-2009/</link> 
					<description><![CDATA[

This weekend, KeyLimeTie has the distinct honor of sponsoring SocialDevCamp Chicago, an unconference being held at the Illinois Institute of Technology on November 7 & 8 for developers and marketers passionate about the software that powers social networking technology.  Having built web sites for the likes of Illinois gubernatorial candidate Adam Andrzejewski, E! News anchor Giuliana Rancic, and even niche social network GimmePleez, we have a definite interest in seeing these technologies play out so we can stay on the forefront of enabling social media on the web.


Our very own Tim Courtney started SocialDevCamp Chicago last year, and is co-chairing the event with Andy Angelos of Get Talked About.  It’s been great getting an inside peek at watching the event come together.  Peter Morano, our CTO, stepped up and has been coordinating the Hackathon developer contest running at SocialDevCamp as well (There’s even rumor of a KeyLimeTie team entering the competition, so watch out!).


The event has an impressive lineup of speakers.  Facebook’s senior open programs manager, David Recordon, is delivering the Saturday morning keynote, and Google is giving a Wave demo on Sunday morning.  Area leaders including Harper Reed, Chris McAvoy, Alex Bratton, and John R. Dallas, Jr. are covering both the technical and the business side of social applications in the afternoon sessions, and attendees who want to present will be able to self-organize and talk in the Unconference track both days as well.


If you’re a developer or a social marketer, you should attend SocialDevCamp this weekend.  There’s a lot packed into the two days, especially for a free event.  However, registration is almost full, so make sure you register if you want to attend.  Visit the SocialDevCamp Chicago web site for complete information and to register.

]]></description> 
					<pubDate>Mon, 02 Nov 2009 22:58:29 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2009/11/2/keylimetie-sponsors-and-jumps-in-feet-first-to-socialdevcamp-chicago-2009/</guid>
				</item>
			
				<item>
					<title>Early Success for KeyLimeTie iPhone application client; The Secret&amp;amp;trade; Daily Teachings</title> 
					<link>http://keylimetie.com/blog/2009/10/29/early-success-for-keylimetie-iphone-application-client-the-secret-trade-daily-teachings/</link> 
					<description><![CDATA[

We are thrilled to congratulate KeyLimeTie client Prime Time Productions, owners of the popular book and film The Secret&trade; on their early success with their new Daily Teachings iPhone application (App Store Link).  Within 48 hours of its release on October 27, the app skyrocketed to the #1 paid app in the Lifestyle category, and #49 overall!  Congrats!



KeyLimeTie was contracted to build the application, which allows users to read a daily affirmation or teaching from The Secret, highlight favorites, and share with friends.  The app also allows people to set daily alerts on their phones, reminding them to read their daily teaching.



One of our favorite features on the app is its use of the iPhone’s Push Notification service, which Apple released earlier this year through the iPhone OS 3.0.  Push notifications allow app authors to send content to users (in this case a daily reminder), which results in more engaged app users over the long term.  With brands and developers seeking ways to keep users engaged, whether to increase impressions or generate additional revenue, Push Notifications has been a welcome feature.



To power the alerts, we used our iLime service, a publicly available service for iPhone developers that enables them to easily deliver Push Notifications and In App Purchase content to their users.  For us, it ended up being the perfect synergy between our service and product businesses, an  example of what we do best.



You can purchase The Secret™ Daily Teachings on the iTunes App store at http://appsto.re/dailyteachings. 
]]></description> 
					<pubDate>Thu, 29 Oct 2009 20:49:28 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2009/10/29/early-success-for-keylimetie-iphone-application-client-the-secret-trade-daily-teachings/</guid>
				</item>
			
				<item>
					<title>Three things to prepare for Google Caffeine</title> 
					<link>http://keylimetie.com/blog/2009/9/1/three-things-to-prepare-for-google-caffeine/</link> 
					<description><![CDATA[
Google recently announced the latest version of its search engine, called “Caffeine” (a Googler friend recently told me of how they name software versions creative names, “Cupcake” is the code name for a new Android version).



For all of the buzz about Bing, Microsoft’s new search engine slowed its marketshare gains in August, growing only 0.23% from July to an August search market share of 9.65% (according to this release by StatCounter.com).  Google gained 0.29% to a total share of 77.83%.  Clearly, Google will remain the dominant force in search for a long time to come.  Stay focused on growing your rankings on Google while keeping a casual eye on Bing and Yahoo with their new search partnership.



The primary differences between the current search engine and Google Caffeine?  Speed and real-time search results, according to Andy Beal's Marketing Pilgrim article.  Now that aTwitter Search is becoming known for delivering real-time results about conversations happening right now, Google's new results will begin prioritizing current results as well.  The search giant has thrown more horses behind your search, too, with search results now coming to you up to twice as fast, according to speed tests.



Here’s what to do about Google Caffeine:



Compare your old rankings with your new ones using this comparison site ( http://www.comparecaffeine.com/search-com.php).
Read what the experts have to say about making sure your rankings stay high:


360i: 6 Things to Expect if Google Decaf Gets a “Caffeine” Boost
Mashable: Google Caffeine: A Detailed Test of the New Google
PCWorld: Google Caffeine FAQ: Your Questions Answered


Work with your SEO vendor to be sure your sites are up to date.  Even if you don’t engage them on a full project, consider hiring them for an hour to review changes you’ve made and allow them to communicate their consolidated knowledge on the topic (they read this stuff all day and use it in the field).
If you’re already a KeyLimeTie client, or if you don’t yet work with a dedicated SEO team, give us a call and ask about staying optimized for Caffeine.



Extra Credit: If you wish, you can also help Google test the new search engine by following the steps in Google’s own blog post.
]]></description> 
					<pubDate>Tue, 01 Sep 2009 16:38:55 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2009/9/1/three-things-to-prepare-for-google-caffeine/</guid>
				</item>
			
				<item>
					<title>Twitterizer Simplifies .NET Integration with Twitter</title> 
					<link>http://keylimetie.com/blog/2009/5/1/twitterizer-simplifies-net-integration-with-twitter/</link> 
					<description><![CDATA[As Twitter continues to grow in popularity, integrating your applications will become an essential step in effectively reaching a community. Fortunately, connecting your .NET applications with Twitter can be a trivial task if you use the Twitterizer Framework, a .NET 2.0 library that provides an easy to use, object-oriented interface to twitter's online API. This article and sample application will show you how to take advantage of this interface. Sample ApplicationGetting Started There are several steps required to get started:1. Register your application with Twitter: http://twitter.com/oauth_clients/new. You can skip this step, but any status posts your application makes to Twitter will appear as coming from Twitterizer. 2. Download the Twitterizer Framework:  http://code.google.com/p/twitterizer/ and add a reference in your project.Taking Control of TwitterThe Twitter API allows programmatic access to updating, searching and deleting a user’s status, adding and removing friends and followers, and direct messaging other others. The following examples show some of these operations.Establish a ConnectionTo establish a connection, you instantiate the Twitter object as shown below (If you skip step one above, you do not need to supply the Source parameter).
	function ToggleSourceCodeRegion(regionNumber)
	{
		var divRegion = document.getElementById('region' + regionNumber);
		var divRegionBlock = document.getElementById('regionBlock' + regionNumber);

		if (divRegion.style.display == 'inline')
		{
			divRegion.style.display = 'none';
			divRegionBlock.style.display = 'inline';
		}
		else
		{
			divRegion.style.display = 'inline';
			divRegionBlock.style.display = 'none';
		}
	}
                Twitter twit = null;
                twit = new Twitter("twitteruser", "twitterpwd", "app_source");Updating Your Status
	function ToggleSourceCodeRegion(regionNumber)
	{
		var divRegion = document.getElementById('region' + regionNumber);
		var divRegionBlock = document.getElementById('regionBlock' + regionNumber);

		if (divRegion.style.display == 'inline')
		{
			divRegion.style.display = 'none';
			divRegionBlock.style.display = 'inline';
		}
		else
		{
			divRegion.style.display = 'inline';
			divRegionBlock.style.display = 'none';
		}
	}
                TwitterStatus ts = twit.Status.Update("My Message");Search and Destroy
	function ToggleSourceCodeRegion(regionNumber)
	{
		var divRegion = document.getElementById('region' + regionNumber);
		var divRegionBlock = document.getElementById('regionBlock' + regionNumber);

		if (divRegion.style.display == 'inline')
		{
			divRegion.style.display = 'none';
			divRegionBlock.style.display = 'inline';
		}
		else
		{
			divRegion.style.display = 'inline';
			divRegionBlock.style.display = 'none';
		}
	}
                TwitterStatusCollection myStatus = twit.Status.UserTimeline();
                Console.WriteLine("My Status");
                foreach (TwitterStatus status in myStatus)
                {
                    Console.WriteLine(status.Text);

                    if (status.Text == "My Message")
                        twit.Status.Destroy(status.ID);
                }
                Console.WriteLine();Search for Another User’s StatusTo get the status entries for another user, you can use the TwitterParameters object, setting optional parameter values.
	function ToggleSourceCodeRegion(regionNumber)
	{
		var divRegion = document.getElementById('region' + regionNumber);
		var divRegionBlock = document.getElementById('regionBlock' + regionNumber);

		if (divRegion.style.display == 'inline')
		{
			divRegion.style.display = 'none';
			divRegionBlock.style.display = 'inline';
		}
		else
		{
			divRegion.style.display = 'inline';
			divRegionBlock.style.display = 'none';
		}
	}
                TwitterParameters paras = new TwitterParameters();
                paras.Add(TwitterParameterNames.ID, UsersID);
                paras.Add(TwitterParameterNames.Since,
                     Convert.ToDateTime("1/1/2009"));
                paras.Add(TwitterParameterNames.Page, 1);
                paras.Add(TwitterParameterNames.Count, 5);
                paras.Add(TwitterParameterNames.SinceID, 1);

                TwitterStatusCollection usersStatus =
                      twit.Status.UserTimeline(paras);

                Console.WriteLine("Status For Other User");
                foreach (TwitterStatus status in usersStatus)
                {
                    Console.WriteLine(string.Format("Status For User {0}: {1}", 
                          status.TwitterUser.ScreenName, status.Text));
                }
                Console.WriteLine();Finding Out About Your Friends (and ditching one)
	function ToggleSourceCodeRegion(regionNumber)
	{
		var divRegion = document.getElementById('region' + regionNumber);
		var divRegionBlock = document.getElementById('regionBlock' + regionNumber);

		if (divRegion.style.display == 'inline')
		{
			divRegion.style.display = 'none';
			divRegionBlock.style.display = 'inline';
		}
		else
		{
			divRegion.style.display = 'inline';
			divRegionBlock.style.display = 'none';
		}
	}
                TwitterUserCollection friends = twit.User.Friends();
                foreach (TwitterUser friend in friends)
                {
                    Console.WriteLine(friend.ScreenName.ToString());
                    Console.WriteLine(friend.Status.Text.ToString());
                    Console.WriteLine(friend.NumberOfFollowers.ToString());

                    //Remove a friend
                    friends.Remove(friend);
                }Getting Your Friend’s Status
	function ToggleSourceCodeRegion(regionNumber)
	{
		var divRegion = document.getElementById('region' + regionNumber);
		var divRegionBlock = document.getElementById('regionBlock' + regionNumber);

		if (divRegion.style.display == 'inline')
		{
			divRegion.style.display = 'none';
			divRegionBlock.style.display = 'inline';
		}
		else
		{
			divRegion.style.display = 'inline';
			divRegionBlock.style.display = 'none';
		}
	}
                paras = new TwitterParameters();
                paras.Add(TwitterParameterNames.ID, 36867666);

                TwitterStatusCollection friendsPosts =
                     twit.Status.FriendsTimeline(paras);

                Console.WriteLine("Status For Friends");
                foreach (TwitterStatus status in friendsPosts)
                {
                    if (status.TwitterUser.ScreenName != "petermorano")
                        Console.WriteLine(string.Format("Status For Friend {0}: {1}",
                              status.TwitterUser.ScreenName, status.Text));
                }Following Someone
	function ToggleSourceCodeRegion(regionNumber)
	{
		var divRegion = document.getElementById('region' + regionNumber);
		var divRegionBlock = document.getElementById('regionBlock' + regionNumber);

		if (divRegion.style.display == 'inline')
		{
			divRegion.style.display = 'none';
			divRegionBlock.style.display = 'inline';
		}
		else
		{
			divRegion.style.display = 'inline';
			divRegionBlock.style.display = 'none';
		}
	}
                TwitterUser user = new TwitterUser();
                user.ScreenName = "aplusk";
                twit.User.FollowUser(user);Locating Followers
	function ToggleSourceCodeRegion(regionNumber)
	{
		var divRegion = document.getElementById('region' + regionNumber);
		var divRegionBlock = document.getElementById('regionBlock' + regionNumber);

		if (divRegion.style.display == 'inline')
		{
			divRegion.style.display = 'none';
			divRegionBlock.style.display = 'inline';
		}
		else
		{
			divRegion.style.display = 'inline';
			divRegionBlock.style.display = 'none';
		}
	}
                TwitterUserCollection followers = twit.User.Followers();
                foreach (TwitterUser follower in followers)
                {
                    Console.WriteLine(follower.ScreenName.ToString());
                    Console.WriteLine(follower.Status.Text.ToString());
                    Console.WriteLine(follower.NumberOfFollowers.ToString());
                }Handling ErrorsThe framework also includes a TwitterizerException object that returns exception and request data from the Twitter API. Exceptions can be thrown for a number of reasons, including failure to authenticate, trying to add a friend that is already a friend, and trying to alter someone else's status. The object contains a RequestData child object that contains the details of the original request.

	function ToggleSourceCodeRegion(regionNumber)
	{
		var divRegion = document.getElementById('region' + regionNumber);
		var divRegionBlock = document.getElementById('regionBlock' + regionNumber);

		if (divRegion.style.display == 'inline')
		{
			divRegion.style.display = 'none';
			divRegionBlock.style.display = 'inline';
		}
		else
		{
			divRegion.style.display = 'inline';
			divRegionBlock.style.display = 'none';
		}
	}
            catch (TwitterizerException tex)
            {
                string message = string.Format("Exception: {0}",
                     tex.Message.ToString());
                Console.WriteLine(message);
            }Conclusion and UsesThere are a number of ways that an application can leverage the power of Twitter, such as broadcasting changes in a product's price, letting others know that you have posted a new blog, or letting a group of users know that a task is complete. And because statuses can also be read, applications can be find out when another user or application updates their status.]]></description> 
					<pubDate>Fri, 01 May 2009 13:56:26 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2009/5/1/twitterizer-simplifies-net-integration-with-twitter/</guid>
				</item>
			
				<item>
					<title>Using Firebug To Debug Web Pages</title> 
					<link>http://keylimetie.com/blog/2009/4/27/using-firebug-to-debug-web-pages/</link> 
					<description><![CDATA[Mozilla Firefox has a very powerful add-on tool called Firebug. Firebug allows web developers to inspect web pages to do such things as identify CSS styles being applied to sections of a page, easily inspect sections of a page, and to tweak style values to properly determine values for padding, font sizes, margins, and the like. Firebug is also extremely useful in tracking down and debugging layout issues on a page, especially trying to determine what style is actually being applied to a section of a page. Also, you can step-wise debug Javascript code being run by the browser.

To get started, first install Mozilla Firefox, if not already installed (http://www.mozilla.com/en-US/firefox/ie.html).  Then go to https://addons.mozilla.org/en-US/firefox/addon/1843 (using Firefox) to download and install Firebug. When done, you'll see the Firebug option in Mozilla's Tools menu. Selecting Tools -> Firebug -> Open Firebug will display the Firebug panes at the bottom of the browser:




Click on the Inspect button. Now you can mouse around the page and see the defined sections of the page (surrounded by blue border):




The lower pane will display the relevant section of the page being moused over. You can also click on the moused-over area, which selects the area (and takes you out of inspect mode). The right pane will show what styles are in effect for the selected area, and you can also mouse over the HTML section to highlight the section on the page, and can click on the HTML pane lines to see the relevant styles, including the hierarchy/cascade effect of a given style.

When an HTML line is selected, you can view and tweak the associate styles. This is very useful when debugging the page to determine both what style is (or isn't) being applied, and to determine correct values so the page is displayed as desired.




You can also disable a style setting to see its effect, by clicking to the left of the setting in the right pane (marked by a red 'do not' symbol):




Using combinations of these tweaking mechanisms and you can both easily see why a page displays and what the correct settings should be. You can also add new setting values in the right page.

Lastly, Firebug can be used to debug Javascript. You can set breakpoints, watch values, and step lines of Javascript in real-time:




In conclusion, Firebug helps to take out the guesswork in page layout and very easily shows what styles are being applied to sections of a page, as well as the page layout itself. For any serious web developer it is an essential tool. This blog is by no means a comprehensive explanation of all of Firebug's functionality, but rather a basic introduction of its core features. As of this writing, there is no equivalent tool for Internet Explorer. And, of course, IE and Mozilla don't always display a page the same way, typically because of the way the two browsers interpret styles.
]]></description> 
					<pubDate>Mon, 27 Apr 2009 19:56:53 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2009/4/27/using-firebug-to-debug-web-pages/</guid>
				</item>
			
				<item>
					<title>A Password Reset Solution for Windows SharePoint Services</title> 
					<link>http://keylimetie.com/blog/2009/4/8/a-password-reset-solution-for-windows-sharepoint-services/</link> 
					<description><![CDATA[
If you need a solution that allows users to quickly change their NT account passwords on a web server that resides outside of their domain, you can use the DirectoryServices namespace. One example of when this might be necessary is in the case of a Windows SharePoint Service site that is exposed to an external set of users. The code below and attached solution shows how to do this. You begin by adding a reference to the System.DirectoryServices.dll assembly. Next, create a web form with 2 Labels, 2 Textboxes and a Button control, like the one shown below: In the code behind, add the following: string userName = string.Empty;

    protectedvoid Page_Load(object sender, EventArgs e)
    {

        userName = HttpContext.Current.User.Identity.Name.ToString();
        lblLoggedInUser.Text = userName.Split('\\')[1];
        lblMessage.Text = string.Empty;
        lblMessage.ForeColor = System.Drawing.Color.Red;
    }The first 2 lines of code in the Page_Load event get the current user’s domain and user name and writes the user name portion to the label control. Putting the user name in a label control versus a text box prevents users from changing the passwords of users. Next, add the following code and wire this event to the Button’s Click event: protected void btnResetPassword_Click(object sender, EventArgs e)
    {
        try
        {
                            
            string user = userName.Split('\\')[1];
            DirectoryEntry AD = new DirectoryEntry("WinNT://" + Environment.MachineName + ",computer");
            DirectoryEntry NewUser = AD.Children.Find(user);

            NewUser.Invoke("SetPassword", newobject[] {txtConfirmPassword.Text});
            NewUser.CommitChanges();

            lblMessage.Text = "Password change successful.";
            lblMessage.ForeColor = System.Drawing.Color.Green;
        }
        catch (Exception err)
        {
            // set the error message
            Response.Write(err.Message);
        }
    }
}The first three lines in the code above create an instance of the DirectoryEntry class based on the name of the computer and then query that computer for the specific user. Once the directory entry for that user is located, the Invoke method is called on the directory entry, passing in the command argument for setting the new password. This is followed by a call to the CommitChanges method. Lastly, in order to run this code on the web server, the web.config file needs to be modified so that the solution impersonates a user with privileges to update security settings: identity impersonate="true" userName="user" password="pwd"/>Once the page is made available on the server, you can integrate it with SharePoint by adding a link to the SharePoint site, or by linking to it through a Page Viewer web part.]]></description> 
					<pubDate>Wed, 08 Apr 2009 15:13:30 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2009/4/8/a-password-reset-solution-for-windows-sharepoint-services/</guid>
				</item>
			
				<item>
					<title>SQL Server 2005 Script to Generate INSERT statements</title> 
					<link>http://keylimetie.com/blog/2009/3/24/sql-server-2005-script-to-generate-insert-statements/</link> 
					<description><![CDATA[When it comes time to migrate code and database changes for a project, you often need to create new rows in the various environments (i.e. QA, Staging, Production). Some migrations involve creating rows for list tables, including states, countries, status codes, etc. One option is to write the INSERT statements one at a time, but that is too time consuming and is prone to errors. Instead, you can use the SQL script listed below. 

When you run the script against a table, you'll notice 2 things:
1. All data values are converted to HEX so you don't need to worry about escaping quotes.
2. If the table has an identity column, the script will generate the IDENTITY_INSERT commands as well. 

Download SQL script

/* EXAMPLES--Entire tableCreateInserts 'Webpages'--Entries WHERE WebpageID > 100CreateInserts 'Webpages', 'WebpageID > 100'--Entries WHERE WebpageID > 100 ORDER BY TitleCreateInserts 'Webpages', 'WebpageID > 100', 'Title'*/--If stored procedure already exists, drop it
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = 
OBJECT_ID(N'[dbo].[CreateInserts]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[CreateInserts]
GO

--Create the stored procedure
CREATE PROC CreateInserts

@tableName nvarchar(100),
@whereClause nvarchar(MAX) = '',
@orderByClause nvarchar(MAX) = ''

AS

--Declare variables
DECLARE @tableHasIdentity bit
DECLARE @sql nvarchar(MAX)
DECLARE @cols nvarchar(MAX)
DECLARE @vals nvarchar(MAX)
SET @cols = ''
SET @vals = ''

--Determine if table has an identity column
SELECT @tableHasIdentity = 
OBJECTPROPERTY(OBJECT_ID(TABLE_NAME), 'TableHasIdentity')
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = @tableName

--Do we need 'SET IDENTITY_INSERT tableName ON' statement?
IF @tableHasIdentity = 1
	BEGIN
		SET @sql = 'SELECT TOP 1 ''SET IDENTITY_INSERT ' + 
@tableName + ' ON '' FROM ' + @tableName
		EXEC sp_executesql @sql
	END

--Build list of columns and values
SELECT @cols = @cols + ',' + '[' + column_name + ']', @vals = @vals + 
	'+'',''+ISNULL(master.dbo.fn_varbintohexstr(cast([' + 
column_name + '] as varbinary(max))),''NULL'')' 
FROM INFORMATION_SCHEMA.columns 
WHERE TABLE_NAME = @tableName and DATA_TYPE != 'timestamp'

--Build SQL string
SET @sql = 'SELECT ''INSERT INTO [' + @tableName + '] (' + 
SUBSTRING(@cols,2,LEN(@cols)) + ') ' + 
			'VALUES (''+' + SUBSTRING(@vals, 6, 
LEN(@vals)) + '+'')'' FROM ' + @tableName
--Adjust @whereClause and @orderByClause
IF LEN(@whereClause) > 0
	SET @sql = @sql + ' WHERE ' + @whereClause
IF LEN(@orderByClause) > 0
	SET @sql= @sql + ' ORDER BY ' + @orderByClause

--Execute SQL string
exec sp_executesql @sql

--Do we need 'SET IDENTITY_INSERT tableName OFF' statement?
IF @tableHasIdentity = 1
	BEGIN
		SET @sql = 'SELECT TOP 1 ''SET IDENTITY_INSERT ' + 
@tableName + ' OFF '' FROM ' + @tableName
		EXEC sp_executesql @sql
	END

GO
]]></description> 
					<pubDate>Wed, 25 Mar 2009 02:53:27 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2009/3/24/sql-server-2005-script-to-generate-insert-statements/</guid>
				</item>
			
				<item>
					<title>Why GWT?</title> 
					<link>http://keylimetie.com/blog/2009/3/11/why-choose-gwt/</link> 
					<description><![CDATA[
		
		The last song on the radio, as I was parking my car today, was Turning Japanese (bonus points if you can name the artist without using Google). This is not the ideal song to have running through your head on a workday, or pretty much any other time. So in an effort to dispel the demons of eighties novelty pop music from my tortured brain, I thought today was as good a time as any to write about the Google Web Toolkit (GWT). 
		GWT is a framework for writing AJAX interactive web applications. Take a look at the GWT home page for lots of great information about GWT. I'm going to look at this from the point of view of answering the key question - "Why GWT"? In other words, out of all the AJAX frameworks out there, what compelling reasons are there to choose GWT? 
		Write Java code, not JavaScript
		One of the most unique features of GWT is that you code in Java. While in development, you can run your Java code in a special "hosted mode" browser with all of the mature, sophisticated Java debugging tools you always have available. For deployment, this Java code is run through a compiler which translates this Java code to cross-browser JavaScript. 
		Although this is significant, especially in shops with a lot of Java experience, I don't believe this is a truly killer feature of GWT. The important thing is that the developer is shielded from the complexities of writing JavaScript code that works in all browsers. Other AJAX frameworks provide a layer of JavaScript that provides this abstraction. GWT does this by translating standard Java code, but how this is abstracted is less important than the simple fact that it is abstracted. 
		Simple RPC mechanism
		GWT has its own mechanism for remote procedure calls between the browser and the server. This works a lot like vanilla Java RMI - define interfaces and implementations for your server functions, and code will be generated to allow your client code to call them as if they were simple local methods. This blows away all the work of defining XML or JSON data formats for requests and responses. Just code the function for the server, call the function (still in Java) from the client code, and all of the marshalling, unmarshalling, network communication, etc. is done for you. 
		GWT also supports other RPC methods, such as XML or JSON over HTTP. You can write server code as standard SOAP or REST web services and GWT will be able to use them directly. This will take longer to code than the GWT RPC mechanism, but allows you to use legacy web services or services intended to also be used by non-GWT clients. A good middle-ground approach may be to prototype using GWT RPC, and re-implement as web services later. 
		
		Optimized cross-browser JavaScript
		One of the key reasons to use any AJAX framework is to write code that will produce identical results on all browsers, which is fiendishly difficult in raw JavaScript. Why roll your own code to handle all of those quirks, when a bunch of framework authors have already done it for you? GWT handles this, just like any good framework. As a bonus, the generated JavaScript is automatically compressed and obfuscated, decreasing download size and making reverse engineering more difficult. 
		Download sizes are kept even smaller by a unique GWT feature, namely... 
		Deferred binding
		Writing code that works on any browser is great. But there is a cost - the framework has to include code for every browser. You may be viewing the page in IE, but you also downloaded code specific to Firefox, Safari, and Opera, which will never be executed. Deferred binding is the GWT solution to this dilemma. 
		The first step in deferred binding happens during compilation. The GWT compiler creates a different JavaScript file for each browser type, containing all of your application code optimized for just that one browser. A very small bootstrap script is also generated, which examines the execution environment and determines which browser-specific application script to load. The bootstrap script is included in a standard HTML page, and when the page loads the script will resolve, download, and run the correct application script. 
		There is also provision for taking advantage of caching. The bootstrap file is intended to never be cached (and is helpfully suffixed with "nocache.js" as a reminder). The implementation scripts are intended to be cached, and have file names that are a hash code of their contents. This means that if you re-compile, but there are no changes in a particular file, it will have the same name and will allow the browser to use the already cached version. If the file changes, it's filename will change and therefore force a reload when it is next requested. All of this is done without any developer help (the generated bootstrap script deals with the filenames automatically). Pretty neat, huh? 
		I've only talked about deferring binding based on browser type so far, but this is a general mechanism and you can define other context-dependent variances as well. The most common use of this is... 
		
		Localization
		Localizing a GWT application is very straightforward and very similar to how it is done in standard Java applications. In the simple case, just create properties files with locale suffixes, access them by key through a GWT interface, and the locale-specific string will be used. The cool part is that GWT uses the deferred binding mechanism to make sure that only those properties for the current user's locale are ever downloaded. 
		As with browser-specific code, this starts at compile time. For each combination of browser AND locale, an application script is generated. So, if you have, say, 4 browsers and 3 different locales, you will have 12 files generated - such as FireFox in English, FireFox in French, IE in English, etc. The bootstrap file will examine the client environment and load the application file specific to the detected browser and locale. 
		Image bundles
		It should be obvious by now that the Google team put a lot of effort into ensuring the highest possible performance. Image bundles are yet another performance-boosting feature of GWT. Defining an image bundle allows the GWT compiler to package a number of images into a single file which is accessed through a Java object. This reduces the number of network round trips by getting all images for your application in a single file download. The packaging is done by the GWT compiler; all the developer has to do is define an annotated interface with a function to access each image. 
		
		Embeds well in existing sites
		Some frameworks work best only if they are in charge of the whole page. GWT "plays well with others", in that it can generate entire pages or elements within a page equally well. The GWT scripts work by creating HTML elements inside a specified element on a page during the onLoad() event. To embed a GWT application in an existing page, you therefore only need to include the script file and add an id to the element you want to contain the application (which can be a div, a td, the body, anything). Couldn't be easier. 
		Conclusion
		That's a lot of good reasons to choose GWT, and that's just scratching the surface. There are many other features that make GWT a compelling choice. These include interoperation with native JavaScript, intelligent support for back button navigation within an application, accessibility support, programming delayed logic, support for JUnit testing, availability of third-party widget libraries, and more. GWT is also under continuous development, with the upcoming 1.6 version to include improvements like a faster hosted mode server, faster string handling, better compiler performance, and easier deployment to standard JEE WAR files. The Google team has done a very good job of providing a no-compromise framework that provides a fast, rich, and consistent user experience while keeping the developer focused on the application rather than the technology. It's definitely worth taking for a test drive. 
		Now, if I could just get that song out of my head... 
]]></description> 
					<pubDate>Wed, 11 Mar 2009 14:01:47 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2009/3/11/why-choose-gwt/</guid>
				</item>
			
				<item>
					<title>ASP.NET DataView - Always Create a New Instance!</title> 
					<link>http://keylimetie.com/blog/2009/1/12/aspnet-dataview-always-create-a-new-instance/</link> 
					<description><![CDATA[
We recently built website software for a client that had a requirement to handle 1,000 concurrent users for 3 minutes. During the initial stress testing, the software performed perfectly up to 250 users. Once it hit 250 users, we started to receive exceptions and page content wasn't being displayed properly. After some investigation, KeyLimeTie senior developer, Michael Wick, determined the problem was around our use of the DataView class. He believed the code was not thread safe and causing threads to overwrite each other.


We went to MSDN to see if the class is thread safe and according to Microsoft, "This type is safe for multithreaded read operations. You must synchronize any write operations." What's the definition of "write operations"? In our case, the DataTable the DataView consumed was being written to once (when the website started up), but was being filtered many times in a static class. We felt the way we were using the class constituted as multiple "write operations". To confirm this, we created a test application.


Download Application only
Download Source Code


Code

In the code below, the DataView is initialized two completely different ways:

Line 4: A new instance of the DataView class is created (good)

Line 6: Uses a shared view of the DataTable (bad)



1//Create DataView
2DataView dv = null;
3if (useNew)
4    dv = new DataView(dt);
5else
6    dv = dt.DefaultView;
7
8//Apply filter
9dv.RowFilter = "RandomNumber = " + randomNumber.ToString();
10
11//Return num rows found
12return dv.Count;


With low usage, Line 4's code will work just fine. Once your software starts to pick up more usage, it will begin to error. Please run the test application we have provided to see for yourself. The screenshot below illustrates what happens when a new instance of the DataView class isn't created every time it's used. The feedback in the application shows the thread numbers and their operations. Notice the DataView code has been executed over each other's thread causing unexpected results. Next, check the "Use new keyword" checkbox and you'll see the expected results are always met (no errors reported).]]></description> 
					<pubDate>Mon, 12 Jan 2009 17:55:14 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2009/1/12/aspnet-dataview-always-create-a-new-instance/</guid>
				</item>
			
				<item>
					<title>Writing Database Objects In Managed Code</title> 
					<link>http://keylimetie.com/blog/2008/12/10/writing-database-objects-in-managed-code/</link> 
					<description><![CDATA[With SQL Server 2005, you can use .NET Framework languages to create database objects and retrieve and update data. You can create stored procedures, triggers, aggregates, user-defined functions, and user-defined types, using any one of the CLR-compliant languages. In this article, I will cover the steps involved in creating and debugging a stored procedure in C#.
To begin, it's worth noting that there are several advantages to using managed code over T-SQL: 


Enhanced programming model 
  .NET Framework languages offer constructs and capabilities previously unavailable to SQL developers. Visual Basic, Visual C#, and Visual C++ provide capabilities that are not available in Transact-SQL, such as arrays, sophisticated exception handling, and reusability of code. 


Reusability of Code
   A library of managed assemblies can be created and distributed more easily than a Transact-SQL script can be distributed.  


Leverage Existing Skills
   You can use and enhance your skills in the languages and development environment in which you are already experienced to create database objects. 


Richer developer experience
   When you develop database objects using the SQL Server project template, you have complete integration with the project system, including building, debugging, and deployment to multiple servers. 


Security
   When you use database objects created using Visual Basic, Visual C#, or Visual C++, the code-access security of those languages is combined with the user-based permissions in SQL Server. 



Creating the Database Project


The first step in creating a stored procedure (or any database object) is to create a SQL Server project in Visual Studio: 
1. From the File menu, create a new project. 
2. In the New Project Dialog, select and expand a language node in the Project Types area. 
3. Select the Database node. 
4. Select the SQL Server Project template. 
5. Click OK. 




Next, you will prompted for the database connection you are using. Unless this database has had CLR-integration enabled previously, you will need to run the following in SQL Server:
sp_configure 'clr enabled', 1 
GO 
RECONFIGURE 
GO 


Creating the Stored Procedure


At this point, you are ready to start creating database objects. To create a new stored procedure, do the following steps:
1. Open an existing SQL Server Project, or create a new one.  From the Project menu, select Add New Item. 
2. Select Stored Procedure. 
3. Type a Name for the new stored procedure. 
4. Add code to run when the stored procedure is executed. 
5. In the sample code below, I have created a stored procedure that accepts one parameter and queries the Product table of the Adventure Works database. The code should look very familiar, utilizing Connection, Command and Parameter objects. One object that may not be familiar is the SQLPipe. This allows managed stored procedures running in-process on a SQL Server database to return results back to the caller. 
    [Microsoft.SqlServer.Server.SqlProcedure]    publicstaticvoid SelectProductByProductID(int productID)    {        using (SqlConnection conn = new SqlConnection("context connection=true"))        {            try
            {
                SqlPipe pipe = null;                SqlCommand SelectProductCommand = new SqlCommand();                SqlParameter productIDParam = new SqlParameter("@ProductID", SqlDbType.Int);                productIDParam.Value = productID;                SelectProductCommand.Parameters.Add(productIDParam);                SelectProductCommand.CommandText = 
"Select * from Production.Product where AProductID = @ProductID";                conn.Open();                SelectProductCommand.Connection = conn;                pipe = SqlContext.Pipe;                pipe.ExecuteAndSend(SelectProductCommand);            }            catch (SqlException sqlEx)            {                //code to handle or log the sql exception here 
                Console.WriteLine(sqlEx);
            }
            catch (Exception ex)            {                Console.WriteLine(ex);            }        }    }
Once the code is ready, you can build and deploy the stored procedure to the database by pressing 'F5'. To test the deployment, there is a file in your project called test.sql. In this file, you can add script calls to the obects you just created. For example, to call the stored procedure created above, enter:
EXEC [dbo].[SelectProductByProductID] 4


That's it. If the stored procedure was written correctly, you will now see this item in list of stored procedures in Enterprise Manager. However, you'll see the object has a lock icon next to it, as shown below. This is because the object is not editable outside of the Visual Studio project.





Conclusion
At this point, you might be asking 'so where are the benefits?'. Let's look at a few:


Exception Handling: if the stored procedure returns an error, say a constraint violation for example, this error gets converted into a SqlException that you can then handle in your managed code. To try this, change the column in the stored procedure text above to AProduct and hit 'F5'. You'll see that the catch block is entered. This gives a lot of flexibility in how you handle errors that don't readily exist in T-SQL.


Deployment:
If you need to deploy the objects you created to another server, you simply change the database connection in the project properties and hit 'F5'. No more creating and managing scripted stored procedures.


]]></description> 
					<pubDate>Wed, 10 Dec 2008 23:07:13 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2008/12/10/writing-database-objects-in-managed-code/</guid>
				</item>
			
				<item>
					<title>Migrating ASP.NET Applications to IIS 7.0 Integrated Mode </title> 
					<link>http://keylimetie.com/blog/2008/11/14/migrating-aspnet-applications-to-iis-70-integrated-mode/</link> 
					<description><![CDATA[Upgrading an ASP.NET application from IIS 6.0 and lower (Classic ASP.NET Integration Mode) to IIS 7.0 (Integrated Mode) can be a lot of work. To help, Microsoft provides an application that does the work for you.


IIS 7.0 takes care of migrating the application by using the APPCMD.EXE command line tool to perform the migration. The migration error message contains the command that is executed in command line window (which you must run--right click the Programs\Accessories\Command Prompt icon, and choose "Run as administrator") in order to instantly migrate your application to Integrated mode. 


The basic format of the migration command is the following: 


%windir%\system32\inetsrv\APPCMD.EXE migrate config 


where  is the virtual path of the application containing the site name, such as "Default Web Site/app1". 


When migration is complete, your application runs in both Integrated and Classic modes without a problem. 


Note: If you change the configuration after migration, the server will not prompt you to migrate again. After initial migration, you must make sure that your configuration remains in sync between the two modes – manually migrate the application again using the APPCMD.EXE command line tool. 


Source: http://learn.iis.net/page.aspx/243/aspnet-integration-with-iis7/]]></description> 
					<pubDate>Fri, 14 Nov 2008 20:10:22 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2008/11/14/migrating-aspnet-applications-to-iis-70-integrated-mode/</guid>
				</item>
			
				<item>
					<title>Prevent ASP.NET Pages From Caching</title> 
					<link>http://keylimetie.com/blog/2008/10/17/prevent-aspnet-pages-from-caching/</link> 
					<description><![CDATA[We recently came across a scenario where an ASP.NET page was caching on the user's browser and causing issues. ASP.NET pages are dynamic and their content should never cache. To force the browser to not cache the page, add the following code:


Code-behind

1Response.AppendHeader("Cache-Control", "no-cache; private; no-store; must-revalidate; max-stale=0; post-check=0; pre-check=0; max-age=0");
2Response.AppendHeader("Pragma", "no-cache");
3Response.AppendHeader("Keep-Alive", "timeout=3, max=993");
4Response.AppendHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT"); 
//Some random old date


HTML META tags

1
2
3
]]></description> 
					<pubDate>Fri, 17 Oct 2008 16:02:49 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2008/10/17/prevent-aspnet-pages-from-caching/</guid>
				</item>
			
				<item>
					<title>How to safely escape invalid XML characters</title> 
					<link>http://keylimetie.com/blog/2008/9/25/how-to-safely-escape-invalid-xml-characters/</link> 
					<description><![CDATA[When saving strings to XML, it important to escape invalid characters. The following table shows the invalid XML characters and their escaped equivalents.




Invalid XML Character


Replaced With









>


>




'


'




&apos;


&apos;





&


&amp;




Rather than write code to do a bunch of replaces, use this one line of code:


1string escapedText = System.Security.SecurityElement.Escape(input);

By using this built-in .NET method, you ensure your strings are properly escaped.


To learn more about this method and see developer's feedback (some people have concerns), go to

http://msdn.microsoft.com/en-us/library/system.security.securityelement.escape(VS.80).aspx
]]></description> 
					<pubDate>Thu, 25 Sep 2008 19:32:49 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2008/9/25/how-to-safely-escape-invalid-xml-characters/</guid>
				</item>
			
				<item>
					<title>How to validate strings for XML</title> 
					<link>http://keylimetie.com/blog/2008/9/2/how-to-validate-strings-for-xml/</link> 
					<description><![CDATA[Back on 3/28/2008, we published a blog titled How to check for hexidecimal characters. I used this code as a basis to write a method to ensure only valid UTF-8 characters are in a string. If invalid characters are in an XML document, the document cannot be consumed by an application and can cause a complete website outage (depending on how it's used). The following method looks for invalid XML characters.



1private static bool IsValidString(string input)
2{
3    try
4    {
5        //Trim input string
6        input = input.Trim();
7
8        //If blank, no need to validate
9        if (input.Length == 0)
10            return true;
11
12        //Loop through characters
13        foreach (char currentChar in input)
14        {
15            if (currentChar == 0x9 || // \t = 9
16                currentChar == 0xA || //   = 10
17                currentChar == 0xD || //   = 13
18                (currentChar >= 0x20 && currentChar 19                (currentChar >= 0xE000 && currentChar 20                (currentChar >= 0x10000 && currentChar 21            {
22                //Valid character
23            }
24            else
25                return false;
26        }
27    }
28    catch
29    {
30        return false;
31    }
32    return true;
33}
34]]></description> 
					<pubDate>Tue, 02 Sep 2008 15:22:38 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2008/9/2/how-to-validate-strings-for-xml/</guid>
				</item>
			
				<item>
					<title>Use CSS to AutoSize a DIV</title> 
					<link>http://keylimetie.com/blog/2008/8/11/use-css-to-autosize-a-div/</link> 
					<description><![CDATA[There are often cases where you want to display content in a div, but a fixed height won't work. It the height is too little, content is cut off or you need a vertical scrollbar (by setting the overflow value). If the height is too much, you'll have a lot of whitespace. The example below shows you how to easily create a div that autosizes based on the content.

1//HTML:
2"outerDiv" class="autosize">
3    "innerDiv" runat="server" style="display: block">
4        //Content...
5    
6
7
8//CSS:
9#outerDiv
10{
11    min-height: 200px; 
12}
13
14div.autosize { display: table; width: 1px; }
15div.autosize > div { display: table-cell; }]]></description> 
					<pubDate>Mon, 11 Aug 2008 14:21:55 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2008/8/11/use-css-to-autosize-a-div/</guid>
				</item>
			
				<item>
					<title>Using Visual Studio 2005 Add-ins in Visual Studio 2008</title> 
					<link>http://keylimetie.com/blog/2008/11/10/using-visual-studio-2005-add-ins-in-visual-studio-2008/</link> 
					<description><![CDATA[
		
				As your organization makes the move from Visual Studio 2005 to Visual Studio 2008, you're going to need to move all of the Add-ins you have come to rely on over as well. Unless the Add-in you have in mind uses some Visual Studio version-specific API, the method for porting an Add-in to the new release should be seamless.
				There are 2 steps you need to follow to get the Add-in over to Visual Studio 2008:
				
						1. Move the Add-in's Dll and associated files to the Addins folder under Visual Studio 2008.
				You will find the Add-in Dll and associated files in the Addins folder under Visual Studio 2005. The path is likely
				
						C:\Documents and Settings\User\My Documents\Visual Studio 2005\Addins  
				
				Copy the files for the Add-in you wish to migrate, and paste them into the Addins folder under Visual Studio 2008. The path for 2008 is similar, and if you do not find an Addins folder, you can create one manually.
				
						C:\Documents and Settings\User\My Documents\Visual Studio 2008\Addins
				
				Be sure to grab the .dll, .dll.config the .Addin files, as shown below.
				
						 
				
						2. Once the files have been copied to the new Addins folder, you will need to update the .Addin file to increment the Host Application's (Visual Studio) version number. You can do this by opening the file in any text editor, finding the nodes labelled version, and changing it from 8.0 to 9.0.I have bolded the version node below  \par ??\par ??\tab \par ??\tab \tab \cf0 Microsoft Visual Studio Macros\cf1 \par ??\tab \tab \cf0 8.0\cf1 \par ??\tab \par ??\tab \par ??\tab \tab \cf0 Microsoft Visual Studio\cf1 \par ??\tab \tab \cf0 8.0\cf1 \par ??\tab \par ??\tab \par ??\tab \tab \cf0 Some2005Addin\cf1 \par ??\tab \tab \cf0 The Add-in to end all Add-ins.\cf1 \par ??\tab \tab \cf0 Some2005Addin.dll\cf1 \par ??\tab \tab \cf0 Addin.SomeAddin.For2005\cf1 \par ??\tab \tab \cf0 1\cf1 \par ??\tab \tab \cf0 0\cf1 \par ??\tab \tab \cf0 0\cf1 \par ??\tab \par ??}
-->
				
						
								
										
										xml
										
										
										version
										="1.0"encoding="UTF-16"standalone="no"?>
						
						
								
										
										Extensibility
										
										
										xmlns
										="http://schemas.microsoft.com/AutomationExtensibility">
						
						
								
										  
										HostApplication
										>
								
						
						
								
										    
										Name
										>Microsoft Visual Studio MacrosName>
						
						
								
										
												    
												Version
												>8.0Version>
								
						
						
								
										  
										HostApplication
										>
								
						
						
								
										  
										HostApplication
										>
								
						
						
								
										    
										Name
										>Microsoft Visual StudioName>
						
						
								
										
												    
												Version
												>8.0Version>
								
						
						
								
										  
										HostApplication
										>
								
						
						
								
										  
										Addin
										>
								
						
						
								
										    
										FriendlyName
										>Some2005AddinFriendlyName>
						
						
								
										    
										Description
										>The Add-in to end all Add-ins.Description>
						
						
								
										    
										Assembly
										>Some2005Addin.dllAssembly>
						
						
								
										    
										FullClassName
										>Addin.SomeAddin.For2005FullClassName>
						
						
								
										    
										LoadBehavior
										>1LoadBehavior>
						
						
								
										    
										CommandPreload
										>0CommandPreload>
						
						
								
										    
										CommandLineSafe
										>0CommandLineSafe>
						
						
								
										  
										Addin
										>
								
						
						
								
										
										Extensibility
										>
								
						
				
				
				Once this value has been changed to 9.0, save the file, and open the Add-in Manager dialog in Visual Studio 2008 (TOOLS MENU-->ADD-IN MANAGER...)
				You will now see the Add-in appear in the dialog. Select the Add-in you have just migrated and you are ready to go.
				
						 
		
]]></description> 
					<pubDate>Tue, 01 Jul 2008 23:56:30 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2008/11/10/using-visual-studio-2005-add-ins-in-visual-studio-2008/</guid>
				</item>
			
				<item>
					<title>Access ScriptManager in a Master Page from Content Page</title> 
					<link>http://keylimetie.com/blog/2008/6/12/access-scriptmanager-in-a-master-page-from-content-page/</link> 
					<description><![CDATA[
		I recently had to access the ScriptManager in a Master Page from one of the Content Pages.I first tried to perform a FindControl(), but there's a much easier way.There is a static method in the ScriptManager class called "GetCurrent()" which provides access to the current instance of the ScriptManager.
		
				//Extend script manager timeout to 10 minutes
		ScriptManager.GetCurrent(this).AsyncPostBackTimeout = 600;
]]></description> 
					<pubDate>Thu, 12 Jun 2008 17:45:40 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2008/6/12/access-scriptmanager-in-a-master-page-from-content-page/</guid>
				</item>
			
				<item>
					<title>How to enable HTTP Compression on Windows Server 2003</title> 
					<link>http://keylimetie.com/blog/2008/5/20/how-to-enable-http-compression-on-windows-server-2003/</link> 
					<description><![CDATA[
		If your server and website are not using HTTP Compression, you're not taking advantage of one of the easiest website performance features to implement. This blog tells you how to enable HTTP Compression in less than 10 minutes and reduce traffic by as much as 85%! The instructions below are a combination of articles I've read online and in print. We have implemented this on at least a dozen servers which host hundreds of websites with only one issue (mentioned below; issue with PDFs).Create Compression Folder- Create a folder where the compressed file will be cached. You can give it any name or leave the default: "%windir%\IIS Temporary Compressed Files".- Grant write permissions to IUSR_{machinename} for the folder.Enable Compression in IIS- In IIS, right-click on the "Web Sites" node and click "Properties".- Select the "Service" tab.- Check "Compress application files". (we have seen issues where PDFs are compressed and cannot be opened)- Check "Compress static files".- Change "Temporary directory" (if you created your own folder).- Set the "Maximum temporary directory size" to something that the hard drive can handle (i.e. 1024).- Save and close the "Web Site" Properties.Create a Web Service Extension (WSE)- In IIS, select "Web Service Extensions".- Add a new web service extension.- Name it "HTTP Compression".- Point it to "c:\windows\system32\inetsrv\gzip.dll".- Check the "Set extension status to Allowed" to enable it.Edit IIS Metabase- In IIS, right-click on the server node (top level) and click "Properties".- Check "Enable Direct Metabase Edit".- In Notepad, open the metabase: C:\Windows\system32\inetsrv\metabase.xml- Search for "- There will be two of them, one for deflate and one for gzip.- In "HcScriptFileExtensions", add aspx, asmx and any other extension that you need to the list already there. Do this for both deflate and gzip and format the format.- Change "HcDynamicCompressionLevel" to 9.  Do this for both deflate and gzip.- Restart IIS
]]></description> 
					<pubDate>Wed, 21 May 2008 01:19:41 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2008/5/20/how-to-enable-http-compression-on-windows-server-2003/</guid>
				</item>
			
				<item>
					<title>Disable PDB File Generation in Release Mode</title> 
					<link>http://keylimetie.com/blog/2008/4/15/disable-pdb-file-generation-in-release-mode/</link> 
					<description><![CDATA[		Migrating code to a Production environment is not a difficult task, but I have seen developers do some weird stuff. I have seen developers migrated code compiled for debug and then wonder why the site doesn't run very fast...not common, but really does happen. I have seen developers migrate the entire source code for a project to the Production environment. They call it their "back up" location. Ever hear of VSS? These are bad practices that should be avoided.Have you ever noticed that code you build for Release or Publish still generates a PDB file? Up until recently I really didn't think much of it, but one day I got curious. I did a little research and found a great blog on compiling options and the implications. In short, you can disable generation of the PDB file (see image below), but it's not recommended. Read this article for more details:
		
				http://blog.vuscode.com/malovicn/archive/2007/08/05/releasing-the-build.aspx
				
				
				
		
]]></description> 
					<pubDate>Wed, 16 Apr 2008 01:52:06 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2008/4/15/disable-pdb-file-generation-in-release-mode/</guid>
				</item>
			
				<item>
					<title>How to check for hexidecimal characters</title> 
					<link>http://keylimetie.com/blog/2008/3/28/how-to-check-for-hexidecimal-characters/</link> 
					<description><![CDATA[If you haven't come across it yet, hexidecimal characters are not allowed in XML documents and cause problems when trying to display or work with them. When working with 3rd party data in XML (not received via a web service), it's always a good idea to validate the data. If you see an error like "hexidecimal value 0x04, is an invalid character, Line 1 Position 20154755", your problem is the data in the XML document. We recently came across this issue and created a simple method to check for valid characters:

Be sure to check out related blog: How to validate strings for XML


1private bool IsValidString(string input)
2{
3    try
4    {
5        char[] values = input.ToCharArray();
6        foreach (char c in values)
7        {
8            //Get the integral value of the character
9            int value = Convert.ToInt32(c);
10            //Valid character (space -> tilde) see: http://www.asciitable.com
11            if (value  126)
12                return false;
13        }
14    }
15    catch
16    {
17        return false;
18    }
19    return true;
20}
]]></description> 
					<pubDate>Sat, 29 Mar 2008 01:45:19 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2008/3/28/how-to-check-for-hexidecimal-characters/</guid>
				</item>
			
				<item>
					<title>KeyLimeTie Log Cleaner (file pruning application) - FREE!</title> 
					<link>http://keylimetie.com/blog/2008/3/16/keylimetie-log-cleaner-free/</link> 
					<description><![CDATA[
    With all of the applications running on a server, it is important to keep their
    output pruned. Even with a basic server running a few websites, you can expect to
    have:
    - IIS logs
    - SQL Server database backups
    - Application-specific logging
    
    Over time, these files can consume a lot of disk space and potentially disable a
    server. Over the past 5 years, I have worked on-site with nine clients. Of these
    nine clients, seven of them have encountered this problem. In fact, my most recent
    client had this problem last week! It happens so often that when someone said the
    server was was running slow and throwing errors to the web browser, the first thing
    I said was "I bet the hard drive is full"...and it was.
    
    Why does it happen so often? There are many reasons, but the main reason is because
    nobody is monitoring the disk space (or monitoring tools are not installed) and
    the files aren't being properly pruned or archived. To resolve this issue, I created
    the KeyLimeTie Log Cleaner application free for anyone to download and use. I purposely
    made it very simple to configure and install; there are plenty of features and options
    we could add.
    
    To get it running:
    1. Download Application
    2. Unzip the files to a folder on your hard drive.
    3. Open the "profiles.xml" file and edit it for your needs.
    
    xml version="1.0" standalone="yes"?>
Profiles>
	Profile>
		!-- Keep this application's logs pruned to 15 days -->
		Description>KeyLimeTie Log CleanerDescription>
		FolderPath>D:\Projects\KeyLimeTie\KeyLimeTie.LogCleaner\Logs\FolderPath>
		Extension>txtExtension>
		DelOlderThanDays>15DelOlderThanDays>
		Recursive>falseRecursive>
	Profile>
	Profile>
		!-- Example: Keep IIS Logs pruned to 15 days -->
		!-- Setting Recursive true prunes all ftp and website logs -->
		!-- As new websites are added, no need to update profiles -->
		Description>All IIS LogsDescription>
		FolderPath>C:\Windows\system32\LogFiles\FolderPath>
		Extension>logExtension>
		DelOlderThanDays>15DelOlderThanDays>
		Recursive>trueRecursive>
	Profile>
	Profile>
		!-- Example: Keep SQL Server backups pruned to 1 week -->
		!-- Setting Recursive true prunes all database backups -->
		!-- As new databases are added, no need to update profiles -->
		Description>All Database BackupsDescription>
		FolderPath>D:\Databases\Backups\FolderPath>
		Extension>bakExtension>
		DelOlderThanDays>7DelOlderThanDays>
		Recursive>trueRecursive>
	Profile>
Profiles>


    Fields:
    
    - Description: Profile description
    - Folder Path: Location of files to be deleted
    - Extension: Extension of files to be deleted
    - DelOlderThanDays: Number of days to delete files older than today
    - Recursive: Tells application to look for files in subdirectories
    
    Schedule Application:
    I installed the software on a few servers and simply created a Scheduled Task through
    Windows. I have it set to run every day at 4am (after the SQL Server backups are
    run).
    
    Some ideas...
    - Change "Extension" option to be "MatchPattern". Right now, the code searches for
    all files by the extension. You can put "*" in there and it'll prune all files,
    but it could be made to be more powerful.
    - Create as Windows Service. I have created similar applications as Windows Services...and
    it's very easy to change this to a Windows Service. But I wanted this first version
    to be very simple and simple to install. I have seen people have issues with installing
    Windows Services.
    - Create an interface to manage the profiles. It's so easy to update this really
    isn't necessary.

]]></description> 
					<pubDate>Sun, 16 Mar 2008 18:54:19 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2008/3/16/keylimetie-log-cleaner-free/</guid>
				</item>
			
				<item>
					<title>Internet Explorer 8 Has Arrived!</title> 
					<link>http://keylimetie.com/blog/2008/3/6/internet-explorer-8-has-arrived/</link> 
					<description><![CDATA[
		From "ReadWriteWeb"...Microsoft's next-generation web browser, Internet Explorer 8, has arrived. In a surprising move, after the demo of IE8 and its new features at today's session of the MIX08 conference, the startling announcement was made: "It's available for download now". The new browser showcases many new features and improvements, like Facebook and eBay integration, standards compliance, and the ability to work with AJAX web pages. What's most notable about IE8, though, is more than a sum of its parts. If anything, this launch shows that Microsoft is not taking Firefox's creep into browser market share lightly.IE8 New Features Shown At MIX08Standards ComplianceThere were hints that IE8 would be a remarkable offering on the IE Blog as they released tidbits about the browser's capabilities. For example, the announcement of IE8's passing of the Acid2 test (a test for standards compliance) marked a milestone in IE8's development. The standards mode was originally going to be turned off by default letting web developers code for it by including a "meta" tag to make use of IE8's new standards compliant mode. Later, Microsoft came to their senses and made the default the standards-compliant mode. Meanwhile, Firefox also claims to have passed the Acid 2 test, but an open bug on bugzilla.mozilla.org seems to say otherwise. One commenter on the thread notes, "So, we essentially do pass the test. However, in some situations, it might still fail, that's why this bug is open."Facebook IntegrationWith a Flock-like feature as an unexpected surprise, Microsoft capitalized on their partnership with the popular social networking site, Facebook, to allow IE8 users the ability to get status updates from Facebook right from their browser toolbar.eBay IntegrationLike Facebook, this feature also uses IE8's new technology, called "WebSlices", which introduces a new way to get updates from other sites via the browser itself, without having to visit the web site. With WebSlices, IE8 beta users can subscribe to portions of a page that update dynamically, in order to receive updates from that page as contentchanges. eBay will offer webslices, too, letting you track your auctions from the browser toolbar. Basically, WebSlices look like Favorites on your Links toolbar but they have a little arrow next to them - clicking on this arrow will show you a small window of live web content. Live Maps IntegrationAnother WebSlice was integration with Live Maps. It appeared that you could even highlight text on a page, like an address, and then right-click and choose Live Maps from the context menu to get a WebSlice preview of that location on a map in a small pop-up window.Integration with Me.diumMe.dium integration will be supported in IE8 via WebSlices. Me.dium will now help web surfers discover and view WebSlices directly from the sidebar. The Me.dium sidebar will alert users to the presence of WebSlices on any page – and even allows users to read each WebSlice, without leaving the Sidebar. In addition, Me.dium will make real-time recommendations for other WebSlices on other relevant web pages and provides direct links to them based on the real time activity of other Me.dium users.Working with AJAX PagesIE8 will offer better functionality when it comes to AJAX web pages. The example showed a page where you could zoom in using AJAX technology. Previously, hit the IE "Back" button would take you back to the last page you were on. Now, "Back" will zoom you out.We can now find out what other features IE8 has to offer, since the beta is now publicly available for download. To get IE8, you can download it from here:http://www.microsoft.com/windows/products/winfamily/ie/ie8/readiness/Install.htm.
		 
]]></description> 
					<pubDate>Fri, 07 Mar 2008 01:23:50 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2008/3/6/internet-explorer-8-has-arrived/</guid>
				</item>
			
				<item>
					<title>Safely restart an ASP.NET remotely</title> 
					<link>http://keylimetie.com/blog/2008/2/12/safely-restart-an-aspnet-remotely/</link> 
					<description><![CDATA[
Every once in awhile, an ASP.NET website may need to be restarted. There are a few ways to do this: kill the worker process (too forceful), restart IIS (restarts all websites) or modify the web.config (best choice). Instead of FTP'ing the web.config down and back up or logging onto the server to update the web.config, why not create a web page that allows you to easily update the "last write date" on the file. The .NET Framework monitors website files and when the web.config write date changes, it automatically restarts that website. Here's code you can drop into an ASP.NET web page to accomplish this:




	function ToggleSourceCodeRegion(regionNumber)
	{
		var divRegion = document.getElementById('region' + regionNumber);
		var divRegionBlock = document.getElementById('regionBlock' + regionNumber);

		if (divRegion.style.display == 'inline')
		{
			divRegion.style.display = 'none';
			divRegionBlock.style.display = 'inline';
		}
		else
		{
			divRegion.style.display = 'inline';
			divRegionBlock.style.display = 'none';
		}
	}
1"C#" %>
2
3"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
4
5"server">
6    protected void Page_Load(object sender, EventArgs e)
7    {
8        lblMessage.Text = "";
9    }
10
11    protected void btnRestart_Click(object sender, EventArgs e)
12    {
13        if (txtPassword.Text.Trim().ToUpper() ==
14            System.Configuration.ConfigurationManager.AppSettings["ResetSitePassword"].ToString().Trim().ToUpper())
15        {
16            string webConfigPath = Server.MapPath("Web.config");
17            System.IO.File.SetLastWriteTime(webConfigPath, DateTime.Now);
18            Session.Abandon();
19            Response.Redirect("/");
20        }
21        else
22            lblMessage.Text = "Invalid password";
23    }
24
25
26"http://www.w3.org/1999/xhtml">
27"server">
28    Restart Website
29
30
31    "aspnetForm" runat="server">
32        Password:
33        "txtPassword" runat="server" TextMode="Password">
34        "btnRestart" runat="server" Text="Restart" OnClick="btnRestart_Click">
35        
36        "lblMessage" runat="server" ForeColor="Red">
37    
38
39]]></description> 
					<pubDate>Tue, 12 Feb 2008 21:15:04 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2008/2/12/safely-restart-an-aspnet-remotely/</guid>
				</item>
			
				<item>
					<title>Don&amp;quot;t Search For Domain Names on Network Solutions!</title> 
					<link>http://keylimetie.com/blog/2008/2/9/dont-search-for-domain-names-on-network-solutions/</link> 
					<description><![CDATA[		If you check for a domain name on Network Solutions, you will have to buy it there or risk losing it forever!
		When you check for a domain name on Network Solutions, they immediately lock that domain for 4 days. If you want the domain, you must buy it through them for $35. If you don't and the 4 days pass, it becomes public to domain name snipers and may be unavailable forever! Don;t believe me, try it your self:1. Go to Network Solutions (http://www.netsol.com) and search for a domain name. I tried keylimetierocks.com2. It's available, but I don't buy it.3. Immediately go to GoDaddy (http://www.godaddy.com) and search for the same domain name.4. It's not available!]]></description> 
					<pubDate>Sun, 10 Feb 2008 05:06:51 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2008/2/9/dont-search-for-domain-names-on-network-solutions/</guid>
				</item>
			
				<item>
					<title>How to use Visual Studio 2003 in Windows Vista</title> 
					<link>http://keylimetie.com/blog/2008/1/17/using-vs7-in-vista/</link> 
					<description><![CDATA[
		
				This blog entry is intended to illustrate the steps necessary to set up a Windows Vista machine to use Visual Studio 2003 (.NET 1.1).  Most of the information was obtained from the following blogs: 
		
		
				
						http://citruslime.blogspot.com/2007/04/visual-studio-2003-web-debugging-on.html
				
		
		
				
						http://blogs.iis.net/brian-murphy-booth/archive/2007/03/09/how-to-setup-asp-net-v1-1-visual-studio-net-2003-projects-on-iis7-vista.aspx
				
		
		
				
				
						 
				
		
		
				
						
								
										
												Steps
										
								
						
				
		
		
				
						
								
										1.
										       
								
						
						
								Setup your user account as a local admin on the Vista machine and switch off the "user account control”.
						
				
		
		
				
						
								
										a.
										       
								
						
						
								Open Control Panel -> User Accounts.
						
				
		
		
				
						
								
										b.
										      
								
						
						
								Select “Change your account type”.
						
				
		
		
				
						
								
										c.
										       
								
						
						Select “Administrator” (if not already Administrator).
				
		
		
				
						
						
								
								
								
										
										
										
										
										
										
										
										
										
										
										
										
										
										
										
										
										
										
										
										
										
										
										
										
								
								
								
								
								
						
				
		
		
				
						
								
										d.
										      
								
						
						Press “Change Account Type”.
				
		
		
				
						
								
										e.
										      
								
						
						Select “Turn User Account Control on or off”.
				
		
		
				
						
								
										f.
										        
								
						
						Uncheck “Use User Account Control (UAC) to help protect your computer”.
				
		
		
				
				
		
		
				
						
								
										g.
										       
								
						
						Press “OK”.
				
		
		
				
						
								
										2.
										       
								
						
						
								Ensure your user account is included in the Debugger User group.
						
				
		
		
				
						
								
										a.
										       
								
						
				
				
						
								Note: It appears this is not possible in certain versions of Vista, such as Home Premium.  Click the following link for more information:  
						
						
								http://windowshelp.microsoft.com/Windows/en-US/Help/0faddcfc-e2a9-4297-a429-3f7e83fe6e361033.mspx
						
						.
				
		
		
				
						
								
										3.
										       
								
						
						
								Ensure that .NET 1.1 **SP1** is properly installed.
						
				
		
		
				
						
								
										·
										         
								
						
						
								Vista does not include .NET v1.1 by default.
						
				
		
		
				
						
								
										·
										         
								
						
						
								Because .NET 1.1 is not included by default, .NET v1.1 *SP1* is also not included.
						
				
		
		
				
						
								
										·
										         
								
						
						
								Without SP1, W3WP.exe will crash when running an appPool under v1.1 due to DEP
						
				
		
		
				
						
								
										·
										         
								
						
						
								To check this, make sure that "c:\Windows\Microsoft.NET\Framework\v1.1.4322\mscorsvr.dll" is version "1.1.4322.2032" or higher.
						
				
		
		
				
				
		
		
				
						
								
										·
										         
								
						
						
								Unless you are 100% sure that SP1 for .NET is installed, you *really* should double-check this.
						
				
		
		
				
						
								
										·
										         
								
						
				
				
						If you need to install .NET 1.1 SP1, you can download the upgrade here: 
						
								http://www.microsoft.com/downloads/details.aspx?familyid=A8F5654F-088E-40B2-BBDB-A83353618B38&displaylang=en.
						
				
		
		
				
						
								
										4.
										       
								
						
						Enable IIS 6.0 compatiblity.
				
		
		
				
						
								
										a.
										       
								
						
						
								Open "Control Panel".
						
				
		
		
				
						
								
										b.
										      
								
						
						
								Double-click "Programs and Features".
						
				
		
		
				
						
								
										c.
										       
								
						
						
								Expand "Internet Information Services".
						
				
		
		
				
						
								
										d.
										      
								
						
						
								Click on “Turn Windows Features On and Off”.
						
				
		
		
				
						
								
										e.
										      
								
						
						
								Expand "Web Management Tools".
						
				
		
		
				
						
								
										f.
										        
								
						
						
								Check “IIS 6 Management Compatibility”.
						
				
		
		
				
				
		
		
				
						
								
										5.
										       
								
						
						
								Enable ASP.NET Application Development Features, if not already done so.
						
				
		
		
				
						
								
										a.
										       
								
						
						
								Open "Control Panel".
						
				
		
		
				
						
								
										b.
										      
								
						
						
								Double-click "Programs and Features".
						
				
		
		
				
						
								
										c.
										       
								
						
						
								Expand "Internet Information Services".
						
				
		
		
				
						
								
										d.
										      
								
						
						
								Click on “Turn Windows Features On and Off”.
						
				
		
		
				
						
								
										e.
										      
								
						
						Expand “World Wide Web Services”.
				
		
		
				
						
								
										f.
										        
								
						
						Expand “Application Development Features”.
				
		
		
				
						
								
										g.
										       
								
						
						Check “ASP.NET”.
				
		
		
				
						
								
										                                                 
										Note: 
										 
								
						
						“.NET Extensibility”, “ISAPI Extensions”, and “ISAPI Filters” are dependencies, so they become automatically checked.
				
		
		
				
						
								
										6.
										       
								
						
						
								Register v1.1 with IIS.
						
				
		
		
				
						
								
										a.
										       
								
						
						
								Open a CMD prompt.
						
				
		
		
				
						
								
										b.
										      
								
						
						
								Change your directory to c:\Windows\MIcrosoft.net\Framework\v1.1.4322.
						
				
		
		
				
						
								
										c.
										       
								
						
						
								Run "aspnet_regiis -ir -enable".
						
				
		
		
				
						
								
										·
										   
								
						
						
								"ir" registers v1.1 with IIS but doesn't change any existing script mappings.
						
				
		
		
				
						
								
										·
										   
								
						
						
								"enable" marks aspnet_isapi.dll as "Allowed" under "ISAPI and CGI Restrictions".
						
				
		
		
				
						
								
										·
										   
								
						
						
								aspnet_regiis should also create a new AppPool under "Application Pools" called "ASP.NET 1.1" that is configured with the "Classic" pipline, and "Enable32BitAppOnWin64" set to true if a 64-bit OS.
						
				
		
		
				
				
		
		
				
						
								
										7.
										       
								
						
						
								Make the new "ASP.NET 1.1" appPool the default.
						
				
		
		
				
						
								
										a.
										       
								
						
						
								Open the IIS manager.
						
				
		
		
				
						
								
										b.
										      
								
						
						
								Select the "Web Sites" folder.
						
				
		
		
				
						
								
										c.
										       
								
						
						
								Under "Actions" on the upper right, click "Set Web Site Defaults...".
						
				
		
		
				
				
		
		
				
						
								
										d.
										      
								
						
						
								Change the "Application Pool" setting to "ASP.NET 1.1".
						
				
		
		
				
				
		
		
				
						
								
										8.
										       
								
						
						
								**Alternative step to 7** - Change the AppPool to "ASP.NET 1.1" after creating the ASP.NET project instead of making it the default
						
				
		
		
				
						
								
										a.
										       
								
						
						
								Create the v1.1 ASP.NET project via Visual Studio. Attempting to run the project at this point will fail if the 1.1 appPool is not the default.
						
				
		
		
				
						
								
										b.
										      
								
						
						
								Open the IIS manager.
						
				
		
		
				
						
								
										c.
										       
								
						
						
								Right-click the newly create application directory and choose "Advanced Settings".
						
				
		
		
				
						
								
										d.
										      
								
						
						
								Change the "Application Pool" to "ASP.NET 1.1".
						
				
		
		
				
						
								
										e.
										      
								
						
						
								Go back to Visual Studio and attempt to run/debug project.
						
				
		
		
				
						
								
										9.
										       
								
						
				
				
						Adjust ISAPI and CGI restrictions in IIS.
				
		
		
				
						
								
										a.
										       
								
						
						
								
										Go into IIS
								
						
				
				
						7.0 manager and select your server.
				
		
		
				
						
								
										b.
										      
								
						
				
				
						Select ISAPI and CGI restrictions.
				
		
		
				
				
		
		
				
						
								
										c.
										       
								
						
				
				
						Ensure ASP v1.1 has the restriction set to Allowed.
				
		
		
				
				
		
		
				
						
								
										10.
										   
								
						
						
								Launch Visual Studio 2003 as Administrator.
						
				
		
		
				
						
								
										11.
										   
								
						
						
								Create a simple web application with some event handling to test debugging (a button that displays text in a label control is what I used to test).
						
				
		
		
				
						
								
										12.
										   
								
						
						Attach to the w3wp.exe process.
				
		
		 
		
				
						
								
										13.
										   
								
						
						Set breakpoints where appropriate.
				
		
		
				
						
								
										14.
										   
								
						
						Launch the website in a browser (eg. 
				
				
						http://localhost/YourWebApp/YourPage.aspx
				
				).
		
		
				
						
								
										15.
										   
								
						
						Ensure your breakpoints are being hit.
				
		
		
				
						
								
										16.
										   
								
						
						
								That’s it!  
								Happy coding.
						
				
		
		 
]]></description> 
					<pubDate>Thu, 17 Jan 2008 23:14:48 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2008/1/17/using-vs7-in-vista/</guid>
				</item>
			
				<item>
					<title>KeyLimeTie Mass Emailer - Free!</title> 
					<link>http://keylimetie.com/blog/2008/1/2/keylimetie-mass-emailer-free/</link> 
					<description><![CDATA[Over the years, we have built a number of Mass Emailing applications for customers (some web, some windows apps).I took a recent version I created and added more to it and am now making it available to anyone.Download ApplicationFeatures - Use email list with custom fields from database or cut-and-paste in an email list. - Validate email addresses and view invalid email addresses. - Specify all fields of an email including From, Reply To, CC, BCC, Subject and Body. Attachments coming soon! - Allows for custom fields in the title and body. - Send test email to verify formatting accuracy.]]></description> 
					<pubDate>Thu, 03 Jan 2008 02:42:02 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2008/1/2/keylimetie-mass-emailer-free/</guid>
				</item>
			
				<item>
					<title>How to Communicate between ASP.NET and Flash</title> 
					<link>http://keylimetie.com/blog/2007/12/18/how-to-communicate-between-aspnet-and-flash/</link> 
					<description><![CDATA[Ever wonder how to send data back and forth between ASP.NET and Flash?About a year ago, we designed and built the DIY Floor Plan website (http://www.diyfloorplan.com). We needed the ability to send data between the Flash Floor Plan Designer and the ASP.NET web pages that saved the data to the database. We wanted the floor plan designer to be as "dumb" as possible...simply design the floor plan and allow the ASP.NET application manage the data. Here's some quick code snippets that will show you how to do it very easily.ViewFloorPlan.aspxThis page displays the public, non-editable version of the floor plan. The important thing here is that we put the Floor Plan GUID in a Flash Parameter. We use a GUID to prevent users from seeing floor plans that are not publicly available by the floor plan administrator. The Flash application uses the GUID as the key to communicate with the ASP.NET application.1"text/javascript">
2    var so = new SWFObject("/flash/map_client.swf", "map_client", "775", "650", "6", "#ececec");
3    so.addParam("menu", "false");
4    so.addParam("quality", "high");
5    so.addParam("wmode", "transparent");
6    so.addParam("allowScriptAccess", "sameDomain");
7    so.addParam("movie", "/flash/map_client.swf");
8    so.addParam("bgcolor", "#ffffff");
9    so.addParam("FlashVars", "FloorPlanGUID=");
10    so.write("flashcontent1");
11FlashGetData.aspxThis page is used by the Flash application to get data. The ASPX portion of this web page has no HTML or controls. When processing the Flash application's request, we output the data it needs in the HTML in a name-value pair. A little explanation...this page is called for the floor plan XML or an individual booth's details (name, address, etc.). After calling the database to get the data, it's written to the output HTML as field=value.1public partial class FlashGetData : System.Web.UI.Page
2{
3protected void Page_Load(object sender, EventArgs e)
4    {
5       if (Request.QueryString["Mode"] != null)
6        {
7            try8            {
9                //Extract mode10                Enums.ModeEnum mode =                            (Enums.ModeEnum)int.Parse(Request.QueryString["Mode"].ToString());
1112                //Process based on mode13                DataSet ds = null;
14                DataRow row;
15                if (mode == Enums.ModeEnum.RequestFloorPlan)
16                {
17                    //Extract Querystring parameters18                    string floorPlanGUID = Request.QueryString["FloorPlanGUID"].ToString();
1920                    //Get the data21                    ds = FloorPlans_BLL.SelectFloorPlansByFloorPlanGUID(new Guid(floorPlanGUID));
22                    row = ds.Tables[0].Rows[0];
23                    Response.Write("FloorPlanXML=" + row["FloorPlanXML"].ToString());
24                }
25                else if (mode == Enums.ModeEnum.RequestCompanyDetails)
26                {
27                    //Extract Querystring parameters28                    string floorPlanGUID = Request.QueryString["FloorPlanGUID"].ToString();
29                    string boothID = Request.QueryString["BoothID"].ToString();
3031                    //Get the data32                    ds = Companies_BLL.SelectCompaniesByFloorPlanIDBoothID(                               new Guid(floorPlanGUID), boothID);
33                    Response.Write("CompanyDetails=" + BuildCompanyDetails(boothID, ds));
34                }
35            }
36            catch (Exception ex)
37            {
38                Helpers.ProcessException(ex);
39            }
40        }
41    }
42}FlashSaveData.aspxThis page is used in the administration area. Again, the ASPX portion of this web page has no HTML or controls.The Flash movie executes a command like: xmlDoc.sendAndLoad("FlashSaveData.aspx?FloorPlanGUID=xxx-xxx-xxx-xxx", returnXML, "POST");The important point of this code is Line 19. The Flash application posts data in the Request stream.1public partial class FlashSaveData : System.Web.UI.Page
2{
3protected void Page_Load(object sender, EventArgs e)
4    {
5        //The Flash movie executes a command like:6        //xmlDoc.sendAndLoad("FlashSaveData.aspx?FloorPlanGUID=xxx-xxx-xxx-xxx",                    returnXML, "POST");78         XmlDocument doc = null;
9         FloorPlans floorplans = null;
10        FloorPlanCompanies fpc = null;
11        DataSet ds = null;
12        try13        {
14            if (Request.QueryString["FloorPlanGUID"] != null)
15            {
16                //Extract GUID and XML17                string floorPlanGUID = Request.QueryString["FloorPlanGUID"].ToString();
18                doc = new XmlDocument();
19                doc.Load(Request.InputStream);
2021                //Get the FloorPlan row22                ds = FloorPlans_BLL.SelectFloorPlansByFloorPlanGUID(new Guid(floorPlanGUID));
23                DataRow row = ds.Tables[0].Rows[0];
2425                //Build FloorPlans object26                floorplans = new FloorPlans();
27                floorplans.FloorPlanID = Int32.Parse(row["FloorPlanID"].ToString());
28                floorplans.FloorPlanGUID = new Guid(row["FloorPlanGUID"].ToString());
29                floorplans.UserID = Int32.Parse(row["UserID"].ToString());
30                floorplans.Title = row["Title"].ToString();
31                floorplans.URL = row["URL"].ToString();
32                floorplans.FloorPlanXML = doc.InnerXml;
33                floorplans.Active = (bool)row["Active"];
34                floorplans.RewriterID = Int32.Parse(row["RewriterID"].ToString());
3536                //Make sure all booths are now in the database37                XmlNodeList objNodes = doc.SelectNodes("./floorplan/booths/boothtxt");
38                foreach (XmlNode objNode in objNodes)
39                {
40                    fpc = new FloorPlanCompanies();
41                    fpc.FloorPlanID = Int32.Parse(row["FloorPlanID"].ToString());
42                    fpc.BoothID = objNode.InnerXml;
43                    fpc.CompanyID = 0;
44                    FloorPlanCompanies_BLL.SaveFloorPlanCompanies(fpc, false, null);
45                }
4647                //Save to database48                FloorPlans_BLL.UpdateFloorPlans(floorplans);
49            }
50            else51                throw new Exception("FloorPlanGUID missing");
52        }
53        catch (Exception ex)
54        {
55            Helpers.ProcessException(ex);
56        }
57        finally58        {
59            if (ds != null)
60            {
61                ds.Dispose();
62                ds = null;
63            }
64            fpc = null;
65            floorplans = null;
66            doc = null;
67        }
68    }
69}]]></description> 
					<pubDate>Wed, 19 Dec 2007 05:29:46 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/12/18/how-to-communicate-between-aspnet-and-flash/</guid>
				</item>
			
				<item>
					<title>How to make an AJAX Postback with JavaScript</title> 
					<link>http://keylimetie.com/blog/2007/12/3/how-to-make-an-ajax-postback-with-javascript/</link> 
					<description><![CDATA[Recently, we were working on a project that required us to make an AJAX postback with a table cell (TD) onclick event. We were "forced" to do this because the webpage designer wanted the search results displayed in a table and the TD's had onmouseover, onmouseout and onmouseclick events. The way he designed it was very nice and we didn't want to change it because AJAX for .NET didn't natively support the TD click event.We quickly searched the web for an answer and couldn't find anything. Over the past few months many others asked how to do it too, but nobody could provide an answer. It's really not that difficult...you just need to be a little creative and think how AJAX works in ASP.NET.In our project, we were binding location search results to a Repeater. In the onclick event, we added code to make a call to JavaScript function "makeAJAXPostback" and passed the ID. Originally, we tried to make a call to __doPostBack, but that forces a full page postback:1"rptSearchResults" runat="server">
2    
3        "100%" border="0" cellpadding="0" cellspacing="4">
4            
5                
6                    class="agentbox" onmouseover="style.backgroundColor='#e0e8f3';"                              onmouseout="style.backgroundColor='#f1f1f1';"7                        onclick="makeAJAXPostback('ID")%>')">
8                        "DisplayName")%>
9                        
10                        "Address1")%>
11                        
12                        "City")%>
13                        
14                        "StateIDCode")%>
15                        "Zip")%>
16                        
17                        "Phone")%>
18                    
19                
20        
21    
22
23At the bottom of the page, we added a the "makeAJAXPostback" function.We also added a hidden field and a hidden HTML submit button:1            "submit" id="btnTDClicked" name="btnTDClicked" style="display: none" />
2            "hidden" id="hidTDClickID" name="hidTDClickID" />
3        
4    
5    "text/javascript">
6        function makeAJAXPostback(TDClickID)
7        {
8            document.forms[0].hidTDClickID.value = TDClickID;
9            document.forms[0].btnTDClicked.click();
10        }
11    
12
13When the TD cell is clicked, the "makeAJAXPostback" function is called, the ID is put in the hidden field and the hidden button is clicked. Because the AJAX Toolkit handles all form postbacks, the button click is automatically made via AJAX.All that's left is to handle the postback on the server. In Page_Load, we simply check if the hidden field is populated and process accordingly:1//Handle TD Clicked Event when user clicks search results2if (Request.Form["hidTDClickID"] != null &&
3    Request.Form["hidTDClickID"].ToString() != "")
4    TDClicked(int.Parse(Request.Form["hidTDClickID"].ToString()));]]></description> 
					<pubDate>Mon, 03 Dec 2007 22:00:21 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/12/3/how-to-make-an-ajax-postback-with-javascript/</guid>
				</item>
			
				<item>
					<title>Convert Plain Text to MD5 Hash</title> 
					<link>http://keylimetie.com/blog/2007/11/20/convert-plain-text-to-md5-hash/</link> 
					<description><![CDATA[		Nothing groundbreaking here, but if you need to know how to convert plain text to an MD5 Hash, here you go:
		1using System;
2using System.Security.Cryptography;
3using System.Text;
45public static string ConvertToMD5(string plainText)
6{
7    byte[] input = Encoding.UTF8.GetBytes(plainText);
8    byte[] output = MD5.Create().ComputeHash(input);
9    return Convert.ToBase64String(output).Trim();
10}
		/html>]]></description> 
					<pubDate>Wed, 21 Nov 2007 04:08:32 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/11/20/convert-plain-text-to-md5-hash/</guid>
				</item>
			
				<item>
					<title>Enable File Upload on an AJAX Webpage</title> 
					<link>http://keylimetie.com/blog/2007/11/8/enable-file-upload-on-an-ajax-webpage/</link> 
					<description><![CDATA[File uploads do not work when doing async postbacks due to security restrictions. Because of this, we have to add a PostBackTrigger. PostbackTriggers enable controls inside an UpdatePanel to cause a postback instead of performing an asynchronous postback. Here's a code snippet that shows how to accomplish this.                                                                                             By adding the PostbackTrigger, you can mix controls that make AJAX calls with controls that require the postback and maintain the good user experience. ]]></description> 
					<pubDate>Fri, 09 Nov 2007 03:51:35 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/11/8/enable-file-upload-on-an-ajax-webpage/</guid>
				</item>
			
				<item>
					<title>Speed Up Your Site! 8 ASP.NET Performance Tips</title> 
					<link>http://keylimetie.com/blog/2007/10/11/speed-up-your-site-8-aspnet-performance-tips/</link> 
					<description><![CDATA[
		I see these "Top 10 Ways..." articles all the time, but this one was the first in a while that didn't restate what all of the other ones talk about.Website: http://www.sitepoint.com/article/aspnet-performance-tips1. Determine what to optimizeDiscusses quick, simple techniques such as tracing.2. Decrease the size of the view stateThis one really got my attention. ViewState is so powerful, but can kill your website too. With AJAX gaining so much momentum, ViewState compression is a must. The article even gives you the C# class! Storing ViewState on the server can also be a great technique.3. Decrease the bandwidth that my site usesHTTP Compression has been around for several years. With IIS 6.0, it requires no 3rd party controls or custom code. Why wouldn't you enable it today?4. Improve the speed of my siteOutput caching can improve site speed very quickly and easily. Nothing new here.5. Refresh cache when the data changesDepending on how you bind data to objects or store cache, this tip may or may not apply to you. But definitely worth reading.6. Gain more control over the ASP.NET cacheUsing the Cache class/object is a great technique, but only when it makes sense...do not overuse it.7. Speed up database queriesWe have helped many clients speed up their website throughout the years. Evaluating and optimizing the database is one of the easiest and best bang for your buck approaches. Just run down the list: Indexes, Stored Procs, Views, locking, etc.8. Troubleshoot slow queriesA quick guide to understanding execution plans.
]]></description> 
					<pubDate>Thu, 11 Oct 2007 17:17:50 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/10/11/speed-up-your-site-8-aspnet-performance-tips/</guid>
				</item>
			
				<item>
					<title>PayPal Payment Data Transfer (PDT) WebControls Fix</title> 
					<link>http://keylimetie.com/blog/2007/9/4/paypal-payment-data-transfer-pdt-webcontrols-fix/</link> 
					<description><![CDATA[Over the past several years, we have implemented PayPal into our websites and many
of our customer websites. Since PayPal created their 
    Developer Program, the methods to access PayPal shopping carts and checkout
has continued to grow. There are easy a half dozen ways to do it today 
    [Learn More]. One popular method is the 
        Payment Data Transfer (PDT) program. Back on 1/28/2006, I blogged about
how to easily implement PDT into your website.


Problem: Throughout the life of the PDF program, several versions
of the PayPal WebControls have been released. The most recent version is v1.0.22.19341.
But there's a problem with the release that PayPal never resolved. When using the
DLLs and .NET Web Controls to test in the Sandbox environment, the UseSandbox property
is always ignored and the Postaction is always set to the Production environment.
This makes it impossible to test in their Sandbox environment.


Solution
We created a very simple class to override the PostAction property. See code below.

Download code


using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using PayPal.Web.Controls;

namespace PayPalCustom
{
    public class CustomUploadCompleteCartButton : UploadCompleteCartButton
    {
        public override string PostAction
        {
            get
            {
                return
this.UseSandbox ?
                    "https://www.sandbox.paypal.com/cgi-bin/webscr"
:
                    "https://www.paypal.com/cgi-bin/webscr";
            }
        }
    }
}

To implement into your website:
1. Add PayPalCustom.dll as a Reference in your application.
2. Change the "Register" tag at the top of your page to:

3. Change the UploadCompleteCartButton WebControl tag to



]]></description> 
					<pubDate>Tue, 04 Sep 2007 17:16:52 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/9/4/paypal-payment-data-transfer-pdt-webcontrols-fix/</guid>
				</item>
			
				<item>
					<title>PayPal PDT Sandbox Setup</title> 
					<link>http://keylimetie.com/blog/2007/8/1/paypal-pdt-sandbox-setup/</link> 
					<description><![CDATA[I recently implemented a PayPal checkout solution using Payment Data Transfer (PDT) to retrieve the transaction details. 
Testing the transaction process required using PayPal Sandbox, which I have used before and for which I already had my acccount 
set up. But when my customer wanted to do some testing, I had them set up their own Sandbox account, and was 
reminded that the initial setup is not simple. Eventually, I had to provide step by step instructions to get them up and
running correctly.

Here are those instructions for anyone needing to go through this for the first time:
1. Go to https://developer.paypal.com/ and create a new PayPal Developer 
account. After confirming the account, log in and you will see:
        - Tab for Test Accounts – this is where you create Buyer and Seller accounts. A Seller account 
    provides you with a fake online store, and a Buyer account allows you to make fake purchases from that store.
        - Tab for Test Email – this is where all the order/payment emails are sent during test purchases. 
    The emails are contained within the Sandbox environment, not sent to external email accounts.
        - Tab for API Credentials – for a PDT application, ignore this tab completely. There is an Identity 
    Token here, but it is not the one needed for the "PayPalPDTID” in the web.config. There is also a seller password here, 
    but it is not the one you will use during testing.
2. In the upper right corner, click “Enter Sandbox”.
        - Log in to Sandbox using the Seller Test Account credentials. For PDT to work, go to “Profile” 
    tab, then “Selling Preferences”, then “Website Payment Preferences” and confirm you have the following settings:
            “Auto Return for Website Payments” is on, return URL is set to 
        http://www.yoursite.com/PDTHandler.aspx (or whatever page you use to process the transaction details.
            “Payment Data Transfer” is on. Note that this is where you get the Identity Token that 
        should be used in the web.config.

Back in the project, you need to open the web.config and check these settings:

appSettings>
	add key="RootURL" value="http://localhost:xxxxx/ProjectName/"/>
		   
	!-- Sandbox Settings -->
	add key="PayPalServer" value="https://www.sandbox.paypal.com/cgi-bin/webscr"/>
	add key="UseSandbox" value="true"/>
	add key="PayPalEmailAddress" value="Seller email address used to login to Sandbox"/>
	add key="PayPalPDTID" value="Identity Token from the Website Payment Preferences"/>		
appSettings>

You are finally ready to run the project and make a purchase. When it redirects to PayPal, make sure it goes to 
https://www.sandbox.paypal.com/cgi-bin/webscr and login 
using the Buyer Test Account credentials. Complete the purchase and wait for it to redirect back to the project. You should 
have a message page advising that the transaction failed or was completed.

Finally, you can go back to https://developer.paypal.com/, enter Sandbox, 
login using the Seller credentials, and under My Account - History, see a report of all the transactions posted.]]></description> 
					<pubDate>Wed, 01 Aug 2007 23:16:08 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/8/1/paypal-pdt-sandbox-setup/</guid>
				</item>
			
				<item>
					<title>Some Design Principles To Consider</title> 
					<link>http://keylimetie.com/blog/2007/7/24/some-design-principles-to-consider/</link> 
					<description><![CDATA[
		I came across an interesting set of principles that you might want to keep in mind the next time you set out to design an application, a website, or even improve your daily life. They are The Laws of Simplicity and were conceived by John Maeda, an artist and noted computer scientist from the MIT Media Lab. He compiled them in a short, 100-page book (and posted them on his website as well). I found them in a back issue of Wired magazine, in an article that applied them in a critique some new gadget. I have since found that they increasingly influence my own analysis of UIs and websites, and occassionally use them as the basis for discussions with clients to keep a design session on track.
		The Laws are:
		
				 1. Reduce - The simplest way to achieve simplicity is through thoughtful reduction of functionality.
				 2. Organize - Organization makes a system of many appear fewer.
				 3. Time - Savings in time feel like simplicity.
				 4. Learn - Knowledge makes everything simpler.
				 5. Differences - Simplicity and complexity need each other.
				 6. Context - What lies in the periphery of simplicity is de?nitely not peripheral.
				 7. Emotion - More emotions are better than less.
				 8. Trust - In simplicity we trust.
				 9. Failure - Some things can never be made simple.
				10. The One - Simplicity is about subtracting the obvious, and adding the meaningful.
		
		You can find a more detailed explanation of each law on his site
		 
		
				www.petermorano.com
		
		 
		 
]]></description> 
					<pubDate>Tue, 24 Jul 2007 17:17:11 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/7/24/some-design-principles-to-consider/</guid>
				</item>
			
				<item>
					<title>Build an iPhone friendly webpage</title> 
					<link>http://keylimetie.com/blog/2007/7/14/build-an-iphone-friendly-webpage/</link> 
					<description><![CDATA[
digg_url = "http://digg.com/apple/Build_an_iPhone_friendly_webpage_Sample_code_included";



		

I just got the new iPhone and it's amazing. What you see it doing in the commercials is accurate...and it does a lot more! So right away, I want to know how to implement my own software. Maybe start developing some 3rd party applications. I researched a little and found out no iPhone Software Development Kit (SDK) is available. It seems like Apple is instead telling people to develop applications as webpages. But then you cannot actually interact with the iPhone...and you cannot access the iPhone database (Contacts, Favorites, etc.).I searched a bit more and found the following sample webpage released by Apple:http://developer.apple.com/samplecode/Puzzler/View webpage with your iPhone:http://www.iarchitect.net/Uploads/126/index.htmlNote: When trying to view the webpage in a standard browser (IE, Firefox), it doesn't display much. The weird thing is that if you click "Print Preview", you'll see the game.Description"Puzzler" is a fun and interactive game that illustrates the use of web standards and JavaScript for the iPhone. This application makes advanced usage of mouse-handlers for user-input.To play the game simply double-click or double-tap on any set of 2 or more balls of the same color that are touching. The balls will disappear and any balls above or to the left of the balls you just eliminated will shift into new positions. The goal is to clear all the balls from the screen.ScreenshotsClick any image to see a larger version



  Navigate to iArchitect.net
  Click into this Blog
  Start Game

 



  Tap circles with finger
  All cleared. You win!
]]></description> 
					<pubDate>Sat, 14 Jul 2007 23:21:06 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/7/14/build-an-iphone-friendly-webpage/</guid>
				</item>
			
				<item>
					<title>I Forgot The sa Account Password!</title> 
					<link>http://keylimetie.com/blog/2007/7/12/i-forgot-the-sa-account-password/</link> 
					<description><![CDATA[
		At one time or another, we will all find ourselves trying to remember the sa password. Now, thanks to Rodney Landrum's article and the sp_help_revlogin stored procedure, there is an easy way to deal with this.
		You can find his article here
		 
		
				www.petermorano.com
		
]]></description> 
					<pubDate>Thu, 12 Jul 2007 16:47:12 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/7/12/i-forgot-the-sa-account-password/</guid>
				</item>
			
				<item>
					<title>Use Dynamic Connection Strings MDAAB</title> 
					<link>http://keylimetie.com/blog/2007/7/4/dynamic-connection-strings-microsoft-daab/</link> 
					<description><![CDATA[I recently came across a situation where I needed to pass the Microsoft Data Access Application Blocks a dynamic connection string. Out of the box, the DAAB does not support this. Solution: Create a simple method that accepts a connection string and return a Database object. Code Before:Database db = DatabaseFactory.CreateDatabase();Code After:Database db = CustomDatabaseFactory.CreateDatabase(connstring);Class Code:1using System;
2using System.Collections.Generic;
3using System.Data.Common;
4using System.Text;
5using Microsoft.Practices.EnterpriseLibrary.Data;
6namespace Satisfyd.DataAccessLayer
7{
8//This class is used to dynamically set the connection string9//while using the Microsoft Data Application Blocks10publicstaticclass CustomDatabaseFactory
11    {
12staticreadonly DbProviderFactory dbProviderFactory =
13            DbProviderFactories.GetFactory("System.Data.SqlClient");
1415publicstatic Database CreateDatabase(string connectionString)
16        {
17returnnew GenericDatabase(connectionString, dbProviderFactory);
18        }
19    }
20}]]></description> 
					<pubDate>Wed, 04 Jul 2007 16:00:24 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/7/4/dynamic-connection-strings-microsoft-daab/</guid>
				</item>
			
				<item>
					<title>Re-Enable A Disabled SQL Server 2005 Service Broker</title> 
					<link>http://keylimetie.com/blog/2007/6/27/re-enable-a-disabled-sql-server-2005-service-broker/</link> 
					<description><![CDATA[
		If you are caching data using SQL Cache Dependency with the SqlCacheDependency parameter set to "CommandNotification", and then restore or detach/attach your database (say, during a deployment), you will likely see this error: 
		
				
						"The SQL Server Service Broker for the current database is not enabled, and as a result query notifications are not supported. Please enable the Service Broker for this database if you wish to use notifications." 
				
		
		This is caused by the fact that the service broker is disabled automatically during these operations. To re-enable it, you need to run the following:
		
		
		
				   ALTER DATABASE 
				YOUR_DATABASE 
				SET ENABLE_BROKER
		
		 
		 
		
				www.petermorano.com
		
]]></description> 
					<pubDate>Wed, 27 Jun 2007 23:56:53 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/6/27/re-enable-a-disabled-sql-server-2005-service-broker/</guid>
				</item>
			
				<item>
					<title>Acropolis: The Future Of Windows Client Development</title> 
					<link>http://keylimetie.com/blog/2007/6/21/acropolis-the-future-of-windows-client-development/</link> 
					<description><![CDATA[
		Microsoft has released the Acropolis CTP, a set of tools and components that help developers quickly assemble applications from loosely-coupled parts and services. With Acropolis you will be able to:
		
				
						
								
										
												Quickly create WPF enabled user experiences for your client applications. 
										
										
												Build client applications from reusable, connectable, modules that allow you to easily create complex, business-focused applications in less time. 
										
										
												Integrate and host your modules in applications such as Microsoft Office, or quickly build stand-alone client interfaces. 
										
										
												Change the look and feel of your application quickly using built-in themes, or custom designs using XAML. 
										
										
												Add features such as workflow navigation and user-specific views with minimal coding. 
										
										
												Manage, update, and deploy your application modules quickly and easily.
										
								
								
										David Hill has put together a short video walkthrough of using Acropolis: 
								
								
										
												
														
																
																		Acropolis Video
																
														
												
										
								
								
										You can download the CTP here:
								
								
										
												
														
																
																		Acropolis CTP Download
																
														
												
										
								
								
										
										
										 
								
						
				
		
]]></description> 
					<pubDate>Thu, 21 Jun 2007 20:21:36 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/6/21/acropolis-the-future-of-windows-client-development/</guid>
				</item>
			
				<item>
					<title>How to Add a Digg Link to Your Website</title> 
					<link>http://keylimetie.com/blog/2007/6/3/how-to-add-a-digg-link-to-your-website/</link> 
					<description><![CDATA[If you're not familiar with Digg.com, you might want to check it out.What is Digg?"Digg is a user driven social content website. Ok, so what the heck does that mean? Well, everything on Digg is submitted by our community (that would be you). After you submit content, other people read your submission and Digg what they like best. If your story rocks and receives enough Diggs, it is promoted to the front page for the millions of visitors to see.
What can you do as a Digg user? Lots. Every person can digg (help promote), bury (help remove spam), and comment on stories... you can even Digg and bury comments you like or dislike. Digg also allows you to track your friends' activity throughout the site — want to share a video or news story with a friend? Digg it!" 
I have been visiting Digg at least 2-3 times per week to read the quick posts. I usually jump directly to "Top in 24 Hours" page. This page usually has some really interesting links: http://www.digg.com/news/popular/24hoursIf you decide to post a link, be sure your server can handle the hits. Everyday, sites crash due to too many hits too fast from Digg users. Or if your hosting provider has limits on bandwidth, you might lose your account all together. Fortunately, we have our own servers and can handle this type of traffic.Back to the topic of this blog...if you decide to post a link on Digg, here's the snippet of code you need to add to your website to add the Digg Link to your website:    digg_url = "digg url to your link";http://digg.com/tools/diggthis.js" type="text/javascript">For example:    digg_url = "http://digg.com/software/20_Promo_Code_SGMAY07_good_for_1_week";http://digg.com/tools/diggthis.js" type="text/javascript">results in this:

digg_url = "http://digg.com/software/20_Promo_Code_SGMAY07_good_for_1_week";



]]></description> 
					<pubDate>Sun, 03 Jun 2007 19:56:56 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/6/3/how-to-add-a-digg-link-to-your-website/</guid>
				</item>
			
				<item>
					<title>Google Street View</title> 
					<link>http://keylimetie.com/blog/2007/5/28/google-street-view/</link> 
					<description><![CDATA[Within the past few days, Google has released a new feature to its Google Maps website. This new feature, Street View, is only available in a few cities like New York, Miami, Denver, San Francisco and Las Vegas. Not sure how it can be useful, but it is kind of cool. Just zoom into the street level and click on the blue outlined street. You will then see a photo view taken from a car.

View Las Vegas Street View

Screenshot:
]]></description> 
					<pubDate>Mon, 28 May 2007 06:00:00 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/5/28/google-street-view/</guid>
				</item>
			
				<item>
					<title>unescape() in Code Behind</title> 
					<link>http://keylimetie.com/blog/2007/5/22/unescape-code-behind/</link> 
					<description><![CDATA[Ever have the need to unescape a string in your code-behind?
 Here's how:
value = Microsoft.JScript.GlobalObject.unescape(value);

Just remember to add a reference to Microsoft.JScript in your project.
You now have access to all javascript functions in your code-behind.]]></description> 
					<pubDate>Tue, 22 May 2007 06:00:00 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/5/22/unescape-code-behind/</guid>
				</item>
			
				<item>
					<title>Some cool websites we&amp;quot;ve recently found...</title> 
					<link>http://keylimetie.com/blog/2007/5/17/cool-websites/</link> 
					<description><![CDATA[Some cool websites we've recently found...

kuler
http://kuler.adobe.com
"Explore, create and share color themes. Use it online or download themes to use
    with Adobe CS2 and 3."
Basically, it's an interactive color theme designer. Download any of the 1,000+
themes which are rated by visitors, or creeate your own.


Simply Google
http://lloydi.com/blog/simplygoogleoriginal.htm
The owner of this website basically put most (if not all) Google features and websites
into one easy to use page.


SitePoint Contests
http://www.sitepoint.com/contests/
Over the past 10 years, we have tried all kinds of approaches to web design. Some
worked out, but most do not. Here's the pros and cons of what we have tried and
some comments on each approach:

    Professional designers
        Pros: Original work. Direct communication with designer.
        Cons: Expensive. Only get ideas from one designer, not a pool or designers. Depending
        on the person, their availability might be limited.
        Comments: Unless the customer specifically requires it, we will not use a designer
        unless we know the person very well and he/she has consistently developed excellent
        work and is good to work with. This means he/she needs to stick to the project schedule,
        be available during core business hours and keep us up to date with progress.
        
    
    Template websites
        Pros: Very cheap ($50-$70 for Flash, PSD, HTML & CSS). 1,000 of designs to choose
        from. A lot of the designs are very professional.
        Cons: Your website design will not be unique.
        Comments: For customers who have a decent budget and need a unique design, this
        is not an option. Templates work very well for businesses where the budget is tight
        and the website design doesn't have to be unique. And realistically, what's the
        chances of you seeing your website somewhere else...maybe 1 in a million? Also you
        do get the PSD, so you can easily modify parts of it. We still use templates all
        the time. When we choose a template, we buy it for the overall look-and-feel. Most,
        if not all, of the images are swapped out with our own. And of course the logo is
        replaced with ours.
        
    
    Crowdsourcing websites
        Pros: Affordable (Price amount + $25 flat fee or 10%). Unique designs. Designers
        fight over prize money.
        Cons: There's a chance only a few designers may participate in your contest and
        you won't have anything good to choose from.
        Comments: We have been using 
            Design Outpost for a few months now (posted 6 projects). For the most part,
        it has worked out well until my most recent project received only one entry the
        day before the project was supposed to end. We had to cancel it. Then we found SitePoint. So
        far, it's been great, but we have only posted two projects...a logo project that
        has received over 60 entries so far (ends tonight) and a template project that has
        received only 2 entries (but doesn't end for 3 for days).
    
]]></description> 
					<pubDate>Thu, 17 May 2007 06:00:00 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/5/17/cool-websites/</guid>
				</item>
			
				<item>
					<title>Cool Business Card Designs</title> 
					<link>http://keylimetie.com/blog/2007/5/8/cool-business-card-designs/</link> 
					<description><![CDATA[A few months ago, I renamed my company from New Vision to iArchitect. With any business name change comes the need for a new logo, new stationary, a new website and new business cards. Fortunately, I have been doing this long enough to create great relationships with excellent designers and also found great resources for one off jobs here and there. Today, I came across a great blog on "Cool Business Card Designs":http://creativebits.org/cool_business_card_designsI am not a very creative person, but the people who designed these business cards sure are.I thought I might share it with those of you who have businesses or are planning to start a new business. These kinds of touches can make a nice first impression.]]></description> 
					<pubDate>Tue, 08 May 2007 06:00:00 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/5/8/cool-business-card-designs/</guid>
				</item>
			
				<item>
					<title>AJAX Animated GIF</title> 
					<link>http://keylimetie.com/blog/2007/4/29/ajax-animated-gif/</link> 
					<description><![CDATA[

I have been doing a lot of work with the Microsoft AJAX Toolkit lately.
Most recently, I have implemented it on a major insurance website I am always adding features to.
I am also updating the iArchitect CMS to be 100% AJAX-enabled. Very soon, you will see it on this website.


If you're not familiar with AJAX, here's the Wikipedia definition.
Basically, it's the process of updating small portions of a webpage instead of refreshing the entire page. For example,
when you leave a comment to a blog on this website, instead of refreshing the entire page, I can now just refresh the comments area.
This presents a much more enjoyable user experience and speeds up the website.


When a portion of a webpage is being updated, you will see an animated image indicating so.
While working on these websites, I found the need to create custom animated images.
These are not easy to create...until now.
Visit the following link and you can create your own animated AJAX image in seconds!
http://www.ajaxload.info
]]></description> 
					<pubDate>Mon, 30 Apr 2007 04:12:00 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/4/29/ajax-animated-gif/</guid>
				</item>
			
				<item>
					<title>Google PageRank</title> 
					<link>http://keylimetie.com/blog/2007/4/26/google-page-rank/</link> 
					<description><![CDATA[A very interesting article on Google PageRank:http://searchengineland.com/070426-011828.php]]></description> 
					<pubDate>Fri, 27 Apr 2007 04:12:00 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/4/26/google-page-rank/</guid>
				</item>
			
				<item>
					<title>Simple XML Validator</title> 
					<link>http://keylimetie.com/blog/2007/3/24/simple-xml-validator/</link> 
					<description><![CDATA[I recently had the need to validate an XML document against its schema, so I quickly threw together this application.It includes the XSD document (schema) for the Google Sitemaps program.To use:1. Download the application2. Unzip the two files to a folder on your computer.3. Run the application and change the XSD location to where the "sitemap.xsd" file is located.4. Enter in the path of the XML document and click "Validate".The application will return with a success message or a list of error messages.]]></description> 
					<pubDate>Sat, 24 Mar 2007 17:19:00 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/3/24/simple-xml-validator/</guid>
				</item>
			
				<item>
					<title>20 Things To Remember For Good Web Copy</title> 
					<link>http://keylimetie.com/blog/2007/3/14/good-web-copy/</link> 
					<description><![CDATA[1. Tight writing. That doesn't mean bad or easy writing.2. Copy of about 600-800 words is better for SEO and catching the long tail of search.3. Title – Subject – Support, in that order, like subject, verb, object.4. Titles should be snappy and informative – clickable, but clear.5. Leads (first sentence or paragraph) should get to the point. Tell the reader what the article's about first thing.6. No fancy, wordy intros where it's not clear what you're talking about.7. Information beats fluff every time. Pretty is for books and newspapers (and only sometimes).8. Information does not beat style every time. Style keeps people awake.9. Sans serif fonts are easier and faster to read on computer screens.10. White space is awesome – even better than big, pretty pictures.11. Content should be scannable.12. Think in bullets and subtitles.13. People like lists.14. Pictures should be specific and informative, not generic, decorative and ad-like.15. Photos should be relevant to content.16. People in pictures should look friendly and approachable (and have their whole head).17. Photos should be full body if possible.18. Spell stuff right. It makes you look smarter.19. Grammar IS important. Unless you're not really a professional.20. Online press releases should be even tighter than Web copy.Source: WebProNews]]></description> 
					<pubDate>Thu, 15 Mar 2007 05:03:45 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/3/14/good-web-copy/</guid>
				</item>
			
				<item>
					<title>Sitemap Generator v4.1.1 Beta Available</title> 
					<link>http://keylimetie.com/blog/2007/3/13/sitemap-generator-v411-released/</link> 
					<description><![CDATA[Version 4.1.1 is now available with some bug fixes: - Scheduling Service may run multiple times if spidering process takes over 1 hour. - FTP cannot communicate with server in some rare scenarios. - Edit Results vertical scrollbar sometimes becomes disabled. - Spidering error message "Object reference not set" occurs when spidering stopped before completing.This is a beta release and has been tested.New users: I recommend all visitors who have not installed my Google software to install this beta version.Existing users: Please uninstall the current version and install this version. All websites and preferences will remain.Download Sitemap Generator v4.1.1]]></description> 
					<pubDate>Tue, 13 Mar 2007 06:45:09 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/3/13/sitemap-generator-v411-released/</guid>
				</item>
			
				<item>
					<title>Sitemap Generator v4.1 Released!!!</title> 
					<link>http://keylimetie.com/blog/2007/3/4/sitemap-generator-v41-released/</link> 
					<description><![CDATA[Version 4.1 Released with all of the features you asked for and much more!				Generate Google, Yahoo and HTML Sitemaps....and now RSS Feeds!Version 4.0 was released only one and a half weeks ago, but I've received a lot of great response.Because of all of the great feature requests, I decided to jump on them right away and get them out in a v4.1.Download it today and check it out.Download - Try it today for FREE!Download Sitemap Generator v4.1New Features in v4.1:- Preferences: Ability to specify the spider start directory.- Preferences: Ability to disable advertising- Preferences: Last Modified Date has been overhauled! Instead of just specifying a default date, your options are:"Use server's modified date" - While spidering, the application will read the webpage headers to get the last modified date (if available). This is the best option."Use today's date" - Especially useful when your server doesn't supply the last modified date and you want to schedule your updates."Let me specify the date" - Some people might still want to specify a default date.- Ability to export to RSS: Another format to publish your website! RSS is very popular and getting more attention everyday.]]></description> 
					<pubDate>Mon, 05 Mar 2007 04:39:51 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/3/4/sitemap-generator-v41-released/</guid>
				</item>
			
				<item>
					<title>Automating Database Maintenance in SQL Server 2005 Express</title> 
					<link>http://keylimetie.com/blog/2007/2/21/sql-2005-express-maintenance/</link> 
					<description><![CDATA[When building highly scalable applications, you need a powerful database. My database of choice right now is SQL Server 2005. Since a full SQL Server license costs a few thousand dollars per processor, I use SQL Server Express. Why not...it's free! It's basically the same thing as the full blown SQL Server 2005, except there are some limitations on memory, database capacity and other things I will not hit with the websites I build on the side. It also doesn't allow you Import/Export data which is a vey useful feature. That's OK, we can script our database updates. And finally, it doesn't include scheduled maintenance. This is not good. All websites and databases MUST be backed up daily in case of a disaster.So how do we implement this?I did a quick search on Google and found the following webpage:http://www.sqldbatips.com/showarticle.asp?ID=27Download SQL scriptBasically, it's a SQL script that does the maintenance tasks for you. Simply specify the parameters based on your needs and schedule it to run with Windows Task Scheduler. That's it!Example execute callThis call executes a Full Database Backup of all user databases to c:\backups.It also verifies the backups and reports to c: eports.It keeps the backups for 2 weeks and reports for 1 week  exec expressmaint      @database      = 'ALL_USER',       @optype         = 'DB',      @backupfldr    = 'c:\backups',      @reportfldr      = 'c: eports',      @verify          = 2,      @dbretainunit  = 'weeks',      @dbretainval   = 1,      @rptretainunit  = 'weeks',      @rptretainval   = 1,      @report          = 1Example Scheduled TaskOn my server, I have it scheduled with the following parameters. It's set to run everyday at 3am.Run: "C:\Program Files\Microsoft SQL Server\90\Tools\Binn\SQLCMD.EXE" -S.\SQLExpress -i"D:\DBBackups\UserFullBackup.sql"
		
				
						Start in: "C:\Program Files\Microsoft SQL Server\90\Tools\Binn"Additional comments1. When I ran the script for the first time, I received the following error:
				
						SQL Server blocked access to procedure 'sys.sp_OACreate' of component 'Ole Automation Procedures' because this component is turned off as part of the security configuration for this server. A system administrator can enable the use of 'Ole Automation Procedures' by using sp_configure. For more information about enabling 'Ole Automation Procedures', see "Surface Area Configuration" in SQL Server Books Online. 
						
						To resolve it, run the following SQL commands:USE masterGOsp_configure 'show advanced options', 1;GORECONFIGURE;GOsp_configure 'Ole Automation Procedures', 1;GORECONFIGURE;GO2. I then received error:
				SQL Server blocked access to procedure 'sys.xp_cmdshell' of component 'xp_cmdshell' because this component is turned off as part of the security configuration for this server. A system administrator can enable the use of 'xp_cmdshell' by using sp_configure. For more information about enabling 'xp_cmdshell', see "Surface Area Configuration" in SQL Server Books Online. 
				
				To resolve it, run the following SQL commands:USE masterGOEXEC sp_configure 'show advanced options', 1GORECONFIGURE WITH OVERRIDEGOEXEC sp_configure 'xp_cmdshell', 1GORECONFIGURE WITH OVERRIDEGOEXEC sp_configure 'show advanced options', 0GO]]></description> 
					<pubDate>Thu, 22 Feb 2007 03:14:24 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/2/21/sql-2005-express-maintenance/</guid>
				</item>
			
				<item>
					<title>Sitemap Generator v4.0 Released!!!!</title> 
					<link>http://keylimetie.com/blog/2007/2/21/sitemap-generator-v4-released/</link> 
					<description><![CDATA[
				Version 4.1 is now available! 
				
						
								Click here for more details!
						
				
		
		
		
		
		(You will automatically be redirected to the new version in 5 seconds). 
]]></description> 
					<pubDate>Wed, 21 Feb 2007 08:47:34 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/2/21/sitemap-generator-v4-released/</guid>
				</item>
			
				<item>
					<title>Sitemap Generator v4.0 Pre-Release</title> 
					<link>http://keylimetie.com/blog/2007/2/19/sitemap-generator-4-pre-release/</link> 
					<description><![CDATA[
				
				I have tested the main application and it's solid. It runs very fast and all of the new features run great. The scheduling part appears to be running great, but I still want to test it out on a couple more operating systems (it's very complicated code and I want to make sure it runs perfectly). I have finished testing it on Windows XP and Windows 2003, but still want to test it on Windows 2000. I plan to complete this tomorrow and release ALL of version 4.0. But if you want to get a jump start with the new features, the download link is below. When I publish the final v4 tomorrow, it will be an installation package. And if you don't care about the scheduling feature, then the download link below will be perfect for you.You'll notice the entire application is now branded with my company name, iArchitect. This is a decision I recently made to push the product under my company name with other products I will be releasing soon. One product coming soon, Web Analyzer, will be free for all licensed Sitemap Generator users! I'll let you know when it's available.]]></description> 
					<pubDate>Tue, 20 Feb 2007 05:39:42 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/2/19/sitemap-generator-4-pre-release/</guid>
				</item>
			
				<item>
					<title>Sitemap Generator v4.0 being released tonight!</title> 
					<link>http://keylimetie.com/blog/2007/2/19/sitemap-generator-4/</link> 
					<description><![CDATA[After a long, long wait, I finally have version 4.0 ready! A few licensed users have been using it for the past week and have identified only a couple minor glitches. I am confident the code is solid and ready to be released. I am finishing up some installation package items and will be releasing the new version Monday night (tonight). Thank you everyone for the wait. It will be well worth it! In case you're curious, here are the features that have been added:
		
				
						
								
										
												
														When creating a new website profile, you can now copy the preferences from another profile
												
												
														Ability to specify Google sitemap file name
												
												
														HTML title is now extracted while spidering and displayed on the HTML sitemaps
												
												
														When spidering websites, the software now sets the "User Agent" property to "iArchitect Sitemap Generator v4.0"
												
												
														When spidering websites, the software now handles "302 Redirect" response codes
												
												
														When spidering is completed, all found webpage paths are sorted
												
												
														Updated XML header element per Google's update
												
												
														Customize your HTML sitemaps with header and footer templates
												
												
														Ability to export to RSS format
												
												
														Ability to copy sitemaps to a local path (useful when running software on web server)
												
												
														Ability to schedule application to run automatically
												
												
														Help tab added which displays online forums website
												
												
														Small advertising image area added in header of software; Licensed users can disable it
												
												
														Rebranded software; instead of seeing Brian Pautsch, you will now see iArchitect (my company name)
												
												
														Bug: When deleting a website profile, not all files were deleted
												
												
														Bug: For very large sites, the google sitemap index file had "/google/" in the paths 
												
										
								
						
				
		]]></description> 
					<pubDate>Mon, 19 Feb 2007 06:57:33 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/2/19/sitemap-generator-4/</guid>
				</item>
			
				<item>
					<title>Windows 2003 Server does not stream FLV videos</title> 
					<link>http://keylimetie.com/blog/2007/1/16/windows-2003-flv-videos/</link> 
					<description><![CDATA[A friend of mine came across a problem trying to stream a FLV video on his customer's website. Before deploying it to their web server, he tested it successfully on his local machine and on a UNIX test server...no problems. Once he migrated the code and FLV file to the Production Windows 2003 Server, it didn't work anymore. He figured out the problem and told me about it.IssueWhen Flash Player movie files that stream external FLV files (Flash videos) are placed on a Microsoft Windows 2003 server and then viewed in a browser, the SWF file plays correctly, but the FLV video does not stream. These files work correctly if tested on other operating systems. The issue affects all FLV files played via Windows 2003 server, including files made with the Flash Video Kit for Dreamweaver MX 2004.
		This TechNote describes the steps necessary to allow Windows 2003 to stream Flash Video files.
		Note: These instructions are provided as a courtesy for customers and address the issue in Microsoft Internet Information Services (IIS) 6.0 rather than Flash.
		
				Reason
				With IIS 6.0, Microsoft changed the way streaming media is handled. Previous versions of IIS did not require any modification to stream Flash Video. Microsoft IIS 6.0, the default web server that ships with Windows 2003, requires a MIME type to recognize that FLV files are streamed media.
		
				Solution
				Please be aware that these steps do not resolve any issue with Flash, but are a configuration step for Microsoft Windows 2003 and Microsoft IIS Server 6.0. Any difficulties in executing these instructions or any errors that may arise from modifying your system settings should be addressed to Microsoft. For more details, please refer to your IIS documentation.
		1. On the Windows 2003 server, open the Internet Information Services Manager. 2. Expand the Local Computer Server. 3. Right-click the local computer server and select Properties. 4. Select the MIME Types tab. 5. Click New and enter the following information:     Associated Extension box: .FLV     MIME Type box:flv-application/octet-stream 6. Click OK. 7. Restart the World Wide Web Publishing service. Sourcehttp://www.adobe.com/cfusion/knowledgebase/index.cfm?id=tn_19439]]></description> 
					<pubDate>Wed, 17 Jan 2007 02:58:10 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/1/16/windows-2003-flv-videos/</guid>
				</item>
			
				<item>
					<title>Microsoft Enterprise Library - Hosting in &quot;Medium Trust&quot; Environment</title> 
					<link>http://keylimetie.com/blog/2007/1/4/enterprise-library/</link> 
					<description><![CDATA[I have been using the Microsoft Enterprise Library for many years now. For the first time, I had serious problems deploying them to a production environment today. After about an hour of searching online, I found out that a lot of people were having this problem and only a few people had figured out how to resolve it. Here's what I did....very easy, very fast. Problem:Deployed web application with any Microsoft Enterprise Library component and received the follow error: Server Error in '/' ApplicationRequired permissions cannot be acquired.Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.Exception Details: System.Security.Policy.PolicyException: Required permissions cannot be acquired.Source Error:An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.Stack Trace:[PolicyException: Required permissions cannot be acquired.]System.Security.SecurityManager.ResolvePolicy(Evidence evidence, PermissionSet reqdPset, PermissionSet optPset, PermissionSet denyPset, PermissionSet& denied, Boolean checkExecutionPermission) +2736869System.Security.SecurityManager.ResolvePolicy(Evidence evidence, PermissionSet reqdPset, PermissionSet optPset, PermissionSet denyPset, PermissionSet& denied, Int32& securitySpecialFlags, Boolean checkExecutionPermission) +57blah blah blah... Explanation:Simply put, the Microsoft Enterprise Library is trying to perform operations that it is not allowed based on the trust level set on that server.I have never received this error before since I host all of my code on my own dedicated servers (where I have a "Full" trust set).Recently, I have been opening accounts for customers at WebHost4Life.com (I'm sort of trying to get out of the hosting business due to the liabilities). WebHost4Life must also have the trust level set to "Full" since I've never had problems there. Just today, I deployed code to a new hosting provider. I believe they have their trust level set to "Medium" and this is why I'm getting the error. Resolution:1. A few months ago, Microsoft released updated code to resolve this issue. Click here to download the code updates2. For any application block to read information from configuration files, it is necessary to grant the application ConfigurationPermission (which is not provided by default in medium trust). You can add the requirePermission="false" attribute to the application's configuration section definitions. For example: xml version="1.0"?>  configuration>    configSections>    section name="dataConfiguration" requirePermission="false"       type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings,             Microsoft.Practices.EnterpriseLibrary.Data"/>    configSections>
	.
	.
	.
configuration>That's it...pretty easy and fast.]]></description> 
					<pubDate>Fri, 05 Jan 2007 04:12:55 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2007/1/4/enterprise-library/</guid>
				</item>
			
				<item>
					<title>SQL Server 2005 - Generate INSERT statements for easy migrations</title> 
					<link>http://keylimetie.com/blog/2006/12/12/generate-insert/</link> 
					<description><![CDATA[I often work in a local environment and later need to migrate data to a remote database server. If the ports are open on the remote server, I can just export the data. Often this is not the case. In the past, I have either- Export the data, FTP it to the other location and import the data (what a pain!)- Used code I wrote to export the data to INSERT statements, copy/paste text to other location and execute scripts (not too bad)I was looking for an easier approach and came across Narayana Vyas Kondreddi's website. He has written a ton of code (VB and SQL) to do a lot of the everyday things we do.Here's a link to a "Procedure to script your data (to generate INSERT statements from the existing data)":http://vyaskn.tripod.com/code.htm#insertsIt's great. It installs in the master database and is available to all users for all databases.It even has options to filter results, omit certain data types, get only n rows, and much more.Be sure to check it out for yourself.In case the site ever shuts down, here's a link to the SQL 2005 script.]]></description> 
					<pubDate>Wed, 13 Dec 2006 05:01:19 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/12/12/generate-insert/</guid>
				</item>
			
				<item>
					<title>Google Checkout Processing Free Now through 2007!!!</title> 
					<link>http://keylimetie.com/blog/2006/12/6/free-google-checkout/</link> 
					<description><![CDATA[Announced this morning on Google.com...To celebrate the holidays, Google is processing your Checkout sales for freeAs you may know, for every $1 you spend on AdWords, you can process $10 of Google Checkout sales for free. Just in time for the holidays, we're giving you even more by processing your Google Checkout sales for free through the end of 2007! Here's how it works:- From November 8, 2006 through December 31, 2007, we'll process your Checkout transactions for free, even if you aren't an AdWords advertiser. If you're already an AdWords advertiser, we'll process your Checkout transactions for free regardless of what you spend on AdWords.* - Valid Checkout orders you receive during the promotion will automatically qualify. - You can take full advantage of this promotion by encouraging your buyers to use Google Checkout on your site. - Other applicable fees (e.g. chargeback fees) may apply. This promotion is subject to the Google Checkout Terms of Service. Google may revoke the promotion for accounts that do not comply with these terms.On January 1, 2008, the standard transaction fee will apply again. Also, if applicable, your regular free transaction processing (based on your December, 2007 AdWords spend) will resume.Using Google Checkout to increase sales and lower costs during this busy holiday season has never been easier. If we can do anything else to help, feel free to drop us a line. Happy holidays from Google Checkout!* AdWords advertisers: Because this promotion begins on 11/8/06, the free transaction processing based on your AdWords spend will still apply to your Checkout sales from 11/1/06 through 11/7/06. Any Checkout orders you receive and process from 11/8/06 through 12/31/07 will then be eligible for free processing under this promotion.]]></description> 
					<pubDate>Wed, 06 Dec 2006 14:18:51 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/12/6/free-google-checkout/</guid>
				</item>
			
				<item>
					<title>How To Get Around Having To Click Flash Movies</title> 
					<link>http://keylimetie.com/blog/2006/11/29/click-flash-movies/</link> 
					<description><![CDATA[If you use Internet Explorer, I’m sure you’re just as annoyed as me with the need to click a Flash movie once just to activate it. Not sure what I’m talking about? Check out this website I built: http://www.coyledevelopment.com
		
		Notice the Flash object is disabled (it runs, but you can’t interact with it) and your cursor has a little message that states “Click to activate and use this control”. Once you click it, it becomes “unlocked” and you can use it. What a pain, right? If the Flash object does any kind of posting back to the webpage and re-renders itself, you’ll have to click it again…meaning, your choice to activate it isn’t “saved” during your session.
		Why must we deal with this? It’s because of a dispute between Microsoft and Eolas. Eolas owns the patent to the technology for rendering plug-ins in web browsers. Microsoft must license the technology in order to use it in IE. They don’t want to so they added this annoyance to better their case. Read more at: http://en.wikipedia.org/wiki/Eolas
		So how can I get around it? It’s easy now thanks to deconcept and SWFObject.1. Download the SWFObject Javascript file2. Include the swfobject.js Javascript file and write a small amount of Javascript on your page to embed your Flash movie. Here is an example showing the minimum amount of code needed to embed a Flash movie:    This text is replaced by the Flash movie.   var so = new SWFObject("movie.swf", "mymovie", "200", "100", "7", "#336699");   so.write("flashcontent");This is just the basic explanation. You might want to know more about required parameters versus optional parameters or how to pass variables into the movie. For this information, visit their website to learn more.]]></description> 
					<pubDate>Thu, 30 Nov 2006 05:43:53 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/11/29/click-flash-movies/</guid>
				</item>
			
				<item>
					<title>Important SEO Tips Everyone Should Know</title> 
					<link>http://keylimetie.com/blog/2006/11/18/seotips/</link> 
					<description><![CDATA[From a WebProNews email I received recently:Important SEO Tips Everyone Should KnowChris Richardson | Staff WriterDuring the Interactive Site Review session at the 2007 Las Vegas PubCon, various site owners submitted their site for the panel to pick apart. The panel consisted of heavy hitters like Matt Cutts from Google, Tim Mayer from Yahoo, Greg Boser from WebGuerrilla, and Danny Sullivan.While some of the sites they reviewed may have been lacking in certain departments, the knowledge the panel bestowed is quite valuable for SEOers of all types. What follows is are some quotes and paraphrases that go a long way to demonstrating what it is search engines are looking for:- each page of your site is an entry point, optimize (title tags, keyphrases) for what each page targets - Greg- strive for quality links over quantity links - the entire panel- if you are targeting your site geographically, get links from local entities (Chamber of Commerce, local directories)- unique content is important (this and link bait are the prevailing themes of the Las Vegas PubCon)- if you can get into the top 3 of Google Local, you will be on the front page of Google's standard search if the query is geographically based... - Danny Sullivan- when optimizing for Google Local, navigate to the Google Local Business Center - this was suggested by Matt as a source to assist with being indexed by Google Local's index as well as a place to claim your business, similar to Technorati's blog claim function.- one of the sites reviewed was a real estate site... during this portion, Greg revealed some interesting information about how this industry markets to the search industry: the real estate industry conducts SEO much like they did in 98, it's a bad field in reference to SEO...and while this may not be a tip per se, it's good information to be aware of especially if you are considering this industry...- ditch javascript menus altogether... they are a red flag to ranking algos - Boser- template-based sites may not rank well because they appear alike to the crawlers... - Tim Mayer and Matt Cutts both iterated this thought.- Session IDs urls need to be blocked from crawlers because of duplicate content issues (don't serve session ids to bots)... this was emphasized by Matt who said: "session ids can be poison for crawlers"- if your site sells manufactured products, don't use manufacturer copy... use your own descriptions - this was also stated by Heather Lloyd-Martin during the effective web copy session- there's no good use for 302 redirects, ever - the entire panel- blog about your product or target area, this provide so much of the original content the search engines are looking for - paraphrased from Matt CuttsThis last point plays into the whole link bait theory that was incredibly prominent during this conference (I cannot count the number of times I heard this phrase...). Keep these tips and ideas in mind when you are conducting any SEO or SEM-related process. They will serve you well.
		
				 ]]></description> 
					<pubDate>Sat, 18 Nov 2006 19:13:43 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/11/18/seotips/</guid>
				</item>
			
				<item>
					<title>Gmail Spam Trick</title> 
					<link>http://keylimetie.com/blog/2006/11/18/gmail-spam-trick/</link> 
					<description><![CDATA[
				I saw this forum entry on digg.com and had to share...pretty tricky:
				
		When you give your email address to a website, you hope that they don't sell or trade your address to a bunch of spammers. Well if they do, here is a simple way to see what sites are responsible for what particular piece of email. This requires you have a Gmail account. 
If your Gmail login name was mailto:username@gmail.comand you went to samplesite.com to fill out a registration form, instead of just entering mailto:username@gmail.comas your email, enter it as mailto:username+samplesitecom@gmail.cominstead. When Gmail sees a "+" in an email address, it uses all the characters to the left of the plus sign to know who to send it to. In this example it would still send it to mailto:username@gmail.com. Now whats cool is if you search Gmail for username+samplesitecom, you will see all massages that were sent to that email address. To see who is responsible for sending a specific message click the Show Details link and you will see the complete address. ]]></description> 
					<pubDate>Wed, 15 Nov 2006 23:38:15 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/11/18/gmail-spam-trick/</guid>
				</item>
			
				<item>
					<title>Create a Web Layout with Adobe Photoshop</title> 
					<link>http://keylimetie.com/blog/2006/10/24/create-layout-photoshop/</link> 
					<description><![CDATA[Learn step by step how to create a web layout with Adobe Photoshop. Really amazing and useful for web design beginners.
		
				http://www.13dots.com/index.php?categoryid=33&p2_articleid=65
		]]></description> 
					<pubDate>Wed, 25 Oct 2006 02:21:20 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/10/24/create-layout-photoshop/</guid>
				</item>
			
				<item>
					<title>Free Photoshop-compatible Plugins</title> 
					<link>http://keylimetie.com/blog/2006/10/22/photoshop-plugins/</link> 
					<description><![CDATA[Free Photoshop-compatible Plugins http://thepluginsite.com/resources/freeps.htm]]></description> 
					<pubDate>Mon, 23 Oct 2006 04:45:14 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/10/22/photoshop-plugins/</guid>
				</item>
			
				<item>
					<title>Gartner: Five reasons why offshore deals go bust</title> 
					<link>http://keylimetie.com/blog/2006/10/18/offshore-deals-go-bust/</link> 
					<description><![CDATA[Over the past few years, I have worked with companies that have used offshore resources to work on part of or complete projects. I also have been "hands on" with some of the projects and in my experience, it rarely works.I was recently in a meeting discussing the possibility of offshoring some work. Since I have been down this road all too many times, I voiced my opinion. Most people also didn't like the idea and I took it upon myself to gather some facts. Now I know there are arguments for both sides, but when I was browsing the web I came across a study by Gartner Inc.If you're not familiar with Gartner Inc., they are pretty much the authority on gathering, analyzing and reporting statistical data in an unbiased manner. Companies all over the world utilize Gartner's services to gather data on pretty much anything...and because they are so thorough, it's not cheap.The 5 high level reasons are:1. Unrealized cost savings2. Loss of productivity3. Poor commitment and communications4. Cultural differences5. Lack of offshore expertise and readinessClick here read the entire article]]></description> 
					<pubDate>Thu, 19 Oct 2006 03:31:39 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/10/18/offshore-deals-go-bust/</guid>
				</item>
			
				<item>
					<title>The 18 Mistakes That Kill Startups</title> 
					<link>http://keylimetie.com/blog/2006/10/16/18mistakes/</link> 
					<description><![CDATA[I found this great article on the "18 Mistakes That Kill Startups", by Paul Graham.I have been a part of several start ups, some successful, some not so successful.A lot of the points Paul makes I have seen first hand.I learned a few really good things from his article.http://paulgraham.com/startupmistakes.html]]></description> 
					<pubDate>Tue, 17 Oct 2006 05:34:41 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/10/16/18mistakes/</guid>
				</item>
			
				<item>
					<title>21,600 Developers Email Addresses found with Google Code Search</title> 
					<link>http://keylimetie.com/blog/2006/10/12/googleemailaddresses/</link> 
					<description><![CDATA[
A few days ago, I blogged about how to find database credentials using Google Code Search.Here's another interesting search:
Google Code Search supports regular expressions...try:
^\w+([-+.]\w+)*@\w+([-.]\w+)*.\w+([-.]\w+)*$

21,600 results with is probably at least 30,000 email addresses.


]]></description> 
					<pubDate>Fri, 13 Oct 2006 02:05:06 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/10/12/googleemailaddresses/</guid>
				</item>
			
				<item>
					<title>How to Add a WinForm DataGridView Header CheckBox</title> 
					<link>http://keylimetie.com/blog/2006/10/10/datagridview/</link> 
					<description><![CDATA[A recent project required that we figure out how to add a "Select All" checkbox to the header column header of a DataGridViewCheckBoxColumn Windows Forms. After searching the web for possible solutions, it became clear that the actual control cound not be added dynamically. The best approach we could find was to paint a checkbox image into the header and respond to the DataGridView's "ColumnHeaderMouseClick" event. Here's the solution in detail:Download source code1. Create a Resource File and add in the two attached images. When I dragged them in, they were renamed to “_checked” and “_unchecked”. 2. Declare a “Select All” private variable. 1privatebool _selectAll = false;3. Wherever you bind your DataGridView (I did in Page_Load for this example), add in the checkbox column (unless you already have it in your design view). 1private void Form1_Load(object sender, EventArgs e)
2{
3    try4    {
5        //Bind XML dataset to DataGridView6        DataSet ds = new DataSet();
7        ds.ReadXml(_xmlFilePath);
8        dataGridView1.DataSource = ds.Tables[0];
9        //Add the checkbox column10        dataGridView1.Columns.Insert(0, 
11            new DataGridViewCheckBoxColumn());
12    }
13    catch (Exception ex)
14    {
15        MessageBox.Show("Exception: " + ex.ToString());
16    }
17}4. Create the CellPainting Event. 1privatevoid dataGridView1_CellPainting(object sender, 
2    DataGridViewCellPaintingEventArgs e)
3{
4    //Is this the checkbox column header?5    if (e.RowIndex == -1 && e.ColumnIndex == 0)
6    {
7        try8        {
9            //Erase the cell10            using (Brush backColorBrush = 
11                new SolidBrush(e.CellStyle.BackColor))
12            {
13                e.Graphics.FillRectangle(backColorBrush, e.CellBounds);
14            }
1516            //Draw 1 bottom line...17            e.Graphics.DrawLine(Pens.DarkGray, e.CellBounds.Left, 
18                e.CellBounds.Bottom - 1, e.CellBounds.Right, e.CellBounds.Bottom - 1);
19            //Draw 2 top lines...20            e.Graphics.DrawLine(Pens.DarkGray, e.CellBounds.Left, 
21                e.CellBounds.Top, e.CellBounds.Right, e.CellBounds.Top);
22            e.Graphics.DrawLine(Pens.White, e.CellBounds.Left, 
23                e.CellBounds.Top + 1, e.CellBounds.Right, e.CellBounds.Top + 1);
24            //Draw right line...25            e.Graphics.DrawLine(Pens.DarkGray, e.CellBounds.Right - 1, 
26                e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom);
27            //Draw left line...28            e.Graphics.DrawLine(Pens.White, e.CellBounds.Left, 
29                e.CellBounds.Top, e.CellBounds.Left, e.CellBounds.Bottom);
3031            //Get the image from the resource file32            Image imgChecked = (Image)Resource1._checked;
33            Image imgUnchecked = (Image)Resource1._unchecked;
3435            //Determine paint coordinates36            int X = e.CellBounds.Left + 
37                ((e.CellBounds.Width - imgChecked.Width) / 2) - 1;
38            int Y = e.CellBounds.Top + 
39                ((e.CellBounds.Height - imgChecked.Height) / 2) - 1;
4041            //Draw checkbox in header42            if (_selectAll)
43                e.Graphics.DrawImage(imgChecked, X, Y);
44            else45                e.Graphics.DrawImage(imgUnchecked, X, Y);
4647            //Set event as handled48            e.Handled = true;
49        }
50        catch51        {
52            //Handle exception53        }
54    }
55}5. Handle the Select All click event. 1privatevoid dataGridView1_ColumnHeaderMouseClick(object sender, 
2    DataGridViewCellMouseEventArgs e)
3{
4    if (e.ColumnIndex == 0)
5    {
6        _selectAll = !_selectAll;
7        for (int i = 0; i 8        {
9            dataGridView1.Rows[i].Cells[0].Value = _selectAll;
10        }
11    }
12}]]></description> 
					<pubDate>Wed, 11 Oct 2006 04:15:40 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/10/10/datagridview/</guid>
				</item>
			
				<item>
					<title>Find Database Credentials with Google Code Search</title> 
					<link>http://keylimetie.com/blog/2006/10/5/finddbcredentials/</link> 
					<description><![CDATA[I was messing around with Google Code Search today and decided to see if people were dumb enough to publish web.config files with their private database credentials.Yep...there are a few out there. Check out this example:http://google.com/codesearch?hl=en&lr=&q=database+file%3A%22web.config%22&btnG=Search]]></description> 
					<pubDate>Fri, 06 Oct 2006 03:31:19 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/10/5/finddbcredentials/</guid>
				</item>
			
				<item>
					<title>Google Code Search</title> 
					<link>http://keylimetie.com/blog/2006/10/4/googlecodesearch/</link> 
					<description><![CDATA[Today, Google announced "Google Code Search":http://www.google.com/codesearch"It's a site that simplifies how software developers search for programming code to improve existing software or create new programs."The Basic Search is OK, but you really need to check out the Advanced Search.Here's you can specify a few things, most importantly the language.In the example below, I search for "PayPal" in C# code.Results return in code snippet format. Check out result #11...that's some amazing code!Click into each result and the entire code file is displayed with links to related project files. ]]></description> 
					<pubDate>Thu, 05 Oct 2006 05:46:31 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/10/4/googlecodesearch/</guid>
				</item>
			
				<item>
					<title>ViewStateException solved!</title> 
					<link>http://keylimetie.com/blog/2006/9/24/viewstate/</link> 
					<description><![CDATA[A few months ago, I started receiving the following exception on my website for one of my blogs:System.Web.HttpException: The state information is invalid for this page and might be corrupted. ---> System.Web.UI.ViewStateException: Invalid viewstateImmediately, I visited the webpage and it displayed fine. So I refreshed a bunch of times without receiving any errors. Then I tried viewing and posting comments with several browsers...nothing wrong. Then I opened up the code and reviewed it...it looked good. Since it was only happening to one blog, I thought it might have to do with the content of that blog...maybe I accidentally dropped a "" or "" tag in the content...nope! I was puzzled and kind of dismissed it for awhile.Then it started happening more and more...on average, I now receive 2-3 of these errors per day. I started getting a little worried that a handful of visitors couldn't post comments to my website...but I had no ideas what to do.Then I got a call from a customer. They purchased some blog spamming software and asked me to come to their office, figure out how it works and show them how to use it. Before going there, I researched the product and that's when I figured out my problem. The software I was reading up on asks you what keywords to search blog sites for. Next, it asks you for a blog comment. Finally, it searches the blog sites with the keywords you entered and posts the comment you entered. Not only does it get people to read your comment and visit your website, but it also increases your Google "PageRank" over time...genius! But be careful...if Google sniffs this out, you'll be blacklisted.This is what is happening to my website...people are running software programs to leave spam comments and are causing exceptions to be thrown. The good news is that I now know it's now my software causing the problems and that I'm successfully blocking a lot of spam thanks to my Captcha code.Below is the full exception message...I'm posting it so that it is indexed is search engines and others having this problem will now have resolution.Page: Global.asaxMethod: Application_ErrorException: System.Web.HttpException: The state information is invalid for this page and might be corrupted. ---> System.Web.UI.ViewStateException: Invalid viewstate.Additional Details:Client IP: 65.88.129.2 Port: 46644 User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 1.1.4322) ViewState: sssssss Referer: Path: /BlogEntry.aspx ---> System.FormatException: Invalid length for a Base-64 char array. at System.Convert.FromBase64String(String s) at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString) at System.Web.UI.ObjectStateFormatter.System.Web.UI.IStateFormatter.Deserialize(String serializedState) at System.Web.UI.Util.DeserializeWithAssert(IStateFormatter formatter, String serializedState) at System.Web.UI.HiddenFieldPageStatePersister.Load() --- End of inner exception stack trace --- --- End of inner exception stack trace --- at System.Web.UI.ViewStateException.ThrowError(Exception inner, String persistedState, String errorPageMessage, Boolean macValidationError) at System.Web.UI.HiddenFieldPageStatePersister.Load() at System.Web.UI.Page.LoadPageStateFromPersistenceMedium() at System.Web.UI.Page.LoadAllState() at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) at System.Web.UI.Page.ProcessRequest() at System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context) at System.Web.UI.Page.ProcessRequest(HttpContext context) at ASP.blogentry_aspx.ProcessRequest(HttpContext context) in c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files oot\6486194d\28a90c6b\App_Web_znedlsbn.2.cs:line 0 at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)Inner Exc:System.Web.UI.ViewStateException: Invalid viewstate. Client IP: 65.88.129.2 Port: 46644 User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 1.1.4322) ViewState: sssssss Referer: Path: /BlogEntry.aspx ---> System.FormatException: Invalid length for a Base-64 char array. at System.Convert.FromBase64String(String s) at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString) at System.Web.UI.ObjectStateFormatter.System.Web.UI.IStateFormatter.Deserialize(String serializedState) at System.Web.UI.Util.DeserializeWithAssert(IStateFormatter formatter, String serializedState) at System.Web.UI.HiddenFieldPageStatePersister.Load() --- End of inner exception stack trace ---Inner/Inner Exc:System.FormatException: Invalid length for a Base-64 char array. at System.Convert.FromBase64String(String s) at System.Web.UI.ObjectStateFormatter.Deserialize(String inputString) at System.Web.UI.ObjectStateFormatter.System.Web.UI.IStateFormatter.Deserialize(String serializedState) at System.Web.UI.Util.DeserializeWithAssert(IStateFormatter formatter, String serializedState) at System.Web.UI.HiddenFieldPageStatePersister.Load() ]]></description> 
					<pubDate>Sun, 24 Sep 2006 22:31:52 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/9/24/viewstate/</guid>
				</item>
			
				<item>
					<title>Extract Current Webpage HTML (and maybe generate a PDF)</title> 
					<link>http://keylimetie.com/blog/2006/9/20/extracthtmlpdf/</link> 
					<description><![CDATA[I recently had a requirement from a customer to generate a PDF that looked exactly like the webpage. Instead of trying to recreate the webpage in Crystal or SQL Server Reports, I decided it would be much easier, cheaper and maintainable to simply take the webpage's HTML, load it into a 3rd party PDF generator and create a PDF. Below is the code you need to do this.The important part is that you need to override the page's "OnPreRenderComplete" event and extract the HTML from the base. 1protectedoverridevoid OnPreRenderComplete(EventArgs e)
2{
3    GeneratePDFFromPageHTML();
4}
56protected void GeneratePDFFromPageHTML()
7{
8    StringWriter sw;
9    HtmlTextWriter htmltw;
1011    try12    {
13        //Get the current page's HTML14        sw = new StringWriter();
15        htmltw = new HtmlTextWriter(sw);
16        base.Render(htmltw);
17        StringBuilder html = sw.GetStringBuilder();
1819        //Generate PDF with HTML here. Code not supplied 20        //since there are so many 3rd party PDF generators.21        //When done generating PDF, either load it into the22        //browser or stream it back as an attachment23    }
24    catch (Exception ex)
25    {
26        //Handle exception27    }
28    finally29    {
30        if (htmltw != null)
31        {
32            htmltw.Close();
33            htmltw.Dispose();
34            htmltw = null;
35        }
36        if (sw != null)
37        {
38            sw.Close();
39            sw.Dispose();
40            sw = null;
41        }
42    }
43}]]></description> 
					<pubDate>Thu, 21 Sep 2006 05:04:25 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/9/20/extracthtmlpdf/</guid>
				</item>
			
				<item>
					<title>Great Regular Expression Resource</title> 
					<link>http://keylimetie.com/blog/2006/9/18/regularexpression/</link> 
					<description><![CDATA[Regular Expressions can be very helpful when searching for strings of text.I use them all the time and recently came across and amazing website:http://regexlib.com - Regular Expression LibrarySome of the pages I use a lot:Cheat Sheet: http://regexlib.com/CheatSheet.aspxTester: http://regexlib.com/RETester.aspx]]></description> 
					<pubDate>Tue, 19 Sep 2006 05:12:01 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/9/18/regularexpression/</guid>
				</item>
			
				<item>
					<title>Google Sitemap Generator v3.1 Released!!!!</title> 
					<link>http://keylimetie.com/blog/2006/9/13/googlesitemapgenerator/</link> 
					<description><![CDATA[
				Version 4.1 is now available! 
				
						
								Click here for more details!
						
				
		
		
		
		
		(You will automatically be redirected to the new version in 5 seconds). 
]]></description> 
					<pubDate>Thu, 14 Sep 2006 02:52:41 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/9/13/googlesitemapgenerator/</guid>
				</item>
			
				<item>
					<title>8 Things Businesses Should Know Before Building A Website</title> 
					<link>http://keylimetie.com/blog/2006/9/12/8things/</link> 
					<description><![CDATA[Over the past 10 years, I have had the pleasure to work with some great customers. I also have had the unfortunate honor of working with some "difficult" customers. Below are a few things I have learned and my advice to you if you're looking to build or re-build your company website. Good luck!1. Do Your HomeworkThe number one complaint from designers and developers is that customers cannot articulate what they want. Designers and developers are not mind readers and often are not very familiar with your industry. You need to specify what features you want exactly with great detail. Visit competitor sites and see what they have. It's OK to copy ideas, but make them unique in your own way if possible. The design process is very important and takes time. There will be several iterations until a finished design is made. But if you have a clear vision, you can save time and money because the designers won't have to keep reworking the design while you figure out what you want.2. Don't Cut CornersThere are several phases to any website project. A typical life cycle is:1. Project Inception - Imagine how great the site could be if it were created without limits. Write these ideas down.2. Project Launch Meeting - Brainstorming session. No decisions will be made, but you'll talk about things like colors, fonts, logos, navigation and who the site will target (very important!).3. Project Requirements Document - Essentially you want this document to summarize what the team currently thinks the project will look like when it's completed. There's no need to get it all right or feel tied down.4. Discovery Documents - With these documents, you'll get down to working out who your target audience is, what they want, the sections of the site, and what they will contain. This will become the true roadmap for the project.5. Prototype - The prototype will turn your documents into a reality. Now is the time to simply produce a visual that the client can see.6. Development - The designers will give the developers the necessary files and developers will build the website. After some time, a rough website will be produced and give everyone a chance to see where the project now stands...and appreciate how far it has come.7. Testing and Final Approval - Get lots of people to use your site and make sure they enjoy it. Take their comments into consideration and tweak where appropriate.8. Go Live - Turn the site onto the world. Monitor the usage, watch for errors and fix them. Get people's reaction. Maintenance will be necessary. A lot of people think that once the site is live, it's done. Not true at all. I'll discuss this more later (#7 below).3. You Need To Provide ContentOnce you have your Discovery documents complete, the designers and developers will start working. This is when you need to start building the content for the website. Start early and stay on top of it! Writing content for most people is difficult and takes a lot of time. It's very easy to push it off until the end...this will severely push back your timeline. Also, some customers think the web designers or developers write the content. This doesn't make any sense. It's your business, you're the expert. You have to write the content.4. Too Flashy = No TrafficWeb sites don't need to be over-the-top to get results. Some clients will ask for lots of animation and cool graphics. They want a splash page built in Flash, and Javascript rollover images for menu items. They don't understand that (a) these things can turn off visitors who don't have a fast Internet connection or up-to-date browsers or extensions; (b) these things eat up bandwidth; (c) these things make a web site much less visible to search engines. In short, they rarely help, and often hurt, the majority of business web sites. The structure should be defined by the content, not the look. The look is important but only to support the content...not to control the content. A lot of designers are user interface experts - listen to them.5. It Costs More And Takes Longer than You ThinkJust because you can create a website in a few minutes with an off-the-shelf package doesn't mean it's the right solution for your business. These off-the-shelf packages are bought by thousands of people and your website will looked like a cheesy, canned solution. They also only have a limited feature set. If the feature you need isn't there, you will not get it and no developer will be able to add it in. It's not that the website is hard to build, it's just that it takes time. Good, experienced developers who have built hundreds of websites over that time typically create a library of common code. These developers can help you save a lot of money by reusing their common code...but if you have something unique it needs to be created from scratch. Just remember that you only get what you pay for. If you get something cheap, there is always a catch. The lowest bidder is the lowest bidder for a reason. Also, most people in the Web industry are clueless. The majority of web developers need to update their skills to what is required for the 21st century. Anyone can build a website...but it doesn’t always mean that they should.6. If You Build It, They Won't Necessarily ComeThere's a commercial where a company launches their website and immediately starts getting millions of sales. That doesn't happen. Your website will not be the first result in any Google search the first day you go live. Getting your website on the first page of Google takes time (it'll take months), commitment and money. Building the site is not the same thing as marketing it. There are hundreds of companies whose sole purpose is to help you market you website. It's not "If we build it, they will come, and throw money at us." For most businesses, it's more like "If we build it, and dedicate effort to keeping it fresh and up to date and interesting, and if we're selling something people really want to buy, and if we think of the web site as only a part of our marketing effort, and if we pay attention to having clean code and optimized pages and tweak our pay-per-click keywords effectively, we should be more successful with a website than without."7. Maintenance Is A MustI know a lot of developers who do not create maintenance sites for their customers. Whenever the customer needs an update, they have to pay for the developer's services. This nickle-and-diming approach should be avoided. When creating your Project Requirements document, be sure a secure administrative section of your website is developed. Every reasonable feature of your website must be maintainable...meaning products and content, but not the design and most look-and-feel. You also need to have the ability to move your website from one provider to the next without having to contact a developer. All web sites require at least some degree of maintenance. Try to control that maintenance yourself. After a year or two, major changes (i.e. complete website redesign) may be needed.8. Designers And Developers Are ProfessionalsMany web designers and developers are appalled at assumptions that their skills are basic and valueless. Professional design takes a lot of work, skill, education and ability. Do you think that a professional chef is a person who puts a bunch of ingredients that don't match into a big pan and sticks it in the oven? You should expect to assign one person from your company to interact with the designers and developers. There is nothing that will cause more confusion, anger and disappointment than the fact that one designer has 3 or 4 people calling and e-mailing them every 5 minutes...each person changing what the last person said.ConclusionI believe these points are very important. As a developer, I try to have a discussion about these points with all new customers. Almost all "get it" and agree...and it's a pleasure to do business with these people. In fact, if I know they will work this way, I know the process will be faster and easier and, therefore, much more affordable for them. If I know the customer is going to do things the hard way, I will add in the necessary hours to compensate for the extra time needed to complete their project.Bonus (for Developers): From My Experience...Over the past 10 years, I have built hundreds of websites and still learn new things everyday. Here are some of my practices that allow me to work very fast and efficiently:Design: I used to use graphic artists, but now use templates whenever possible. Why? A custom design costs between $1,000 and $4,000. Professional templates are about $60. Sure, other people can buy these templates too, but for most small-medium businesses, who cares? It's worth saving the thousands of dollars. Also, you get all of the source files, so you can tweak them to make them your own. All you'd have in common with others is the colors/style...it's your own logo and content...change the graphics. My favorite template site: http://www.templatemonster.com Development: I write all code in .NET, C# specifically. The .NET 1.0 platform came out in 2001 and has developed into the most amazing development platform. The set of libraries and namespaces is so large and includes everything you could possibly want to do. .NET is by far the fastest development platform and is the future of software. (Bold, but true statement) When appropriate, use the Microsoft Application Blocks... I use several of them in most of my projects. Development: Build your own library of reusable code. Over the past few years, I have continued to extend my "BrianPautsch" namespace. It contains distinct classes and methods for specific tasks including exception handling, validation, emailing, form helpers, database access, ecommerce, SSL, image handling, captcha, advanced search engines, etc. When I start on a new project, I can complete more than 1/2 the project requirements in less than an hour because of my library of code. Development: Use a code generator. There are a bunch out there, so you don't have to create your own. I created my own a few years ago and use it to generate parts of the Business layer, the Database layer and all related Stored Procedures. Once I have the database schema completed, I can generate code and stored procedures in seconds with just one click. Not only am I saving hours and hours of work (extremely boring work!), but the code is 100% perfect and ready to be used. Now, with my library of code and the code generator, I can have a website 75% complete in only an hour or so. This is how I can create a fully functional ecommerce site in a weekend. Search Engines: Create Google Sitemaps with my Google Sitemap Generator (shameless plug). I have seen websites get into the Google index within 24 hours this way. I have also seen sites already in Google jump in the results by simply creating a Google Sitemap. ]]></description> 
					<pubDate>Wed, 13 Sep 2006 00:29:42 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/9/12/8things/</guid>
				</item>
			
				<item>
					<title>Website Testing Part II - Automation, Autofill, etc. for Frames</title> 
					<link>http://keylimetie.com/blog/2006/8/7/websitetesting2/</link> 
					<description><![CDATA[Back on 3/9/2005, I published a blog titled
Website Testing - Automation, Autofill, etc. (C# WinForms).
Since then, dozens of people have downloaded it and used it successfully to build projects with similar technology.
Today, "Herman" asked how to populate forms, click buttons, etc. in frames. Of course, frames are a big no no, but they do exist.
This blog explains how to do what Herman is asking for.
Download code
The only real difference from the previous blog is lines 5-29. In lines 5-14, I iterate through the frames collection and find
the specific frame by name. on line 20, I load that frame into its own IHTMLDocument2 object. And finally, on lines 22-28, I find
the controls and manipulate them. That's it!
1//Get the web browser document2myDoc = new HTMLDocumentClass();3myDoc = (HTMLDocument) WebBrowser.Document;45//Find the frame named "content"6FramesCollection myFramesColl = myDoc.frames;7IHTMLWindow2 myContentFrame = null;8for (int i = 0; i 9{10object refIndex = i;11	mshtml.IHTMLWindow2 frame = (mshtml.IHTMLWindow2)myFramesColl.item(ref refIndex);12if (frame.name == "content")13		myContentFrame = frame;14}1516//Frame found?17if (myContentFrame != null)18{19//Load into IHTMLDocument2 object20	IHTMLDocument2 myContentFrameDoc = myContentFrame.document;2122//Find the textbox23	HTMLInputElement objTextBox = (HTMLInputElement) myContentFrameDoc.all.item("txtEmail", 0);24	objTextBox.value = txtEmail.Text;2526//Click the selected button27	HTMLInputElement btnSearch = (HTMLInputElement) myContentFrameDoc.all.item("cmdJoin", 0);28	btnSearch.click();29}]]></description> 
					<pubDate>Tue, 08 Aug 2006 05:39:13 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/8/7/websitetesting2/</guid>
				</item>
			
				<item>
					<title>How Google Ranks Pages</title> 
					<link>http://keylimetie.com/blog/2006/8/2/howgooglerankspages/</link> 
					<description><![CDATA[From the Stanford archives...
The Anatomy of a Large-Scale Hypertextual Web Search EngineSergey Brin and Lawrence Page{sergey, page}@cs.stanford.eduComputer Science Department, Stanford University, Stanford, CA 94305Abstract       In this paper, we present Google, a prototype of a large-scale search engine which makes heavy use of the structure present in hypertext. Google is designed to crawl and index the Web efficiently and produce much more satisfying search results than existing systems. The prototype with a full text and hyperlink database of at least 24 million pages is available at http://google.stanford.edu/       To engineer a search engine is a challenging task. Search engines index tens to hundreds of millions of web pages involving a comparable number of distinct terms. They answer tens of millions of queries every day. Despite the importance of large-scale search engines on the web, very little academic research has been done on them. Furthermore, due to rapid advance in technology and web proliferation, creating a web search engine today is very different from three years ago. This paper provides an in-depth description of our large-scale web search engine -- the first such detailed public description we know of to date.        Apart from the problems of scaling traditional search techniques to data of this magnitude, there are new technical challenges involved with using the additional information present in hypertext to produce better search results. This paper addresses this question of how to build a practical large-scale system which can exploit the additional information present in hypertext. Also we look at the problem of how to effectively deal with uncontrolled hypertext collections where anyone can publish anything they want. 
 Keywords: World Wide Web, Search Engines, Information Retrieval, PageRank, Google1. Introduction(Note: There are two versions of this paper -- a longer full version and a shorter printed version. The full version is available on the web and the conference CD-ROM.)The web creates new challenges for information retrieval. The amount of information on the web is growing rapidly, as well as the number of new users inexperienced in the art of web research. People are likely to surf the web using its link graph, often starting with high quality human maintained indices such as Yahoo! or with search engines. Human maintained lists cover popular topics effectively but are subjective, expensive to build and maintain, slow to improve, and cannot cover all esoteric topics. Automated search engines that rely on keyword matching usually return too many low quality matches. To make matters worse, some advertisers attempt to gain people's attention by taking measures meant to mislead automated search engines. We have built a large-scale search engine which addresses many of the problems of existing systems. It makes especially heavy use of the additional structure present in hypertext to provide much higher quality search results. We chose our system name, Google, because it is a common spelling of googol, or 10100 and fits well with our goal of building very large-scale search engines. 
1.1 Web Search Engines -- Scaling Up: 1994 - 2000Search engine technology has had to scale dramatically to keep up with the growth of the web. In 1994, one of the first web search engines, the World Wide Web Worm (WWWW) [McBryan 94] had an index of 110,000 web pages and web accessible documents. As of November, 1997, the top search engines claim to index from 2 million (WebCrawler) to 100 million web documents (from Search Engine Watch). It is foreseeable that by the year 2000, a comprehensive index of the Web will contain over a billion documents. At the same time, the number of queries search engines handle has grown incredibly too. In March and April 1994, the World Wide Web Worm received an average of about 1500 queries per day. In November 1997, Altavista claimed it handled roughly 20 million queries per day. With the increasing number of users on the web, and automated systems which query search engines, it is likely that top search engines will handle hundreds of millions of queries per day by the year 2000. The goal of our system is to address many of the problems, both in quality and scalability, introduced by scaling search engine technology to such extraordinary numbers. 
1.2. Google: Scaling with the WebCreating a search engine which scales even to today's web presents many challenges. Fast crawling technology is needed to gather the web documents and keep them up to date. Storage space must be used efficiently to store indices and, optionally, the documents themselves. The indexing system must process hundreds of gigabytes of data efficiently. Queries must be handled quickly, at a rate of hundreds to thousands per second. 
These tasks are becoming increasingly difficult as the Web grows. However, hardware performance and cost have improved dramatically to partially offset the difficulty. There are, however, several notable exceptions to this progress such as disk seek time and operating system robustness. In designing Google, we have considered both the rate of growth of the Web and technological changes. Google is designed to scale well to extremely large data sets. It makes efficient use of storage space to store the index. Its data structures are optimized for fast and efficient access (see section 4.2). Further, we expect that the cost to index and store text or HTML will eventually decline relative to the amount that will be available (see Appendix B). This will result in favorable scaling properties for centralized systems like Google. 
1.3 Design Goals1.3.1 Improved Search QualityOur main goal is to improve the quality of web search engines. In 1994, some people believed that a complete search index would make it possible to find anything easily. According to Best of the Web 1994 -- Navigators,  "The best navigation service should make it easy to find almost anything on the Web (once all the data is entered)."  However, the Web of 1997 is quite different. Anyone who has used a search engine recently, can readily testify that the completeness of the index is not the only factor in the quality of search results. "Junk results" often wash out any results that a user is interested in. In fact, as of November 1997, only one of the top four commercial search engines finds itself (returns its own search page in response to its name in the top ten results). One of the main causes of this problem is that the number of documents in the indices has been increasing by many orders of magnitude, but the user's ability to look at documents has not. People are still only willing to look at the first few tens of results. Because of this, as the collection size grows, we need tools that have very high precision (number of relevant documents returned, say in the top tens of results). Indeed, we want our notion of "relevant" to only include the very best documents since there may be tens of thousands of slightly relevant documents. This very high precision is important even at the expense of recall (the total number of relevant documents the system is able to return). There is quite a bit of recent optimism that the use of more hypertextual information can help improve search and other applications [Marchiori 97] [Spertus 97] [Weiss 96] [Kleinberg 98]. In particular, link structure [Page 98] and link text provide a lot of information for making relevance judgments and quality filtering. Google makes use of both link structure and anchor text (see Sections 2.1 and 2.2). 
1.3.2 Academic Search Engine ResearchAside from tremendous growth, the Web has also become increasingly commercial over time. In 1993, 1.5% of web servers were on .com domains. This number grew to over 60% in 1997. At the same time, search engines have migrated from the academic domain to the commercial. Up until now most search engine development has gone on at companies with little publication of technical details. This causes search engine technology to remain largely a black art and to be advertising oriented (see Appendix A). With Google, we have a strong goal to push more development and understanding into the academic realm. 
Another important design goal was to build systems that reasonable numbers of people can actually use. Usage was important to us because we think some of the most interesting research will involve leveraging the vast amount of usage data that is available from modern web systems. For example, there are many tens of millions of searches performed every day. However, it is very difficult to get this data, mainly because it is considered commercially valuable. 
Our final design goal was to build an architecture that can support novel research activities on large-scale web data. To support novel research uses, Google stores all of the actual documents it crawls in compressed form. One of our main goals in designing Google was to set up an environment where other researchers can come in quickly, process large chunks of the web, and produce interesting results that would have been very difficult to produce otherwise. In the short time the system has been up, there have already been several papers using databases generated by Google, and many others are underway. Another goal we have is to set up a Spacelab-like environment where researchers or even students can propose and do interesting experiments on our large-scale web data. 
2. System FeaturesThe Google search engine has two important features that help it produce high precision results. First, it makes use of the link structure of the Web to calculate a quality ranking for each web page. This ranking is called PageRank and is described in detail in [Page 98]. Second, Google utilizes link to improve search results. 
2.1 PageRank: Bringing Order to the WebThe citation (link) graph of the web is an important resource that has largely gone unused in existing web search engines. We have created maps containing as many as 518 million of these hyperlinks, a significant sample of the total. These maps allow rapid calculation of a web page's "PageRank", an objective measure of its citation importance that corresponds well with people's subjective idea of importance. Because of this correspondence, PageRank is an excellent way to prioritize the results of web keyword searches. For most popular subjects, a simple text matching search that is restricted to web page titles performs admirably when PageRank prioritizes the results (demo available at google.stanford.edu). For the type of full text searches in the main Google system, PageRank also helps a great deal. 
2.1.1 Description of PageRank CalculationAcademic citation literature has been applied to the web, largely by counting citations or backlinks to a given page. This gives some approximation of a page's importance or quality. PageRank extends this idea by not counting links from all pages equally, and by normalizing by the number of links on a page. PageRank is defined as follows: 
We assume page A has pages T1...Tn which point to it (i.e., are citations). The parameter d is a damping factor which can be set between 0 and 1. We usually set d to 0.85. There are more details about d in the next section. Also C(A) is defined as the number of links going out of page A. The PageRank of a page A is given as follows:PR(A) = (1-d) + d (PR(T1)/C(T1) + ... + PR(Tn)/C(Tn))Note that the PageRanks form a probability distribution over web pages, so the sum of all web pages' PageRanks will be one.PageRank or PR(A) can be calculated using a simple iterative algorithm, and corresponds to the principal eigenvector of the normalized link matrix of the web. Also, a PageRank for 26 million web pages can be computed in a few hours on a medium size workstation. There are many other details which are beyond the scope of this paper. 
2.1.2 Intuitive JustificationPageRank can be thought of as a model of user behavior. We assume there is a "random surfer" who is given a web page at random and keeps clicking on links, never hitting "back" but eventually gets bored and starts on another random page. The probability that the random surfer visits a page is its PageRank. And, the d damping factor is the probability at each page the "random surfer" will get bored and request another random page. One important variation is to only add the damping factor d to a single page, or a group of pages. This allows for personalization and can make it nearly impossible to deliberately mislead the system in order to get a higher ranking. We have several other extensions to PageRank, again see [Page 98]. 
Another intuitive justification is that a page can have a high PageRank if there are many pages that point to it, or if there are some pages that point to it and have a high PageRank. Intuitively, pages that are well cited from many places around the web are worth looking at. Also, pages that have perhaps only one citation from something like the Yahoo! homepage are also generally worth looking at. If a page was not high quality, or was a broken link, it is quite likely that Yahoo's homepage would not link to it. PageRank handles both these cases and everything in between by recursively propagating weights through the link structure of the web. 
2.2 Anchor TextThe text of links is treated in a special way in our search engine. Most search engines associate the text of a link with the page that the link is on. In addition, we associate it with the page the link points to. This has several advantages. First, anchors often provide more accurate descriptions of web pages than the pages themselves. Second, anchors may exist for documents which cannot be indexed by a text-based search engine, such as images, programs, and databases. This makes it possible to return web pages which have not actually been crawled. Note that pages that have not been crawled can cause problems, since they are never checked for validity before being returned to the user. In this case, the search engine can even return a page that never actually existed, but had hyperlinks pointing to it. However, it is possible to sort the results, so that this particular problem rarely happens. 
This idea of propagating anchor text to the page it refers to was implemented in the World Wide Web Worm [McBryan 94] especially because it helps search non-text information, and expands the search coverage with fewer downloaded documents. We use anchor propagation mostly because anchor text can help provide better quality results. Using anchor text efficiently is technically difficult because of the large amounts of data which must be processed. In our current crawl of 24 million pages, we had over 259 million anchors which we indexed. 
2.3 Other FeaturesAside from PageRank and the use of anchor text, Google has several other features. First, it has location information for all hits and so it makes extensive use of proximity in search. Second, Google keeps track of some visual presentation details such as font size of words. Words in a larger or bolder font are weighted higher than other words. Third, full raw HTML of pages is available in a repository. 
3 Related WorkSearch research on the web has a short and concise history. The World Wide Web Worm (WWWW) [McBryan 94] was one of the first web search engines. It was subsequently followed by several other academic search engines, many of which are now public companies. Compared to the growth of the Web and the importance of search engines there are precious few documents about recent search engines [Pinkerton 94]. According to Michael Mauldin (chief scientist, Lycos Inc) [Mauldin], "the various services (including Lycos) closely guard the details of these databases". However, there has been a fair amount of work on specific features of search engines. Especially well represented is work which can get results by post-processing the results of existing commercial search engines, or produce small scale "individualized" search engines. Finally, there has been a lot of research on information retrieval systems, especially on well controlled collections. In the next two sections, we discuss some areas where this research needs to be extended to work better on the web. 
3.1 Information RetrievalWork in information retrieval systems goes back many years and is well developed [Witten 94]. However, most of the research on information retrieval systems is on small well controlled homogeneous collections such as collections of scientific papers or news stories on a related topic. Indeed, the primary benchmark for information retrieval, the Text Retrieval Conference [TREC 96], uses a fairly small, well controlled collection for their benchmarks. The "Very Large Corpus" benchmark is only 20GB compared to the 147GB from our crawl of 24 million web pages. Things that work well on TREC often do not produce good results on the web. For example, the standard vector space model tries to return the document that most closely approximates the query, given that both query and document are vectors defined by their word occurrence. On the web, this strategy often returns very short documents that are the query plus a few words. For example, we have seen a major search engine return a page containing only "Bill Clinton Sucks" and picture from a "Bill Clinton" query. Some argue that on the web, users should specify more accurately what they want and add more words to their query. We disagree vehemently with this position. If a user issues a query like "Bill Clinton" they should get reasonable results since there is a enormous amount of high quality information available on this topic. Given examples like these, we believe that the standard information retrieval work needs to be extended to deal effectively with the web. 
3.2 Differences Between the Web and Well Controlled CollectionsThe web is a vast collection of completely uncontrolled heterogeneous documents. Documents on the web have extreme variation internal to the documents, and also in the external meta information that might be available. For example, documents differ internally in their language (both human and programming), vocabulary (email addresses, links, zip codes, phone numbers, product numbers), type or format (text, HTML, PDF, images, sounds), and may even be machine generated (log files or output from a database). On the other hand, we define external meta information as information that can be inferred about a document, but is not contained within it. Examples of external meta information include things like reputation of the source, update frequency, quality, popularity or usage, and citations. Not only are the possible sources of external meta information varied, but the things that are being measured vary many orders of magnitude as well. For example, compare the usage information from a major homepage, like Yahoo's which currently receives millions of page views every day with an obscure historical article which might receive one view every ten years. Clearly, these two items must be treated very differently by a search engine. 
Another big difference between the web and traditional well controlled collections is that there is virtually no control over what people can put on the web. Couple this flexibility to publish anything with the enormous influence of search engines to route traffic and companies which deliberately manipulating search engines for profit become a serious problem. This problem that has not been addressed in traditional closed information retrieval systems. Also, it is interesting to note that metadata efforts have largely failed with web search engines, because any text on the page which is not directly represented to the user is abused to manipulate search engines. There are even numerous companies which specialize in manipulating search engines for profit. 
4 System AnatomyFirst, we will provide a high level discussion of the architecture. Then, there is some in-depth descriptions of important data structures. Finally, the major applications: crawling, indexing, and searching will be examined in depth. 
Figure 1. High Level Google Architecture   
4.1 Google Architecture OverviewIn this section, we will give a high level overview of how the whole system works as pictured in Figure 1. Further sections will discuss the applications and data structures not mentioned in this section. Most of Google is implemented in C or C++ for efficiency and can run in either Solaris or Linux. 
In Google, the web crawling (downloading of web pages) is done by several distributed crawlers. There is a URLserver that sends lists of URLs to be fetched to the crawlers. The web pages that are fetched are then sent to the storeserver. The storeserver then compresses and stores the web pages into a repository. Every web page has an associated ID number called a docID which is assigned whenever a new URL is parsed out of a web page. The indexing function is performed by the indexer and the sorter. The indexer performs a number of functions. It reads the repository, uncompresses the documents, and parses them. Each document is converted into a set of word occurrences called hits. The hits record the word, position in document, an approximation of font size, and capitalization. The indexer distributes these hits into a set of "barrels", creating a partially sorted forward index. The indexer performs another important function. It parses out all the links in every web page and stores important information about them in an anchors file. This file contains enough information to determine where each link points from and to, and the text of the link. 
The URLresolver reads the anchors file and converts relative URLs into absolute URLs and in turn into docIDs. It puts the anchor text into the forward index, associated with the docID that the anchor points to. It also generates a database of links which are pairs of docIDs. The links database is used to compute PageRanks for all the documents. 
The sorter takes the barrels, which are sorted by docID (this is a simplification, see Section 4.2.5), and resorts them by wordID to generate the inverted index. This is done in place so that little temporary space is needed for this operation. The sorter also produces a list of wordIDs and offsets into the inverted index. A program called DumpLexicon takes this list together with the lexicon produced by the indexer and generates a new lexicon to be used by the searcher. The searcher is run by a web server and uses the lexicon built by DumpLexicon together with the inverted index and the PageRanks to answer queries. 
4.2 Major Data StructuresGoogle's data structures are optimized so that a large document collection can be crawled, indexed, and searched with little cost. Although, CPUs and bulk input output rates have improved dramatically over the years, a disk seek still requires about 10 ms to complete. Google is designed to avoid disk seeks whenever possible, and this has had a considerable influence on the design of the data structures. 
4.2.1 BigFilesBigFiles are virtual files spanning multiple file systems and are addressable by 64 bit integers. The allocation among multiple file systems is handled automatically. The BigFiles package also handles allocation and deallocation of file descriptors, since the operating systems do not provide enough for our needs. BigFiles also support rudimentary compression options. 
4.2.2 Repository   
Figure 2. Repository Data StructureThe repository contains the full HTML of every web page. Each page is compressed using zlib (see RFC1950). The choice of compression technique is a tradeoff between speed and compression ratio. We chose zlib's speed over a significant improvement in compression offered by bzip. The compression rate of bzip was approximately 4 to 1 on the repository as compared to zlib's 3 to 1 compression. In the repository, the documents are stored one after the other and are prefixed by docID, length, and URL as can be seen in Figure 2. The repository requires no other data structures to be used in order to access it. This helps with data consistency and makes development much easier; we can rebuild all the other data structures from only the repository and a file which lists crawler errors. 
4.2.3 Document IndexThe document index keeps information about each document. It is a fixed width ISAM (Index sequential access mode) index, ordered by docID. The information stored in each entry includes the current document status, a pointer into the repository, a document checksum, and various statistics. If the document has been crawled, it also contains a pointer into a variable width file called docinfo which contains its URL and title. Otherwise the pointer points into the URLlist which contains just the URL. This design decision was driven by the desire to have a reasonably compact data structure, and the ability to fetch a record in one disk seek during a search 
Additionally, there is a file which is used to convert URLs into docIDs. It is a list of URL checksums with their corresponding docIDs and is sorted by checksum. In order to find the docID of a particular URL, the URL's checksum is computed and a binary search is performed on the checksums file to find its docID. URLs may be converted into docIDs in batch by doing a merge with this file. This is the technique the URLresolver uses to turn URLs into docIDs. This batch mode of update is crucial because otherwise we must perform one seek for every link which assuming one disk would take more than a month for our 322 million link dataset. 
4.2.4 LexiconThe lexicon has several different forms. One important change from earlier systems is that the lexicon can fit in memory for a reasonable price. In the current implementation we can keep the lexicon in memory on a machine with 256 MB of main memory. The current lexicon contains 14 million words (though some rare words were not added to the lexicon). It is implemented in two parts -- a list of the words (concatenated together but separated by nulls) and a hash table of pointers. For various functions, the list of words has some auxiliary information which is beyond the scope of this paper to explain fully. 
4.2.5 Hit ListsA hit list corresponds to a list of occurrences of a particular word in a particular document including position, font, and capitalization information. Hit lists account for most of the space used in both the forward and the inverted indices. Because of this, it is important to represent them as efficiently as possible. We considered several alternatives for encoding position, font, and capitalization -- simple encoding (a triple of integers), a compact encoding (a hand optimized allocation of bits), and Huffman coding. In the end we chose a hand optimized compact encoding since it required far less space than the simple encoding and far less bit manipulation than Huffman coding. The details of the hits are shown in Figure 3. 
Our compact encoding uses two bytes for every hit. There are two types of hits: fancy hits and plain hits. Fancy hits include hits occurring in a URL, title, anchor text, or meta tag. Plain hits include everything else. A plain hit consists of a capitalization bit, font size, and 12 bits of word position in a document (all positions higher than 4095 are labeled 4096). Font size is represented relative to the rest of the document using three bits (only 7 values are actually used because 111 is the flag that signals a fancy hit). A fancy hit consists of a capitalization bit, the font size set to 7 to indicate it is a fancy hit, 4 bits to encode the type of fancy hit, and 8 bits of position. For anchor hits, the 8 bits of position are split into 4 bits for position in anchor and 4 bits for a hash of the docID the anchor occurs in. This gives us some limited phrase searching as long as there are not that many anchors for a particular word. We expect to update the way that anchor hits are stored to allow for greater resolution in the position and docIDhash fields. We use font size relative to the rest of the document because when searching, you do not want to rank otherwise identical documents differently just because one of the documents is in a larger font. 
Figure 3. Forward and Reverse Indexes and the Lexicon  
The length of a hit list is stored before the hits themselves. To save space, the length of the hit list is combined with the wordID in the forward index and the docID in the inverted index. This limits it to 8 and 5 bits respectively (there are some tricks which allow 8 bits to be borrowed from the wordID). If the length is longer than would fit in that many bits, an escape code is used in those bits, and the next two bytes contain the actual length. 
4.2.6 Forward IndexThe forward index is actually already partially sorted. It is stored in a number of barrels (we used 64). Each barrel holds a range of wordID's. If a document contains words that fall into a particular barrel, the docID is recorded into the barrel, followed by a list of wordID's with hitlists which correspond to those words. This scheme requires slightly more storage because of duplicated docIDs but the difference is very small for a reasonable number of buckets and saves considerable time and coding complexity in the final indexing phase done by the sorter. Furthermore, instead of storing actual wordID's, we store each wordID as a relative difference from the minimum wordID that falls into the barrel the wordID is in. This way, we can use just 24 bits for the wordID's in the unsorted barrels, leaving 8 bits for the hit list length. 
4.2.7 Inverted IndexThe inverted index consists of the same barrels as the forward index, except that they have been processed by the sorter. For every valid wordID, the lexicon contains a pointer into the barrel that wordID falls into. It points to a doclist of docID's together with their corresponding hit lists. This doclist represents all the occurrences of that word in all documents. 
An important issue is in what order the docID's should appear in the doclist. One simple solution is to store them sorted by docID. This allows for quick merging of different doclists for multiple word queries. Another option is to store them sorted by a ranking of the occurrence of the word in each document. This makes answering one word queries trivial and makes it likely that the answers to multiple word queries are near the start. However, merging is much more difficult. Also, this makes development much more difficult in that a change to the ranking function requires a rebuild of the index. We chose a compromise between these options, keeping two sets of inverted barrels -- one set for hit lists which include title or anchor hits and another set for all hit lists. This way, we check the first set of barrels first and if there are not enough matches within those barrels we check the larger ones. 
4.3 Crawling the WebRunning a web crawler is a challenging task. There are tricky performance and reliability issues and even more importantly, there are social issues. Crawling is the most fragile application since it involves interacting with hundreds of thousands of web servers and various name servers which are all beyond the control of the system. 
In order to scale to hundreds of millions of web pages, Google has a fast distributed crawling system. A single URLserver serves lists of URLs to a number of crawlers (we typically ran about 3). Both the URLserver and the crawlers are implemented in Python. Each crawler keeps roughly 300 connections open at once. This is necessary to retrieve web pages at a fast enough pace. At peak speeds, the system can crawl over 100 web pages per second using four crawlers. This amounts to roughly 600K per second of data. A major performance stress is DNS lookup. Each crawler maintains a its own DNS cache so it does not need to do a DNS lookup before crawling each document. Each of the hundreds of connections can be in a number of different states: looking up DNS, connecting to host, sending request, and receiving response. These factors make the crawler a complex component of the system. It uses asynchronous IO to manage events, and a number of queues to move page fetches from state to state. 
It turns out that running a crawler which connects to more than half a million servers, and generates tens of millions of log entries generates a fair amount of email and phone calls. Because of the vast number of people coming on line, there are always those who do not know what a crawler is, because this is the first one they have seen. Almost daily, we receive an email something like, "Wow, you looked at a lot of pages from my web site. How did you like it?" There are also some people who do not know about the robots exclusion protocol, and think their page should be protected from indexing by a statement like, "This page is copyrighted and should not be indexed", which needless to say is difficult for web crawlers to understand. Also, because of the huge amount of data involved, unexpected things will happen. For example, our system tried to crawl an online game. This resulted in lots of garbage messages in the middle of their game! It turns out this was an easy problem to fix. But this problem had not come up until we had downloaded tens of millions of pages. Because of the immense variation in web pages and servers, it is virtually impossible to test a crawler without running it on large part of the Internet. Invariably, there are hundreds of obscure problems which may only occur on one page out of the whole web and cause the crawler to crash, or worse, cause unpredictable or incorrect behavior. Systems which access large parts of the Internet need to be designed to be very robust and carefully tested. Since large complex systems such as crawlers will invariably cause problems, there needs to be significant resources devoted to reading the email and solving these problems as they come up. 
4.4 Indexing the WebParsing -- Any parser which is designed to run on the entire Web must handle a huge array of possible errors. These range from typos in HTML tags to kilobytes of zeros in the middle of a tag, non-ASCII characters, HTML tags nested hundreds deep, and a great variety of other errors that challenge anyone's imagination to come up with equally creative ones. For maximum speed, instead of using YACC to generate a CFG parser, we use flex to generate a lexical analyzer which we outfit with its own stack. Developing this parser which runs at a reasonable speed and is very robust involved a fair amount of work. 
IndexingDocuments into Barrels -- After each document is parsed, it is encoded into a number of barrels. Every word is converted into a wordID by using an in-memory hash table -- the lexicon. New additions to the lexicon hash table are logged to a file. Once the words are converted into wordID's, their occurrences in the current document are translated into hit lists and are written into the forward barrels. The main difficulty with parallelization of the indexing phase is that the lexicon needs to be shared. Instead of sharing the lexicon, we took the approach of writing a log of all the extra words that were not in a base lexicon, which we fixed at 14 million words. That way multiple indexers can run in parallel and then the small log file of extra words can be processed by one final indexer. 
Sorting -- In order to generate the inverted index, the sorter takes each of the forward barrels and sorts it by wordID to produce an inverted barrel for title and anchor hits and a full text inverted barrel. This process happens one barrel at a time, thus requiring little temporary storage. Also, we parallelize the sorting phase to use as many machines as we have simply by running multiple sorters, which can process different buckets at the same time. Since the barrels don't fit into main memory, the sorter further subdivides them into baskets which do fit into memory based on wordID and docID. Then the sorter, loads each basket into memory, sorts it and writes its contents into the short inverted barrel and the full inverted barrel. 4.5 SearchingThe goal of searching is to provide quality search results efficiently. Many of the large commercial search engines seemed to have made great progress in terms of efficiency. Therefore, we have focused more on quality of search in our research, although we believe our solutions are scalable to commercial volumes with a bit more effort. The google query evaluation process is show in Figure 4. 
Parse the query. 
Convert words into wordIDs. 
Seek to the start of the doclist in the short barrel for every word. 
Scan through the doclists until there is a document that matches all the search terms. 
Compute the rank of that document for the query. 
If we are in the short barrels and at the end of any doclist, seek to the start of the doclist in the full barrel for every word and go to step 4. 
If we are not at the end of any doclist go to step 4. Sort the documents that have matched by rank and return the top k.Figure 4. Google Query Evaluation  
To put a limit on response time, once a certain number (currently 40,000) of matching documents are found, the searcher automatically goes to step 8 in Figure 4. This means that it is possible that sub-optimal results would be returned. We are currently investigating other ways to solve this problem. In the past, we sorted the hits according to PageRank, which seemed to improve the situation. 
4.5.1 The Ranking SystemGoogle maintains much more information about web documents than typical search engines. Every hitlist includes position, font, and capitalization information. Additionally, we factor in hits from anchor text and the PageRank of the document. Combining all of this information into a rank is difficult. We designed our ranking function so that no particular factor can have too much influence. First, consider the simplest case -- a single word query. In order to rank a document with a single word query, Google looks at that document's hit list for that word. Google considers each hit to be one of several different types (title, anchor, URL, plain text large font, plain text small font, ...), each of which has its own type-weight. The type-weights make up a vector indexed by type. Google counts the number of hits of each type in the hit list. Then every count is converted into a count-weight. Count-weights increase linearly with counts at first but quickly taper off so that more than a certain count will not help. We take the dot product of the vector of count-weights with the vector of type-weights to compute an IR score for the document. Finally, the IR score is combined with PageRank to give a final rank to the document. 
For a multi-word search, the situation is more complicated. Now multiple hit lists must be scanned through at once so that hits occurring close together in a document are weighted higher than hits occurring far apart. The hits from the multiple hit lists are matched up so that nearby hits are matched together. For every matched set of hits, a proximity is computed. The proximity is based on how far apart the hits are in the document (or anchor) but is classified into 10 different value "bins" ranging from a phrase match to "not even close". Counts are computed not only for every type of hit but for every type and proximity. Every type and proximity pair has a type-prox-weight. The counts are converted into count-weights and we take the dot product of the count-weights and the type-prox-weights to compute an IR score. All of these numbers and matrices can all be displayed with the search results using a special debug mode. These displays have been very helpful in developing the ranking system. 
4.5.2 FeedbackThe ranking function has many parameters like the type-weights and the type-prox-weights. Figuring out the right values for these parameters is something of a black art. In order to do this, we have a user feedback mechanism in the search engine. A trusted user may optionally evaluate all of the results that are returned. This feedback is saved. Then when we modify the ranking function, we can see the impact of this change on all previous searches which were ranked. Although far from perfect, this gives us some idea of how a change in the ranking function affects the search results. 
5 Results and Performance   
Query: bill clintonhttp://www.whitehouse.gov/   100.00%  (no date) (0K)   http://www.whitehouse.gov/         Office of the President           99.67% (Dec 23 1996) (2K)            http://www.whitehouse.gov/WH/EOP/OP/html/OP_Home.html        Welcome To The White House           99.98%  (Nov 09 1997) (5K)          http://www.whitehouse.gov/WH/Welcome.html          Send Electronic Mail to the President           99.86%  (Jul 14 1997) (5K)            http://www.whitehouse.gov/WH/Mail/html/Mail_President.html   mailto:president@whitehouse.gov   99.98%          mailto:President@whitehouse.gov           99.27%    The "Unofficial" Bill Clinton    94.06% (Nov 11 1997) (14K)   http://zpub.com/un/un-bc.html          Bill Clinton Meets The Shrinks             86.27%  (Jun 29 1997) (63K)             http://zpub.com/un/un-bc9.html   President Bill Clinton - The Dark Side   97.27%  (Nov 10 1997) (15K)   http://www.realchange.org/clinton.htm   $3 Bill Clinton   94.73%  (no date) (4K) http://www.gatewy.net/~tjohnson/clinton1.html   
Figure 4. Sample Results from GoogleThe most important measure of a search engine is the quality of its search results. While a complete user evaluation is beyond the scope of this paper, our own experience with Google has shown it to produce better results than the major commercial search engines for most searches. As an example which illustrates the use of PageRank, anchor text, and proximity, Figure 4 shows Google's results for a search on "bill clinton". These results demonstrates some of Google's features. The results are clustered by server. This helps considerably when sifting through result sets. A number of results are from the whitehouse.gov domain which is what one may reasonably expect from such a search. Currently, most major commercial search engines do not return any results from whitehouse.gov, much less the right ones. Notice that there is no title for the first result. This is because it was not crawled. Instead, Google relied on anchor text to determine this was a good answer to the query. Similarly, the fifth result is an email address which, of course, is not crawlable. It is also a result of anchor text. 
All of the results are reasonably high quality pages and, at last check, none were broken links. This is largely because they all have high PageRank. The PageRanks are the percentages in red along with bar graphs. Finally, there are no results about a Bill other than Clinton or about a Clinton other than Bill. This is because we place heavy importance on the proximity of word occurrences. Of course a true test of the quality of a search engine would involve an extensive user study or results analysis which we do not have room for here. Instead, we invite the reader to try Google for themselves at http://google.stanford.edu. 
5.1 Storage RequirementsAside from search quality, Google is designed to scale cost effectively to the size of the Web as it grows. One aspect of this is to use storage efficiently. Table 1 has a breakdown of some statistics and storage requirements of Google. Due to compression the total size of the repository is about 53 GB, just over one third of the total data it stores. At current disk prices this makes the repository a relatively cheap source of useful data. More importantly, the total of all the data used by the search engine requires a comparable amount of storage, about 55 GB. Furthermore, most queries can be answered using just the short inverted index. With better encoding and compression of the Document Index, a high quality web search engine may fit onto a 7GB drive of a new PC.    
Storage StatisticsTotal Size of Fetched Pages147.8 GBCompressed Repository53.5 GBShort Inverted Index4.1 GBFull Inverted Index37.2 GBLexicon293 MBTemporary Anchor Data  (not in total)6.6 GBDocument Index Incl.  Variable Width Data9.7 GBLinks Database3.9 GBTotal Without Repository55.2 GBTotal With Repository108.7 GB Web Page StatisticsNumber of Web Pages Fetched24 millionNumber of Urls Seen76.5 millionNumber of Email Addresses1.7 millionNumber of 404's1.6 million Table 1. Statistics   
 5.2 System PerformanceIt is important for a search engine to crawl and index efficiently. This way information can be kept up to date and major changes to the system can be tested relatively quickly. For Google, the major operations are Crawling, Indexing, and Sorting. It is difficult to measure how long crawling took overall because disks filled up, name servers crashed, or any number of other problems which stopped the system. In total it took roughly 9 days to download the 26 million pages (including errors). However, once the system was running smoothly, it ran much faster, downloading the last 11 million pages in just 63 hours, averaging just over 4 million pages per day or 48.5 pages per second. We ran the indexer and the crawler simultaneously. The indexer ran just faster than the crawlers. This is largely because we spent just enough time optimizing the indexer so that it would not be a bottleneck. These optimizations included bulk updates to the document index and placement of critical data structures on the local disk. The indexer runs at roughly 54 pages per second. The sorters can be run completely in parallel; using four machines, the whole process of sorting takes about 24 hours. 
5.3 Search PerformanceImproving the performance of search was not the major focus of our research up to this point. The current version of Google answers most queries in between 1 and 10 seconds. This time is mostly dominated by disk IO over NFS (since disks are spread over a number of machines). Furthermore, Google does not have any optimizations such as query caching, subindices on common terms, and other common optimizations. We intend to speed up Google considerably through distribution and hardware, software, and algorithmic improvements. Our target is to be able to handle several hundred queries per second. Table 2 has some sample query times from the current version of Google. They are repeated to show the speedups resulting from cached IO. 
 Initial QuerySame Query Repeated (IO mostly cached) QueryCPU Time(s)Total Time(s)CPU Time(s)Total Time(s)al gore0.092.130.060.06vice president1.773.841.661.80hard disks0.254.860.200.24search engines1.319.631.161.16 Table 2. Search Times   
6 ConclusionsGoogle is designed to be a scalable search engine. The primary goal is to provide high quality search results over a rapidly growing World Wide Web. Google employs a number of techniques to improve search quality including page rank, anchor text, and proximity information. Furthermore, Google is a complete architecture for gathering web pages, indexing them, and performing search queries over them. 
6.1 Future WorkA large-scale web search engine is a complex system and much remains to be done. Our immediate goals are to improve search efficiency and to scale to approximately 100 million web pages. Some simple improvements to efficiency include query caching, smart disk allocation, and subindices. Another area which requires much research is updates. We must have smart algorithms to decide what old web pages should be recrawled and what new ones should be crawled. Work toward this goal has been done in [Cho 98]. One promising area of research is using proxy caches to build search databases, since they are demand driven. We are planning to add simple features supported by commercial search engines like boolean operators, negation, and stemming. However, other features are just starting to be explored such as relevance feedback and clustering (Google currently supports a simple hostname based clustering). We also plan to support user context (like the user's location), and result summarization. We are also working to extend the use of link structure and link text. Simple experiments indicate PageRank can be personalized by increasing the weight of a user's home page or bookmarks. As for link text, we are experimenting with using text surrounding links in addition to the link text itself. A Web search engine is a very rich environment for research ideas. We have far too many to list here so we do not expect this Future Work section to become much shorter in the near future. 
6.2 High Quality SearchThe biggest problem facing users of web search engines today is the quality of the results they get back. While the results are often amusing and expand users' horizons, they are often frustrating and consume precious time. For example, the top result for a search for "Bill Clinton" on one of the most popular commercial search engines was the Bill Clinton Joke of the Day: April 14, 1997. Google is designed to provide higher quality search so as the Web continues to grow rapidly, information can be found easily. In order to accomplish this Google makes heavy use of hypertextual information consisting of link structure and link (anchor) text. Google also uses proximity and font information. While evaluation of a search engine is difficult, we have subjectively found that Google returns higher quality search results than current commercial search engines. The analysis of link structure via PageRank allows Google to evaluate the quality of web pages. The use of link text as a description of what the link points to helps the search engine return relevant (and to some degree high quality) results. Finally, the use of proximity information helps increase relevance a great deal for many queries. 
6.3 Scalable ArchitectureAside from the quality of search, Google is designed to scale. It must be efficient in both space and time, and constant factors are very important when dealing with the entire Web. In implementing Google, we have seen bottlenecks in CPU, memory access, memory capacity, disk seeks, disk throughput, disk capacity, and network IO. Google has evolved to overcome a number of these bottlenecks during various operations. Google's major data structures make efficient use of available storage space. Furthermore, the crawling, indexing, and sorting operations are efficient enough to be able to build an index of a substantial portion of the web -- 24 million pages, in less than one week. We expect to be able to build an index of 100 million pages in less than a month. 
6.4 A Research ToolIn addition to being a high quality search engine, Google is a research tool. The data Google has collected has already resulted in many other papers submitted to conferences and many more on the way. Recent research such as [Abiteboul 97] has shown a number of limitations to queries about the Web that may be answered without having the Web available locally. This means that Google (or a similar system) is not only a valuable research tool but a necessary one for a wide range of applications. We hope Google will be a resource for searchers and researchers all around the world and will spark the next generation of search engine technology. 
7 AcknowledgmentsScott Hassan and Alan Steremberg have been critical to the development of Google. Their talented contributions are irreplaceable, and the authors owe them much gratitude. We would also like to thank Hector Garcia-Molina, Rajeev Motwani, Jeff Ullman, and Terry Winograd and the whole WebBase group for their support and insightful discussions. Finally we would like to recognize the generous support of our equipment donors IBM, Intel, and Sun and our funders. The research described here was conducted as part of the Stanford Integrated Digital Library Project, supported by the National Science Foundation under Cooperative Agreement IRI-9411306. Funding for this cooperative agreement is also provided by DARPA and NASA, and by Interval Research, and the industrial partners of the Stanford Digital Libraries Project. 
ReferencesBest of the Web 1994 -- Navigators http://botw.org/1994/awards/navigators.htmlBill Clinton Joke of the Day: April 14, 1997. http://www.io.com/~cjburke/clinton/970414.htmlBzip2 Homepage http://www.muraroa.demon.co.uk/Google Search Engine http://google.stanford.eduHarvest http://harvest.transarc.com/Mauldin, Michael L. Lycos Design Choices in an Internet Search Service, IEEE Expert Interview http://www.computer.org/pubs/expert/1997/trends/x1008/mauldin.htmThe Effect of Cellular Phone Use Upon Driver Attention http://www.webfirst.com/aaa/text/cell/cell0toc.htmSearch Engine Watch http://www.searchenginewatch.com/RFC 1950 (zlib) ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.htmlRobots Exclusion Protocol: http://info.webcrawler.com/mak/projects/robots/exclusion.htmlWeb Growth Summary: http://www.mit.edu/people/mkgray/net/web-growth-summary.htmlYahoo! http://www.yahoo.com/[Abiteboul 97] Serge Abiteboul and Victor Vianu, Queries and Computation on the Web. Proceedings of the International Conference on Database Theory. Delphi, Greece 1997. 
[Bagdikian 97] Ben H. Bagdikian. The Media Monopoly. 5th Edition. Publisher: Beacon, ISBN: 0807061557 
[Chakrabarti 98] S.Chakrabarti, B.Dom, D.Gibson, J.Kleinberg, P. Raghavan and S. Rajagopalan. Automatic Resource Compilation by Analyzing Hyperlink Structure and Associated Text. Seventh International Web Conference (WWW 98). Brisbane, Australia, April 14-18, 1998. 
[Cho 98] Junghoo Cho, Hector Garcia-Molina, Lawrence Page. Efficient Crawling Through URL Ordering. Seventh International Web Conference (WWW 98). Brisbane, Australia, April 14-18, 1998. 
[Gravano 94] Luis Gravano, Hector Garcia-Molina, and A. Tomasic. The Effectiveness of GlOSS for the Text-Database Discovery Problem. Proc. of the 1994 ACM SIGMOD International Conference On Management Of Data, 1994. 
[Kleinberg 98] Jon Kleinberg, Authoritative Sources in a Hyperlinked Environment, Proc. ACM-SIAM Symposium on Discrete Algorithms, 1998. 
[Marchiori 97] Massimo Marchiori. The Quest for Correct Information on the Web: Hyper Search Engines. The Sixth International WWW Conference (WWW 97). Santa Clara, USA, April 7-11, 1997. 
[McBryan 94] Oliver A. McBryan. GENVL and WWWW: Tools for Taming the Web. First International Conference on the World Wide Web. CERN, Geneva (Switzerland), May 25-26-27 1994. http://www.cs.colorado.edu/home/mcbryan/mypapers/www94.ps[Page 98] Lawrence Page, Sergey Brin, Rajeev Motwani, Terry Winograd. The PageRank Citation Ranking: Bringing Order to the Web. Manuscript in progress. http://google.stanford.edu/~backrub/pageranksub.ps[Pinkerton 94] Brian Pinkerton, Finding What People Want: Experiences with the WebCrawler. The Second International WWW Conference Chicago, USA, October 17-20, 1994. http://info.webcrawler.com/bp/WWW94.html[Spertus 97] Ellen Spertus. ParaSite: Mining Structural Information on the Web. The Sixth International WWW Conference (WWW 97). Santa Clara, USA, April 7-11, 1997. 
[TREC 96] Proceedings of the fifth Text REtrieval Conference (TREC-5). Gaithersburg, Maryland, November 20-22, 1996. Publisher: Department of Commerce, National Institute of Standards and Technology. Editors: D. K. Harman and E. M. Voorhees. Full text at: http://trec.nist.gov/[Witten 94] Ian H Witten, Alistair Moffat, and Timothy C. Bell. Managing Gigabytes: Compressing and Indexing Documents and Images. New York: Van Nostrand Reinhold, 1994. 
[Weiss 96] Ron Weiss, Bienvenido Velez, Mark A. Sheldon, Chanathip Manprempre, Peter Szilagyi, Andrzej Duda, and David K. Gifford. HyPursuit: A Hierarchical Network Search Engine that Exploits Content-Link Hypertext Clustering. Proceedings of the 7th ACM Conference on Hypertext. New York, 1996. VitaeSergey Brin received his B.S. degree in mathematics and computer science from the University of Maryland at College Park in 1993. Currently, he is a Ph.D. candidate in computer science at Stanford University where he received his M.S. in 1995. He is a recipient of a National Science Foundation Graduate Fellowship. His research interests include search engines, information extraction from unstructured sources, and data mining of large text collections and scientific data. 
Lawrence Page was born in East Lansing, Michigan, and received a B.S.E. in Computer Engineering at the University of Michigan Ann Arbor in 1995. He is currently a Ph.D. candidate in Computer Science at Stanford University. Some of his research interests include the link structure of the web, human computer interaction, search engines, scalability of information access interfaces, and personal data mining. 
8 Appendix A: Advertising and Mixed MotivesCurrently, the predominant business model for commercial search engines is advertising. The goals of the advertising business model do not always correspond to providing quality search to users. For example, in our prototype search engine one of the top results for cellular phone is "The Effect of Cellular Phone Use Upon Driver Attention", a study which explains in great detail the distractions and risk associated with conversing on a cell phone while driving. This search result came up first because of its high importance as judged by the PageRank algorithm, an approximation of citation importance on the web [Page, 98]. It is clear that a search engine which was taking money for showing cellular phone ads would have difficulty justifying the page that our system returned to its paying advertisers. For this type of reason and historical experience with other media [Bagdikian 83], we expect that advertising funded search engines will be inherently biased towards the advertisers and away from the needs of the consumers. 
Since it is very difficult even for experts to evaluate search engines, search engine bias is particularly insidious. A good example was OpenText, which was reported to be selling companies the right to be listed at the top of the search results for particular queries [Marchiori 97]. This type of bias is much more insidious than advertising, because it is not clear who "deserves" to be there, and who is willing to pay money to be listed. This business model resulted in an uproar, and OpenText has ceased to be a viable search engine. But less blatant bias are likely to be tolerated by the market. For example, a search engine could add a small factor to search results from "friendly" companies, and subtract a factor from results from competitors. This type of bias is very difficult to detect but could still have a significant effect on the market. Furthermore, advertising income often provides an incentive to provide poor quality search results. For example, we noticed a major search engine would not return a large airline's homepage when the airline's name was given as a query. It so happened that the airline had placed an expensive ad, linked to the query that was its name. A better search engine would not have required this ad, and possibly resulted in the loss of the revenue from the airline to the search engine. In general, it could be argued from the consumer point of view that the better the search engine is, the fewer advertisements will be needed for the consumer to find what they want. This of course erodes the advertising supported business model of the existing search engines. However, there will always be money from advertisers who want a customer to switch products, or have something that is genuinely new. But we believe the issue of advertising causes enough mixed incentives that it is crucial to have a competitive search engine that is transparent and in the academic realm. 
9 Appendix B: Scalability9. 1 Scalability of GoogleWe have designed Google to be scalable in the near term to a goal of 100 million web pages. We have just received disk and machines to handle roughly that amount. All of the time consuming parts of the system are parallelize and roughly linear time. These include things like the crawlers, indexers, and sorters. We also think that most of the data structures will deal gracefully with the expansion. However, at 100 million web pages we will be very close up against all sorts of operating system limits in the common operating systems (currently we run on both Solaris and Linux). These include things like addressable memory, number of open file descriptors, network sockets and bandwidth, and many others. We believe expanding to a lot more than 100 million pages would greatly increase the complexity of our system. 
9.2 Scalability of Centralized Indexing ArchitecturesAs the capabilities of computers increase, it becomes possible to index a very large amount of text for a reasonable cost. Of course, other more bandwidth intensive media such as video is likely to become more pervasive. But, because the cost of production of text is low compared to media like video, text is likely to remain very pervasive. Also, it is likely that soon we will have speech recognition that does a reasonable job converting speech into text, expanding the amount of text available. All of this provides amazing possibilities for centralized indexing. Here is an illustrative example. We assume we want to index everything everyone in the US has written for a year. We assume that there are 250 million people in the US and they write an average of 10k per day. That works out to be about 850 terabytes. Also assume that indexing a terabyte can be done now for a reasonable cost. We also assume that the indexing methods used over the text are linear, or nearly linear in their complexity. Given all these assumptions we can compute how long it would take before we could index our 850 terabytes for a reasonable cost assuming certain growth factors. Moore's Law was defined in 1965 as a doubling every 18 months in processor power. It has held remarkably true, not just for processors, but for other important system parameters such as disk as well. If we assume that Moore's law holds for the future, we need only 10 more doublings, or 15 years to reach our goal of indexing everything everyone in the US has written for a year for a price that a small company could afford. Of course, hardware experts are somewhat concerned Moore's Law may not continue to hold for the next 15 years, but there are certainly a lot of interesting centralized applications even if we only get part of the way to our hypothetical example. 
Of course a distributed systems like Gloss [Gravano 94] or Harvest will often be the most efficient and elegant technical solution for indexing, but it seems difficult to convince the world to use these systems because of the high administration costs of setting up large numbers of installations. Of course, it is quite likely that reducing the administration cost drastically is possible. If that happens, and everyone starts running a distributed indexing system, searching would certainly improve drastically. 
Because humans can only type or speak a finite amount, and as computers continue improving, text indexing will scale even better than it does now. Of course there could be an infinite amount of machine generated content, but just indexing huge amounts of human generated content seems tremendously useful. So we are optimistic that our centralized web search engine architecture will improve in its ability to cover the pertinent text information over time and that there is a bright future for search. ]]></description> 
					<pubDate>Thu, 03 Aug 2006 05:08:33 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/8/2/howgooglerankspages/</guid>
				</item>
			
				<item>
					<title>How Google Can Find Your Secret Page</title> 
					<link>http://keylimetie.com/blog/2006/24/7/googlesecretpage/</link> 
					<description><![CDATA[From author David A. Utter of WebProNewshttp://www.webpronews.com/topnews/topnews/wpn-60-20060721HowGoogleCanFindYourSecretPage.htmlAmazingly enough, some webmasters haven't learned about Google yet, and how easy it is to retrieve pages that have been poorly 
protected from being viewed.
When the blogger behind the brand new 
EvolvedLight blog wanted to find out more information regarding an 
accident at Alton Towers amusement park in Staffordshire, 
England, the quest for information led to the park's 
media page.

"This site is for Media use only. To gain an access password please call 01538 704015," reads the page. Instead, the blogger turned 
to the ubiquitous Google to indulge in a little Google hacking.

In looking at the source code, one section revealed that whatever is entered as a password would trigger a redirect to a page 
named {password}.html. The right password would reveal the press page.

So the blogger sent Google a simple search string: * 
site:http://press.altontowers.com and guess what was revealed as the third result in the SERPs? 

"Welcome 
to the Alton Towers Press Site," said the revealed page, called pressxpsa.html. That means the password would be 
pressxpsa. And indeed it is. To call this a poorly designed page would be an insult to poorly designed pages everywhere. 
In the interest of helping out someone in need, here is a Microsoft link on 
securing ASP pages for the amusement park's Windows Server 
2003 host running IIS 6.]]></description> 
					<pubDate>Tue, 25 Jul 2006 05:49:50 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/24/7/googlesecretpage/</guid>
				</item>
			
				<item>
					<title>Google Sitemap Generator v3.0 Released!!!!</title> 
					<link>http://keylimetie.com/blog/2006/7/14/googlesitemapgenerator/</link> 
					<description><![CDATA[
				Version 4.1 is now available! 
				
						
								Click here for more details!
						
				
		
		
		
		
		(You will automatically be redirected to the new version in 5 seconds). 
]]></description> 
					<pubDate>Sat, 15 Jul 2006 03:22:45 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/7/14/googlesitemapgenerator/</guid>
				</item>
			
				<item>
					<title>SQL Server Everywhere, not for me</title> 
					<link>http://keylimetie.com/blog/2006/7/11/sqlservereverywhere/</link> 
					<description><![CDATA[From Microsoft.com: "Microsoft SQL Server 2005 Everywhere Edition offers essential relational database functionality in a compact footprint ideal for embedding in mobile and desktop applications including a new generation of occasionally connected dynamic applications." I'm not sure I agree.Here is my inital list of pros/cons from a developers point of view:ProsCompletely run in-proc, meaning there is no installation requiredFree to develop, deploy and redistributeAllows up to 4GB databasesSupport for up to 256 connectionsVery compact (max of 7 DLLs required at 1.4 MB)ConsNo user interface available (I had to create my database through code)...I'm sure a 3rd party will develop one very soon.Support for only a limited number of datatypes - for example, supports nvarchar, but not varchar or the XML data type!Does not support stored procedures, views,  triggers, extended stored procedures, or macros.Sample ApplicationThe code is not that complicated, so I'm not going to write up a technical explanation. But in my overall opinion, this product seems to be a much more powerful version of Access without the interface. I don't see myself using it anytime soon.I spent a few hours reading about SQL Server Everywhere and put together this sample application.Download Sample ApplicationForm1.csUseful linksDownloaded SQL Server Everywhere: http://www.microsoft.com/sql/ctp_sqleverywhere.mspxPaul Flessner announced SQL Server Everywhere: http://www.microsoft.com/sql/letter.mspxSteve Lasker's Blog -  Interview with Paul Flessner: http://blogs.msdn.com/stevelasker/archive/2006/04/10/SqlEverywhereInfo.aspx]]></description> 
					<pubDate>Wed, 12 Jul 2006 00:07:54 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/7/11/sqlservereverywhere/</guid>
				</item>
			
				<item>
					<title>Getting Your Site Indexed Before You Launch</title> 
					<link>http://keylimetie.com/blog/2006/7/5/indexsitebeforelaunch/</link> 
					<description><![CDATA[Here's an interesting article on getting your site indexed on search engines before it's really live.http://www.site-reference.com/articles/Search-Engines/Getting-Your-Site-Indexed-Before-You-Launch.html]]></description> 
					<pubDate>Thu, 06 Jul 2006 03:13:20 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/7/5/indexsitebeforelaunch/</guid>
				</item>
			
				<item>
					<title>10 Recommendations for Software Developers</title> 
					<link>http://keylimetie.com/blog/2006/7/4/tenrecommendations/</link> 
					<description><![CDATA[
				Over the past 10 years, I have spent a good amount of time teaching software development. First in college, I was a teaching assistant at NorthernIllinoisUniversity. Then after graduating, I worked for a couple companies and did some internal training. Over the years, I have helped a few friends get into the IT industry…taught them the basics and helped get their foot in the door of a new career. I now provide training for companies on a consultant basis.
		
		
				
						 
				
		
		
				I have learned a lot from people, books, magazines, conferences and online…and continue to learn more everyday. At least once a week, I get emails from people who are getting started in software development. Some people have questions while others just thank me for the articles that I publish. Beginning developers often ask something like, “What do you recommend I do so I can become a full time web developer?” More experienced developers often ask what I would recommend to help advance their careers or become an independent contractor.
		
		
				
						 
				
		
		
				These answers are not easy…it depends on your experience, your available time, and most importantly, your drive. But I took the time to put together what I think is important. The first 5 are for those of you just getting started and the last 5 are for the life of your career.
		
		
				
						 
				
		
		
				
						
								Find Good Resources – Whether it’s a friend, colleague, website forum or some online community, try to find at least one good resource. When I graduated college, most of my skills were mainframe-based (Cobol, JCL, etc.). I immediately got a job with IBM but I really wanted to do web development. So I bought a few ASP and Visual Basic 6.0 books, read through them and did the examples. It all made sense, but I wanted to get some practical experience. I was consulting at Allstate Insurance at the time (mainframe area) and had a great deal of knowledge of their systems. Allstate had made the decision to get on the web at that time (May 2000) and I was able to get a position as a business knowledge expert. As the project progressed, I became friends with several of the developers and had great people to bounce questions off of. Over the next 6 months, I learned more than ever…they told me what to learn now, what book chapters to skip for now, what was important, what was not important. Everything became very clear, I developed a couple ecommerce sites (including Cigars Around the World’s first true database-driven, ecommerce site) and earned my MSCD in VB 6.0. This may be the most important recommendation for getting started…but be careful, there are a ton of hacks out there and you do not want their advice!
				
		
		
				
						 
				
		
		
				
						
								Learn the Basics – 75% of the code you write can be written in any language. Your most common tasks will include declaring variables, assigning values, performing calculations, looping through data, if…then…else, functions, etc. Every language supports these features and they must be mastered. Any “Introduction” book will cover these features in very good detail. If a book has at least a dozen or so reviews, see what the consensus says. Better yet, a good resource should be able to recommend a good starter book. I also highly recommend buying an introduction book for the language you plan on developing in. You might not know what that is, but you should have a good idea. You want to always be reading in the language you are learning…this may seem obvious, but I know people who want to learn C#, but are reading a C++ book because their brother had one laying around. If you want to learn C#, make the investment of buying a good C# book. And don’t worry too much about choosing a language to start with…as I said above, the basics translate to any language…it’s just syntax differences.
				
		
		
				
						 
				
		
		
				
						
								Keep It Simple – I have a friend who says this all the time in meetings where we’re discussing how we want to solve a particular issue. That’s all he says…really. Most people kind of laugh at it. I used to, but then I thought about it a little and now I consciously practice it. If you put 1,000 developers in a room and gave them even a simple coding task, not one person would code it the same. The question is, would everyone be able to read your code…and if you looked at it a few months later, would you be able to quickly read and understand it? There are a million ways to solve any problem; the best approach is to keep it simple. It makes it much easier to maintain and also decreases the chance of someone else breaking it (including yourself!).
				
		
		
				
						 
				
		
		
				
						
								Learn By Doing – Reading and comprehending a subject isn’t that difficult….but can you really apply what you just learned? I have tried to get through books very fast and skip over some of the “Chapter Tasks” at the end. The next day, I couldn’t tell you much about what I had read. That’s why I make a point of immediately performing all of the exercises in a book. When I’m teaching a friend programming (as I am right now), we typically work side by side on separate computers. We both do everything I’m teaching and he’s learning. I could just sit there are type everything as he watches, but it has been my experience that it never works. The more time you spend in the software development environment (i.e. Visual Studio.NET, SQL Server Management Studio, etc.), the more comfortable you will get.
				
		
		
				
						 
				
		
		
				
						
								Plan your Code, Code your Plan – One of the biggest mistake developers make is to start coding right away. Big mistake! I cannot express that enough! People get all excited about creating an interface, designing the logo, blah, blah, blah. Yeah, that’s fun, but it’s not the correct approach to take. There are entire courses on proper systems design and architecture (which are definitely worthwhile!), but the basic approach to a System Development Life Cycle (SDLC) is this.
				
		
		
				
						 
				
		
		
				
						
								Project planning and feasibility study: Establish a high-level view of the project and determines its goals. 
						
						
								Systems analysis and requirements definition: Refine goals into defined functions. Analyze end-user needs. 
						
						
								Systems design: Describe desired features in detail, including screen layouts, business rules, process diagrams and other documentation. 
						
						
								Implementation: Write the code. Personally, I design the database first, 
						
						
								Testing: Check for errors, bugs and interoperability. 
						
						
								Deployment: The final stage of the initial development where the software is put into production and runs the actual business. 
						
						
								Maintenance: The rest of the software's life: changes, correction, additions, moves to a different platforms, etc. This, the least glamorous and perhaps most important step of all, goes on seemingly forever.
						
				
		
		
				
						 
				
		
		
				It is so important that you follow these or some other SDLC approach. The amount of upfront planning and preparation will save you tons of time in the long run. 
		
		
				
						 
				
		
		
				
						
								Don’t be lazy! – Often, you might seem under a lot of pressure to get something done very quickly…it is very important to never compromise the quality of the software to get something done fast. Even worse than that are people who take the shortcut or “band-aid” code just to be done with it. These are the worst developers and are not respected. If you there is any chance a user might do something on your website, be sure to account for it…because they will do it! I can think of at least a half dozen cases where a fellow developer did not code for some scenario because “there’s no way anyone would ever do that”. And more times than not, some user somewhere did it…and I’ve seen entire websites crash because of it (and people do get fired). The developer always blames the user for being stupid and doing what should not have been done, when in fact the developer is the real idiot. Don’t be lazy…don’t be a hack…do it right.
				
		
		
				
						 
				
		
		
				
						
								Put First Things First - One of the best books I have ever read (and read at least once every year) is Stephen Covey’s “7 Habit’s of Highly Effective People”. He says in Habit 3: Put First Things First, “The key is not to prioritize your schedule, but to schedule your priorities. Do the most important things first – because where you are headed is more important than how fast you are going”. He also says of all of the 7 habits, this is the hardest one to master. I completely agree…it is so easy to work on the fun tasks or prioritize what may seem urgent over working on the not-so-fun things than require time and serious thought. But what’s important should always take precedence over what’s considered urgent. Self discipline can be difficult and you have to realize these tasks you’re pushing aside for another time will never go away. You have to do them and you have to make them a priority. In Covey’s book, he also referenced a lifelong study on what the common trait among successful people is. The answer: successful people know to “Put First Things First”. This may be the most important recommendation you’re your continued career.
				
		
		
				
						 
				
		
		
				
						
								Reuse, Reuse, Reuse – You should never need to rewrite the same logic of code ever. Does your application send emails out? If so, you better have one “SendEmail” method that everyone uses. Do you query the database for the current specials to be displayed on every page? You better have that method encapsulated in a database tier and every page better be getting the data through that method (Better yet, you better be caching that data to eliminate the extra database queries!). Whenever I start coding a new website (after the database has been designed), the first thing I do is add in my “Common” code. This common code takes care of all of the tasks common to every website, which includes validation, javascript and form helpers, constants, enumerations, exception handling, emailing, base classes, and much more. At least 10-15% of my code is now done and I know it works perfectly. The next thing I do is generate my data access tier. I always write my data access code the same from project to project: I create custom classes to represent data entities, I pass all data from tier to tier through these custom classes and I use the Microsoft Data Access Blocks to do the database access. It’s really time consuming to create the custom classes, CRUD methods and the stored procedures, so I create my own data tier generator. With the data tier generator, I click one button and everything is generated in a couple of seconds…hours and hours of work now done instantaneously and I know the code is perfect. Work smart, not hard.
				
		
		
				
						 
				
		
		
				
						
								Certifications – Get certified or not? This has been a debate among fellow developers for a long time. My personal belief is to get certified, but it’s not priority #1. My reasons include:
						
								
										I have interviewed for contracts where they only accepted resumes from people who were at least an MCSD (Microsoft Certified Solution Developer).
								
								
										I have taken several tests and they are not easy…they do require a very good deal of knowledge and understanding in order to pass.
								
								
										Some companies give bonuses or raises for obtaining your certification
								
								
										Instant credibility – Only those who do not believe in the program will not care…the other 99% who know what the certification is or do not know what it is have an instant feeling that you know what you’re doing.
								
						
				
		
		
				
						 
				
		
		
				Most people I speak to agree getting certified is a good idea. Some are indifferent and a few completely disagree. The main disagreement is that anyone can get certified. They’re just tests and there are “brain dump” websites out there where people post questions and answers right after taking the tests. These are true statements, but almost every interview I have been on for a contract or short term assignment have looked very positive on my certification. I certainly believe getting certified has made my career as an independent contractor a lot easier…and it obviously cannot hurt it.
		
		
				
						 
				
		
		
				
						
								Continued Education – This is what separates the real developers from the 9-5’ers. Most programmers get by with the basics. They know enough to get the job done, work their 8 hours every day and go home to do nothing. Those with drive and ambition to be great continue their education everyday…even at home. Whether it’s reading technical magazines, online articles, blogs, or picking up a good book, anything you do to stay on top of the latest technology will give you a huge advantage. Not only will you continue to work with the latest software, but you will also be much more sought after, have much better job security and be able to bill a much higher rate. I personally subscribe to 4 technical magazines and a few weekly newsletters. I also try to read one good book per month. By doing this, I am always reading about the newest software and have learned great approaches to difficult solutions (which saves me a ton of time and work). My favorite site is The Code Project. They send out a weekly newsletter that lists the recent articles by category. They enforce an excellent format that is easy to follow and provide an area for feedback. When searching for a way to do something specific, I often go here first and almost always find it. Whatever approach you take, make a conscious effort to keep learning. By being smarter and better than the rest, you have complete control of your career…which leads to more opportunities…which leads to a very enjoyable life.
				
		
		
				
						 
				
		]]></description> 
					<pubDate>Tue, 04 Jul 2006 18:26:41 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/7/4/tenrecommendations/</guid>
				</item>
			
				<item>
					<title>Google File System - How Google does it...</title> 
					<link>http://keylimetie.com/blog/2006/6/27/googlefilesystem/</link> 
					<description><![CDATA[While many IT shops deal with the issues related to hundreds or thousands of users, Google regularly manages, administers and upgrades software and systems for millions of users. How do they do it? I found this article with an excellent overview of the Google file system and its unique capabilities.http://storagemojo.com/?page_id=152]]></description> 
					<pubDate>Wed, 28 Jun 2006 05:04:39 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/6/27/googlefilesystem/</guid>
				</item>
			
				<item>
					<title>ASP.NET 2.0 environment setup</title> 
					<link>http://keylimetie.com/blog/2006/6/21/aspnet2environment/</link> 
					<description><![CDATA[I've seen a lot of people have problems getting their image, css and js paths setup correctly in ASP.NET 2.0. In 2.0, every site runs on its own port just off the localhost, but the "virtual directory" name is still in the path...so you can't force everything down to the root. If you do any type of URL Rewriting or use Master Pages in pages in different level subfolders, this is going to be an issue. Prefixing paths with '' works sometime, but not for all cases.In 1.1, I would often set the webinfo file contents to point to http://localhost. Why not do the same in 2.0? To do so, open your web project Property Pages, click into the 'Start Options' area, select 'Use custom server' and enter in 'http://localhost'. This will set your environment up as if it were running on your server as a website. Only pain is changing the IIS default directory when working on another site...but that only takes a couple of seconds.]]></description> 
					<pubDate>Wed, 21 Jun 2006 11:14:44 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/6/21/aspnet2environment/</guid>
				</item>
			
				<item>
					<title>Get Current Page&amp;quot;s HTML (C#)</title> 
					<link>http://keylimetie.com/blog/2006/6/15/getcurrentpage/</link> 
					<description><![CDATA[I was working on a project where I needed to get the current page's HTML. I searched all over the Internet and could not find anything. Then I thought about the Page's built-in methods...Render! Here's how you get it:1sw = new StringWriter();
2htmltw = new HtmlTextWriter(sw);
3base.Render(htmltw);
4StringBuilder html = sw.GetStringBuilder();And be sure to drop this code in the "OnPreRenderComplete" method (you'll need to create an override in your code-behind).Well that was easy enough, huh?]]></description> 
					<pubDate>Fri, 16 Jun 2006 02:29:11 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/6/15/getcurrentpage/</guid>
				</item>
			
				<item>
					<title>Wow...now we know how to get our visitors motivated!</title> 
					<link>http://keylimetie.com/blog/2006/6/14/wow/</link> 
					<description><![CDATA[For the past 2 weeks, I have been giving out free licenses for the Google Sitemap Generator. Each day, I'd send out between 30 and 40 licenses. Yesterday, I released version 2.1 and stated "Last day to get a free license is 6/14/2006.". Well that have some effect.Today's stats:Unique visitors: 624 (normally 230-250)Free licenses: 141 (normally 30-40).And I am still allowing up to 11:59 PM CST.I guess when you set a deadline for something free, people finally get off their butts and ask. And I'm sure solme of these people told their friends.As of tomorrrow, it'll cost $49.99. So for all of you who want to thank me for the great software and free license, tell you friends about it and tell them to buy a copy. Friendly message: I track all usage of the application, so don't try to give your friends your license or you'll lose it! ]]></description> 
					<pubDate>Thu, 15 Jun 2006 05:47:04 GMT</pubDate>
					<guid isPermaLink="false">http://keylimetie.com/blog/2006/6/14/wow/</guid>
				</item>
			
	</channel>
</rss>