<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.syrinx.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Syrinx Consulting</title><link>http://blogs.syrinx.com/blogs/</link><description>Notes from the field on SharePoint development, deployment and usage.</description><dc:language>en-US</dc:language><generator>CommunityServer 2007.1 (Build: 20917.1142)</generator><item><title>Liferay, SharePoint and “open-source” mythology</title><link>http://blogs.syrinx.com/blogs/sharepoint/archive/2011/01/28/liferay-sharepoint-and-open-source-mythology.aspx</link><pubDate>Fri, 28 Jan 2011 19:18:51 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:915</guid><dc:creator>MichaelD</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;I took some time this last week to review Gartner’s Magic Quadrant for Horizontal Portals, published back in September of 2010. As one who has specialized in portal technologies over the last 10 years, I look forward to Gartner’s take on the portal market, as well as watching the trends in this space.&lt;/p&gt;  &lt;p&gt;One product I have been watching (as well as personally reviewing) is Liferay, an “open-source” portal, and definitely a welcome player in this space. Liferay, like Plumtree (now Oracle Web Center Interaction) was 10 years ago, is a smaller, innovative company, with a single focus of delivering a world-class portal product. Making Gartner happy is the fact that they are an “open-source” player. You can download their product, test it, modify it, and deploy it without bumping up to the purchased (and supported) Enterprise Edition. For companies who are adverse to risk, like all similar products, you’ll have to pay for it.&lt;/p&gt;  &lt;p&gt;So this is a SharePoint blog… Why are you talking about Liferay?&lt;/p&gt;  &lt;p&gt;Well, getting back to the Gartner report, I couldn’t help but notice their blatant obsession with “open-source” and their upfront predictions of this glorious trend. On the flip-side, they seem to cast a dark, evil cloud on other technologies, and in particular… Well, I’ll let you read for yourself, from the “Cautions” section under Microsoft SharePoint 2010:&lt;/p&gt;  &lt;p&gt;&lt;font color="#666666"&gt;“Although SharePoint 2010 is more ‘open’ than previous versions, using SharePoint as a portal framework constitutes a long-term commitment to Microsoft&amp;#39;s agenda. The openness occurs at many levels, including authentication and authorization, the Web parts model, business connectivity services, and universal browser support. Still, organizations employing SharePoint will be compelled to invest in the .NET platform and the skills needed to support it, and they will likely be locked in to Microsoft Office for the near future.”&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;i&gt;A long-term commitment to Microsoft’s agenda? Compelled to invest in the .Net platform and the skills needed to support it? Locked in to Microsoft Office?&lt;/i&gt;&amp;#160;&amp;#160; What horrors and madness could come from this!&lt;/p&gt;  &lt;p&gt;In the next few weeks, I’d like to explore the “open-source” mythology, and shed some light on why Microsoft’s “agenda” (with regards to SharePoint) excites me (and obviously a large majority of other portal users). I will also be touching on my real world experiences of .Net vs. Java, and lastly, some of the amazing benefits of being locked into Microsoft Office.&lt;/p&gt;  &lt;p&gt;Stay tuned…&lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=915" width="1" height="1"&gt;</description><category domain="http://blogs.syrinx.com/blogs/sharepoint/archive/tags/MOSS/default.aspx">MOSS</category><category domain="http://blogs.syrinx.com/blogs/sharepoint/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.syrinx.com/blogs/sharepoint/archive/tags/Liferay/default.aspx">Liferay</category><category domain="http://blogs.syrinx.com/blogs/sharepoint/archive/tags/Gartner+Resources/default.aspx">Gartner Resources</category><category domain="http://blogs.syrinx.com/blogs/sharepoint/archive/tags/open-source/default.aspx">open-source</category></item><item><title>Types of apps</title><link>http://blogs.syrinx.com/blogs/tech/archive/2010/12/21/types-of-apps.aspx</link><pubDate>Tue, 21 Dec 2010 21:50:36 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:907</guid><dc:creator>AndrewG</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;The App Store for Apple set a very good precedent for people paying at least something (often 99 cents) for mobile apps. There are a large number of apps, but if you can catapult to the “Top 100” list in iTunes, you can generate some revenue from the sale of your app. $0.99 can add up if you get 500,000 customers. On Android, I see a LOT of free apps and doubt there are as many people buying apps as on Apple’s system. On my first Droid phone, I had over 200 apps on it and I think I paid for 3 of them. A breakdown:&lt;/p&gt;  &lt;p&gt;Paid apps&amp;#160; - When you buy them on Android, you use Google Checkout and the app manifest is recorded in your Google account. If you ever replace your phone, the paid apps can be re-hydrated for free. An example one – GolfShot lets you use your Android as a GPS and scoring tool on the golf course. $30 is pricey for a mobile app and you need an extended battery to make it through a round, but this app is great. Lets you know how far to the hole, hazard, etc. Also keeps score for you and your friends and emails out a scorecard at the end. Goodbye, short pencil and paper scorecard and $300 dedicated GPS unit. A port of an app that started on the iPhone. Another example: a WiFi remote control that will work with your Tivo. Great if you misplace the Tivo remote:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.syrinx.com/blogs/tech/device3_16ED9435.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="device3" border="0" alt="device3" src="http://blogs.syrinx.com/blogs/tech/device3_thumb_1CC837CE.png" width="209" height="345" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Donation-ware: Some apps have a free version, and a second version with the exact same bits in it but you can donate money to the author by purchasing the donation version. I bought the donation-ware version of myRemote, a cool app that lets you control a PC running Windows Media Center using a WiFi connection. Time for dinner? Pause the movie the kids are watching in the other room. This is really the same as a paid app, just a different marketing angle. There are also ad-free paid apps that are just the same as the free ones but with no ads.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.syrinx.com/blogs/tech/device2_432A1B19.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="device2" border="0" alt="device2" src="http://blogs.syrinx.com/blogs/tech/device2_thumb_1AAB3905.png" width="217" height="359" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Most Android apps are free as in beer, you can download and install them free of cost. The installation of free apps are also tied to your Google ID, so your rating and comment for the app will remain and survive install/uninstall and even if you drop your phone and power up a new one. If that happens you will have to manually re-install all of your free apps, though. See below for an example of comments/rating persistence on my new phone.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.syrinx.com/blogs/tech/device1_4D6B19AC.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="device1" border="0" alt="device1" src="http://blogs.syrinx.com/blogs/tech/device1_thumb_1A9B1338.png" width="223" height="369" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;More notes on free apps:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;You can uninstall and re-install free apps any number of times. Some people seem to have uninstalled the Gong (really?) as our total installs number is much higher than active installs. &lt;/li&gt;    &lt;li&gt;Starting this month if your app is free it may never become a “paid” app in the Android Market. You would have to release a completely separate version to be paid. Note that this might kill some “freemium” models but might still support “in-game revenue” models. &lt;/li&gt;    &lt;li&gt;A subset of free apps have advertising in them as a way to produce revenue. The next article will focus on how to enroll in the different mobile application advertising networks, and implementing the code to serve up their ads. But first, a little more background info… &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Ad-supported free apps: A lot of data suggests that across mobile platforms and on Android in particular, mobile ads can pay off as well as or better than selling an app. Recently Android passed Apple in monthly ad revenue according to Millennial Media:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.droid-life.com/2010/10/19/android-eclipses-iphone-in-ad-revenue-for-first-time/"&gt;http://www.droid-life.com/2010/10/19/android-eclipses-iphone-in-ad-revenue-for-first-time/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The difference between free and even charging one cent is huge. There is a wealth of information on the web. about the disruptive force of “free”, etc. From our data, the free Gong app reached over 1,000 installs in a month. The paid-for Gong app that existed before us (at 77 cents) has between 50 and 100 downloads. So at the most he made between $38 – $77. If you could beat $77 in ad revenue, you’d be outperforming (but still not terribly lucrative). We decided to see how it worked. We installed ads at both the top and bottom of the page. So far we’re still short of hitting $25 to recoup our Android Market developer fee, but we learned a lot in the process. More in the next post on the “how”.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.syrinx.com/blogs/tech/device5_40FCF683.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="device5" border="0" alt="device5" src="http://blogs.syrinx.com/blogs/tech/device5_thumb_78CF3AA6.png" width="231" height="383" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=907" width="1" height="1"&gt;</description></item><item><title>The Android Market</title><link>http://blogs.syrinx.com/blogs/tech/archive/2010/12/06/the-android-market.aspx</link><pubDate>Mon, 06 Dec 2010 17:44:04 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:905</guid><dc:creator>AndrewG</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;We’ll back up a bit, to when I decided to try publishing to the Android Market. I had read that the Android publishing system was very open and quick with little to no oversight. This was considered a benefit for the following reasons&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;No draconian “App Store” committee to tell you whether or not you can publish your app &lt;/li&gt;    &lt;li&gt;No lag in time for App Store approval – publish when you want &lt;/li&gt;    &lt;li&gt;An open system versus a closed one &lt;/li&gt;    &lt;li&gt;Crowding – fewer apps on Android right now, so it’s easier to get noticed and used &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;(more depth on this here - &lt;a href="http://ezinearticles.com/?Android-Market-Versus-Apple-App-Store&amp;amp;id=4266917"&gt;http://ezinearticles.com/?Android-Market-Versus-Apple-App-Store&amp;amp;id=4266917&lt;/a&gt;)&lt;/p&gt;  &lt;p&gt;I went to the main Android market page and clicked the link for developers, which brings you to &lt;a href="http://market.android.com/publish/Home"&gt;http://market.android.com/publish/Home&lt;/a&gt;. You can sign up to become a developer, all I needed was a Gmail account and $25 on a credit card. I landed on the “upload your app” page, which asks you for an .apk and some supporting files. The following screen is the “update” screen and not the “initial add” screen but you get the idea.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.syrinx.com/blogs/tech/screen003_71519CEC.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="screen003" border="0" alt="screen003" src="http://blogs.syrinx.com/blogs/tech/screen003_thumb_34B99E4F.png" width="586" height="491" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This is a double edged sword that must be wielded with care. In about ten minutes I was able to sign up and upload an apk into the market. It showed up INSTANTLY in the search results in the market and could be installed by users. I had figured when I went to the movies that no one else would search for or download the Gong app. I thought I could consider the launch “semi-private beta”. I was wrong! I made the change to launch the correct class name and used the upgrade feature to launch the “1.1” version of the app. There are two changes you make to your manifest, a VersionName which is the readable name of the major.minor.patch or whatever naming convention you choose for your releases. There is also a VersionCode which must be an integer and must increment in each release. This is what signals the market to recognize an upgrade. The VersionName can’t be counted on because my 1.1 might be your 1.0.1 or 1.0.0.1 which is our second release in any case. &lt;/p&gt;  &lt;p&gt;When you log in to see how your uploaded app is doing, here is the dashboard:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.syrinx.com/blogs/tech/screen001_48D2BAD8.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="screen001" border="0" alt="screen001" src="http://blogs.syrinx.com/blogs/tech/screen001_thumb_6F349E23.png" width="563" height="538" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I signed up for a merchant account too in case I wanted to do any paid apps down the road. There’s also an offer for you to buy unlocked developer phones that can have the OS flashed if you want as well, they are around $400 – $550.&lt;/p&gt;  &lt;p&gt;When I clicked through to see the error reported, here is what I saw&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.syrinx.com/blogs/tech/screen004_6089F23E.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="screen004" border="0" alt="screen004" src="http://blogs.syrinx.com/blogs/tech/screen004_thumb_4002B28C.png" width="557" height="460" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;This is what got me to stop looking at how I packaged/loaded the apk, and start looking at the refactoring I did. Renaming my main class to Gong worked. Version 1.1 went up on Sunday morning and there have been no problems since. I uploaded a 1.2 later in the week with some snazzier graphics (icon and gong image). I have thought about some other feature ideas (a widget for direct play, ability to shake the phone to ring the gong, etc.) but haven’t implemented them. I am debating whether to work on those or try doing an iPhone gong. There are already a few in the App Store. There are some interesting articles on the viability of the App Store and Android Market, from a market share and a “how much money do developers actually make” perspective. A sampling:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://blog.flurry.com/bid/18265/Can-Developers-Still-Make-Money-in-the-iPhone-App-Store" href="http://blog.flurry.com/bid/18265/Can-Developers-Still-Make-Money-in-the-iPhone-App-Store"&gt;http://blog.flurry.com/bid/18265/Can-Developers-Still-Make-Money-in-the-iPhone-App-Store&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.wired.com/gadgetlab/2010/03/android-developer/"&gt;http://www.wired.com/gadgetlab/2010/03/android-developer/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.readwriteweb.com/mobile/2010/10/android-generates-more-ad-revenue-than-iphone.php"&gt;http://www.readwriteweb.com/mobile/2010/10/android-generates-more-ad-revenue-than-iphone.php&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=905" width="1" height="1"&gt;</description></item><item><title>Developing in Eclipse using the ADT</title><link>http://blogs.syrinx.com/blogs/tech/archive/2010/11/23/developing-in-eclipse-using-the-adt.aspx</link><pubDate>Tue, 23 Nov 2010 15:41:18 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:903</guid><dc:creator>AndrewG</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;When I first got my HTC Incredible, I went to the Android Market and downloaded apps until I killed my battery. There are a ton of free apps, and one of the most popular genres is the “soundboard”. Name any popular TV show or movie (Family Guy, The Office, Star Wars, whatever) and there is probably a soundboard of popular audio samples from it. For very popular shows/movies, there may be a soundboard per character. Here’s an example one from the popular movie “The Hangover”&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.syrinx.com/blogs/tech/Hangover_2DA24F9C.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="Hangover" border="0" alt="Hangover" src="http://blogs.syrinx.com/blogs/tech/Hangover_thumb_14E3028C.png" width="182" height="300" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;(Note also this is an example of an “advertising supported” app. More on the how, why, and economics of this in another article.) &lt;/p&gt;  &lt;p&gt;If you tap on the line (or button, or whatever) of the soundboard, an audio sample of that line will play. My idea was to basically make a single sound version, where there is one button (the gong) and a gong sound plays when you press it. There is an ImageButton class in the Android SDK that would handle showing the image. There is a SoundPool class that can hold several sound samples and play one of them. I Googled for sample code for these and there are several out there.&lt;/p&gt;  &lt;p&gt;The actual coding of the app is minimal, it just loads the sound in, sets up a handler to handle when the button is clicked, and then plays the sound when clicked. If you store the sound in a subdirectory called /res/raw in your project, a generated class R will have R.raw.soundname, where soundname is the name of the file minus its extension. You can refer to the “R Class” in your code to load one or more sounds into memory using the load() method from SoundPool. When your button is clicked, grab the stream volume from the AudioManager and pass it to the play() method on SoundPool along with the sound. The image for the button (and for the app’s icon) are handled in a similar manner. The icon is stored under /res/drawable as a .png file, and the gong image is stored under /res/raw. The latter is an attempt to avoid optimization of the .png when it’s loaded. The first version of the gong artwork was super ugly when loaded, as the palette got crushed on load from /res/drawable.&lt;/p&gt;  &lt;p&gt;There are a couple important XML files in the project. One is the Manifest, which controls where to find the icon, app name, whether it is debuggable, and the version codes. The latter matters when you go to release to the market in order to handle application updates correctly. More on that in the Android Market post. The other important XML file is the layout. It describes how the screen is laid out, how to center and size controls on it, and where to get the gong image from. Making this XML-based instead of code-based makes it easier to change layouts, control nesting, and adjust sizing. There are tools to let you graphically lay out a screen and then generate the XML layout for you. Example:&lt;a title="http://www.droiddraw.org/" href="http://www.droiddraw.org/"&gt;http://www.droiddraw.org/&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.syrinx.com/blogs/tech/DroidDraw_10004ED0.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="DroidDraw" border="0" alt="DroidDraw" src="http://blogs.syrinx.com/blogs/tech/DroidDraw_thumb_7A366672.png" width="485" height="379" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Eclipse is integrated with adb, and if you have your phone connected, it detects the phone and uses it for launches and debugging sessions. If no phone is connected, it will launch an emulator. The setup is pretty robust, but once in a while adb would no longer see my phone when it was connected by USB. Some connects/disconnects and a reboot fixed this. There were also a few gotchas to Eclipse – if you hit Control-F11 (run) while in an XML file instead of in a Java file in the project, it gave an error. Also, Eclipse can get in an error state where it cannot find other class definitions even though they are in the same project. This is called the “cannot be resolved to a type” error or “red squiggle hell”. More info on and solutions to this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://philip.yurchuk.com/2008/12/03/eclipse-cannot-be-resolved-to-a-type-error/"&gt;http://philip.yurchuk.com/2008/12/03/eclipse-cannot-be-resolved-to-a-type-error/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I was now able to compile and run on my HTC Incredible. Eclipse would compile the files, create a signed .apk file, and deploy the file to my phone and optionally attach a debugger to the process. An example:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.syrinx.com/blogs/tech/Debug_19790D46.png"&gt;&lt;img style="background-image:none;border-bottom:0px;border-left:0px;padding-left:0px;padding-right:0px;display:inline;border-top:0px;border-right:0px;padding-top:0px;" title="Debug" border="0" alt="Debug" src="http://blogs.syrinx.com/blogs/tech/Debug_thumb_7FA4D716.png" width="514" height="393" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I felt confident that this was working well, so I started refactoring and simplifying my Gong project. I renamed a few things, changed my manifest to reflect a class name of Gong, and recompiled. At the same time (can you feel a rathole mistake with red herring troubleshooting coming?) I prepared the project for export to a final .apk file for the Android Market. Eclipse wraps a multi-step process of compilation, key generation, and signing of an .apk all into a nice wizard. I stepped through the wizard and produced a “release” version of the .apk. I manually pushed this .apk onto my phone using adb install and now saw errors when I tried to open the app. It Force Closed immediately upon opening. I thought maybe I was doing something wrong installing directly and maybe the “release” .apk file needed to install through the market to work correctly. &lt;/p&gt;  &lt;p&gt;I instrumented every other line of my code with logging. Even the first logging statement failed to fire, so it looked like my code wasn’t even being hit. I’ll skip ahead a bit – I signed up for the Google Android Market, uploaded my release APK, and tried downloading/installing it through the market. I still had the same force close problem. I had run out of time to work on this for the day (it was Saturday, date night with my wife, and time to go see “Due Date”). So I left for the evening.&lt;/p&gt;  &lt;p&gt;When I came home around 11, I happened to refresh the Android Market page. 56 people had downloaded the broken Gong app while I was out! They had complained about the force closes, some had rated it “one star” and one had submitted a crash report. Through looking at the exception info, I could see that when I told the manifest to launch the “Gong” class, it could not find the class com.syrinx.gong.Gong. I needed to rename my main class to “Gong”. Once I did this, my apk’s were working again. I found it odd that the compiler would let me create an .apk that you could not actually “run”, and the Android Market did not detect this either. More detail on the market in my next post..&lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=903" width="1" height="1"&gt;</description></item><item><title>Where to begin?</title><link>http://blogs.syrinx.com/blogs/tech/archive/2010/11/16/where-to-begin.aspx</link><pubDate>Tue, 16 Nov 2010 21:54:48 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:902</guid><dc:creator>AndrewG</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;When I started thinking of the Gong project, I considered “How should I build it?”. I had heard some good things about Appcelerator’s Titanium. Their product lets you code mobile apps in JavaScript, and compiles it down to native code for either the iPhone or Android. This appealed to me for the portability factor and for speed. Side benefits – they have Paypal integration, are in Beta for Blackberry support, and Titanium is open source. I’m not a JavaScript whiz these days, but I figured I would give it a try. I proceeded here and followed the instructions:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.appcelerator.com/products/download/"&gt;http://www.appcelerator.com/products/download/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;The getting started guide available from that page was &lt;strong&gt;great&lt;/strong&gt;, walking me through all the prerequisite steps for developing with Titanium on Windows. It told me where to get the latest JDK, where to install it, avoid space characters in my path to it, etc. It told me how to set my environment variables for everything as well. Very nice screenshots and sanity check steps (“run javac –version from the command line, if you did things right you’ll see this&amp;quot;). The same goes for the Android SDK setup and installs. Blow by blow directions with numerous screen shots.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;TIP:&lt;/strong&gt; The guide did not directly tell me to install Eclipse or which version – you will want 3.5 (Galileo) not 3.6 (Helios). They cite better compatibility between Titanium and 3.5. I put eclipse.exe in my PATH too so I could run it from Start-&amp;gt;Run or the command line.&lt;/p&gt;  &lt;p&gt;Buzzkill: You can only build/deploy iPhone apps using Titanium from a Mac, so you’d need a Mac to “cross compile” for both Android and iPhone. I don’t have a Mac readily available.&lt;/p&gt;  &lt;p&gt;I installed Titanium and created an account for it. By default you have a “free” account. There are in-product promotions for you to upgrade to “Pro” to get better tutorial videos, etc. I figured I would tough it out for now.&lt;/p&gt;  &lt;p&gt;I had trouble getting even “Hello World” to run at first. I did some Googling and found some KB articles about the /build directory not being created on new projects. I copied over the /build directory from the sample “Kitchen Sink” project provided by Appcelerator. I now got “Hello world” to run. When you compile an app and tell it to “run”, by default you will launch a “virtual device” using the Android SDK. This emulator is a virtual machine that runs the Android OS. You can pick from which versions of the OS you want to run on the VM, to whether or not it has an SD card in it, etc. The one thing I can tell you about the emulator is it is PAINFULLY slow. I am on a halfway decent desktop machine. It’s not a developer’s dream box but it is dual core 3+ GHZ with 3GB of memory. It took so long to launch the first few times that I killed it assuming it was hung up. When I finally let it run for five minutes I came back to my desk and it was up. The following process can take 2 – 5 minutes to complete:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.syrinx.com/blogs/tech/Phase1_78FC942D.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="Phase1" border="0" alt="Phase1" src="http://blogs.syrinx.com/blogs/tech/Phase1_thumb_183F3B01.png" width="523" height="309" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.syrinx.com/blogs/tech/Phase2_6C8E7104.png"&gt;&lt;img style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" title="Phase2" border="0" alt="Phase2" src="http://blogs.syrinx.com/blogs/tech/Phase2_thumb_0B64E4E3.png" width="521" height="282" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Note the red boxes, on the top one you may get complaints about waiting for tasks, just say “Wait”. If your app does not come up, click the arrow at the bottom to bring up a list of apps an launch your app. &lt;/p&gt;  &lt;p&gt;I next tried plugging my HTC Incredible phone in to my development machine using the micro USB to USB cable I had to charge it. I enabled the debugging ability:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://developer.android.com/guide/developing/device.html"&gt;http://developer.android.com/guide/developing/device.html&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I told the phone to launch HTC Sync, then killed it. Now I could build and deploy to my phone. This reduced the compile/sign/deploy cycle to under 30 seconds. If you estimate costs at $100/hour for development time and you saved about 4 minutes each compile cycle, it quickly becomes worth it to buy an Android phone off Craigslist, a refurb from your carrier, or a dev phone from Google. By my math, with 16 compile cycles per day it would be about 5 days. It’s probably more than 4 minutes each time when you figure a developer faced with 4 minutes of wait time may wander off, do other tasks, and then have to get “back into the mode” to developing that app again.&lt;/p&gt;  &lt;p&gt;The JavaScript code looks like this (abbreviated – you also create a tab group, window, etc)&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;var label1 = Titanium.UI.createLabel({      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; color:&amp;#39;#999&amp;#39;,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; text:&amp;#39;Hello, Andrew!&amp;#39;,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; font:{fontSize:20,fontFamily:&amp;#39;Helvetica Neue&amp;#39;},       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; textAlign:&amp;#39;center&amp;#39;,       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; width:&amp;#39;auto&amp;#39;       &lt;br /&gt;});&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;win1.add(label1);&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;If you’re a JavaScript whiz and can get used to the syntax you could be super-productive. The Gong app can probably be done in 3-4 statements, create a window, create a ImageButton, play a sound when pressed. But when I tried to adapt the sample code from Kitchen Sink, I found the learning curve hard and Googling for help limited. I was tempted to start with Kitchen Sink and then start stripping out all code except the sound playing part, but it was tedious to strip it, compile, hope to not break anything, and in a scripted environment, debug if I did break something. I feel if I invested some more time I could do it, but my attention span for this project and affinity for Java over JavaScript pointed me towards a compiled app. Fortunately, pretty much everything was set up already. More to come…&lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=902" width="1" height="1"&gt;</description></item><item><title>From Zero to Published Android Application in 8 Hours: So Easy A CEO Could Do It</title><link>http://blogs.syrinx.com/blogs/tech/archive/2010/11/08/from-zero-to-published-android-application-in-8-hours-so-easy-a-ceo-could-do-it.aspx</link><pubDate>Mon, 08 Nov 2010 18:18:00 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:901</guid><dc:creator>AndrewG</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;I have been curious about development for the Android mobile phone platform since I bought my HTC Incredible back in May. I knew that the Verizon phone ran Java, especially from the occasional misbehaved app that would blow up with a message like “com.somecompany.AppName has stopped unexpectedly” or a “null pointer exception”. That brought me back to the old days in 1999, doing Java 1.1 development. I let the vague feeling of “I should build something, just to try it out” stew for a few months.&lt;/p&gt;
&lt;p&gt;Last Thursday I was laughing at one of those office inside jokes. Luke from our sales team has a catch phrase to describe an organization that is in disarray, often saying “That place is a GONG SHOW!” I found a sound effect on the web for a gong and decided to see what it would take to make “an app for that”. I had read that it was relatively easy to build and publish an Android app, so why not give it a try?&lt;/p&gt;
&lt;p&gt;The application is simple, when you open it you are presented with an image of a gong that acts like a button. When you tap the image, a gong sound is played. It is brisk and amusing, even my two year old can operate it, and it only took a couple hours to develop. The rest of the time was setup, prototyping, learning, debugging, and packaging. I’ll be doing a series of articles to describe the process. I’ll cover the setup steps, coding, development environment, packaging, and the Android Market “behind the scenes”. I’ll also throw in some commentary about mobile app dev, the Android platform, iPhone, etc. &lt;/p&gt;
&lt;p&gt;The Gong app icon, the app running, and in the app in the Android Market&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.syrinx.com/blogs/tech/splash_606F7BEA.png"&gt;&lt;img style="BACKGROUND-IMAGE:none;BORDER-BOTTOM:0px;BORDER-LEFT:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;BORDER-TOP:0px;BORDER-RIGHT:0px;PADDING-TOP:0px;" title="splash" border="0" alt="splash" src="http://blogs.syrinx.com/blogs/tech/splash_thumb_058CC657.png" width="545" height="304" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The app in action:&lt;/p&gt;
&lt;div style="PADDING-BOTTOM:0px;MARGIN:0px;PADDING-LEFT:0px;PADDING-RIGHT:0px;DISPLAY:inline;FLOAT:none;PADDING-TOP:0px;" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:2c1a78a9-cf8f-41a8-b078-4afee7cafdbd" class="wlWriterEditableSmartContent"&gt;
&lt;div&gt;
&lt;object width="448" height="252"&gt;&lt;param name="movie" value="http://www.youtube.com/v/iu4DbmUc5G8?hl=en&amp;amp;hd=1"&gt;
&lt;embed src="http://www.youtube.com/v/iu4DbmUc5G8?hl=en&amp;amp;hd=1" type="application/x-shockwave-flash" width="448" height="252"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;
&lt;div style="WIDTH:448px;CLEAR:both;FONT-SIZE:0.8em;"&gt;Gong app demo from YouTube&lt;/div&gt;&lt;/div&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=901" width="1" height="1"&gt;</description><category domain="http://blogs.syrinx.com/blogs/tech/archive/tags/gong/default.aspx">gong</category><category domain="http://blogs.syrinx.com/blogs/tech/archive/tags/android/default.aspx">android</category></item><item><title>Tech Blog</title><link>http://blogs.syrinx.com/blogs/tech/archive/2010/06/04/tech-blog.aspx</link><pubDate>Fri, 04 Jun 2010 16:19:00 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:895</guid><dc:creator>AndrewG</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;This is our new blog at Syrinx for the tech industry - gadgets, trends, business items, things that don&amp;#39;t fall under our other blog umbrellas. Enjoy! -Andrew&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=895" width="1" height="1"&gt;</description></item><item><title>Working with Oracle Virtual Directory using LDAP and Microsoft's System.DirectoryServices.Protocols library</title><link>http://blogs.syrinx.com/blogs/dotnet/archive/2010/03/22/working-with-oracle-virtual-directory-using-ldap-and-microsoft-s-system-directoryservices-protocols-library.aspx</link><pubDate>Mon, 22 Mar 2010 18:40:00 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:223</guid><dc:creator>joep</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;I recently had the opportunity to help a client save a considerable amount of time by replacing a time consuming, mostly manual process with a fully automated service.&amp;nbsp; The client has many locations throughout the country and employees a great number of people.&amp;nbsp; As is similar with other businesses of their kind, there are&amp;nbsp;many employees&amp;nbsp;being hired and terminated&amp;nbsp;on a daily basis.&amp;nbsp; The payroll system is the first official record updated whenever employees are gained or lost, but changes also have to be made so that the users are granted or denied access to the various applications within the enterprise.&amp;nbsp; Access to most systems are controlled by Oracle Virtual Directory, which is the &amp;quot;system of record&amp;quot; used by their web portals and other internal applications.&amp;nbsp; The process they were using involved exporting a fixed-width file from the payroll system, converting it to an LDIF formatted file, exporting the entire OVD to LDIF, then manually comparing the files in Excel to determine adds and deletes.&amp;nbsp; The adds and deletes were split into two LDIF files and imported back into OVD for processing.&amp;nbsp; The process was happening about every other week and took upwards of 6 hours to complete.&amp;nbsp;&amp;nbsp;My assignment was to make the process &amp;quot;hands-off&amp;quot; so it could be run more frequently and not consume valuable time.&lt;/p&gt;
&lt;p&gt;The solution I designed was a .Net 3.5SP1 application that could be run as a Windows Service or a scheduled Console application.&amp;nbsp; The initial version would read from the fixed-width payroll file and directly update OVD, but it was designed in a way to allow for other &amp;quot;adapters&amp;quot; to be written should either the payroll or directory service change.&amp;nbsp; In addition, the vast majority of the logic is embedded in a class library, leaving only console or Windows Service specific logic in the actual executing assembly.&amp;nbsp; This would allow for other versions (web, Windows Forms, etc.) to be written with very little effort.&amp;nbsp; Finally, a great many options were designed to be configurable via the app.config file, allowing for minor changes to functionality without requiring code updates.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;The main flow of the application&amp;nbsp;is pretty straightforward.&amp;nbsp; First, instantiate the appropriate &amp;quot;source&amp;quot; reader (source being the system that the target should be updated to reflect).&amp;nbsp; This is done reflectively based on a configuration setting that specifies the type to be created (all readers extend a common abstract class).&amp;nbsp; Next, instantiate the appropriate &amp;quot;target&amp;quot; reader using the same process (the target being the system to be updated).&amp;nbsp; A &amp;quot;writer&amp;quot; is then instantiated using the same process.&amp;nbsp; The writer is what is used to actually write the records to the target system.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Each reader has a GetPersonnelRecords method that returns a PersonnelRecordsCollection class to represent the directory entries in a generic fashion.&amp;nbsp; Both the source and target are loaded using this method.&amp;nbsp; Next, find all of the &amp;quot;adds&amp;quot;, defined as records that exist in the source but not in the target.&amp;nbsp; For each add, the Add method is executed on the writer.&amp;nbsp; Deletes are next, defined as all records that exist in the target but not in the source.&amp;nbsp; Each delete is processed by executing the Delete method on the writer.&amp;nbsp; Events are fired throughout the processing to provide insight into the calling application for logging purposes.&lt;/p&gt;
&lt;p&gt;So that is the generic explanation, as it applies to any implementation configured.&amp;nbsp; The potentially tricky parts involve actually connecting to&amp;nbsp;and interacting with the OVD.&amp;nbsp; In this case, OVD&amp;nbsp;is used in&amp;nbsp;both the target reader and the writer.&amp;nbsp; In both cases a few Oracle-specific challenges were encountered, but nothing that couldn&amp;#39;t be solved!&lt;/p&gt;
&lt;p&gt;For the &amp;quot;reader&amp;quot; portion, we need to retrieve all users within OVD.&amp;nbsp; Here is the code used to do this:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal SearchResultEntryCollection GetAllUsers()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LdapConnection connection = LdapHelper.GetLdapConnection(_ldapUri, _ldapUserName, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _ldapPassword, _requestTimeoutMinutes);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SearchRequest searchRequest = new SearchRequest(_ldapBase, _searchAllFormat,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.DirectoryServices.Protocols.SearchScope.Subtree, _ldapAttributeDNs);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SearchResponse searchResponse = (SearchResponse)connection.SendRequest(searchRequest);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return searchResponse.Entries;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;The connection is provided by a helper class.&amp;nbsp; Here is the code for GetLdapConnection:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal static LdapConnection GetLdapConnection(string ldapUri, string ldapUserName, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string ldapPassword, int requestTimeoutMinutes)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LdapDirectoryIdentifier ldapId = new LdapDirectoryIdentifier(ldapUri);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; NetworkCredential credentials = new NetworkCredential(ldapUserName, ldapPassword);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LdapConnection connection = new LdapConnection(ldapId, credentials);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; connection.AuthType = AuthType.Basic;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // We need to ignore certificate errors because the certificate on the OID server &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp; is self-signed&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; connection.SessionOptions.VerifyServerCertificate =&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; delegate(LdapConnection l, X509Certificate c) { return true; };&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; connection.SessionOptions.SecureSocketLayer = true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; connection.SessionOptions.SendTimeout = new TimeSpan(0, requestTimeoutMinutes, 0);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; connection.Bind();&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return connection;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Note that you need to add a reference to System.DirectoryServices.Protocols, System.Net,&amp;nbsp;and System.Security.Cryptography.X509Certificates for this code to execute.&lt;/p&gt;
&lt;p&gt;Lets break the code down...&lt;/p&gt;
&lt;p&gt;First, we need to get a connection.&amp;nbsp; This is accomplished using an LdapDirectoryIdentifier, passing in the Ldap server url like this: &amp;quot;example-ldap-01:456&amp;quot;.&amp;nbsp; Note that the port should be specified if using this method.&amp;nbsp; The port used will depend on the authentication method and security protocol used.&amp;nbsp; In our case, we were using Basic Authentication with SSL.&amp;nbsp; The OVD had a setting for the actual port used for LDAPS, which is what I entered above.&amp;nbsp; Next, we need to create a NetworkCredential to be used.&amp;nbsp; It was important in this case to use an admin account as non-admin accounts had search limits imposed (only x number of records would be returned).&amp;nbsp; Also important is to know that the format for username was &amp;quot;cn=admin&amp;quot;, not &amp;quot;admin&amp;quot;.&amp;nbsp; Using the identifier and credentials we can now create an LdapConnection.&amp;nbsp; Next we set the Auth Type to Basic in this case.&amp;nbsp; Since the client was using a self-signed cert, I needed to instruct the library to ignore certificate errors, or else we would get a &amp;quot;server unavailable&amp;quot; error message when trying to connect.&amp;nbsp; I did this by simply returning True&amp;nbsp;in a&amp;nbsp;ValidateServerCertificate delegate.&amp;nbsp; We set a few Session Options such as SecureSocketLayer and SendTime, then we use Bind to test and establish the connection.&lt;/p&gt;
&lt;p&gt;There was a lot of trial and error involved in getting the username and security settings right.&amp;nbsp; One very helpful tool to do this was LDAP Admin, located at &lt;a href="http://ldapadmin.sourceforge.net/"&gt;http://ldapadmin.sourceforge.net/&lt;/a&gt;.&amp;nbsp; By finding parameters that worked within LDAP Admin and finding out how to configure those same parameters in my code I was able to successfully connect to OVD.&lt;/p&gt;
&lt;p&gt;Once the connection was established, I needed to actually perform the search.&amp;nbsp; First I created a SearchRequest object.&amp;nbsp; The object was initialized with several parameters.&amp;nbsp; The first parameter specifies the base of the search, such as &amp;quot;ou=OIDUsers,dc=example,dc=ovd&amp;quot;.&amp;nbsp; You can also find this using LDAP Admin.&amp;nbsp; The second parameter was the search filter to use.&amp;nbsp; I originally used &amp;quot;objectClass=person&amp;quot;, but found that I was getting many records (150 - 200 out of 6000) that were missing all attributes.&amp;nbsp; The weird part about it was that both the count and specifics of the missing attributes were different every time.&amp;nbsp; Only when I ran with &amp;quot;objectClass=*&amp;quot; was I able to get all attributes for all records (it actually ran faster, too).&amp;nbsp; Next I specified a SearchScope of Subtree (I wanted to see everything), and I passed a delimited list of the attributes I wanted to return as the final argument.&amp;nbsp; With these settings I was able to successfully retrieve all users and their attributes.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;The Ldap Writer was actually much easier once the connectivity issues were addressed.&amp;nbsp; I used the same helper class to establish a connection.&amp;nbsp; I then used DeleteRequest for performing deletes, and AddRequest for performing adds.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private void DeleteUser(string userId)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string dn = _deleteFormat.Replace(&amp;quot;{UserId}&amp;quot;, userId);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DeleteRequest deleteRequest = new DeleteRequest(dn);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DeleteResponse deleteResponse = &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (DeleteResponse)connection.SendRequest(deleteRequest);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (deleteResponse.ResultCode != ResultCode.Success)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; OnProcessException(&amp;quot;Error deleting user &amp;quot; + userId + &amp;quot;: &amp;quot; + &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; deleteResponse.ResultCode.ToString());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private void AddUser(PersonnelRecord user)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string dn = LdapHelper.SubstituteAttributeValue(user, _addFormat);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; List&amp;lt;DirectoryAttribute&amp;gt; attributes = new List&amp;lt;DirectoryAttribute&amp;gt;();&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Add all attributes&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (LdapAttribute ldapAttribute in _ldapAttributes)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; attributes.Add(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; new DirectoryAttribute(ldapAttribute.Name, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LdapHelper.SubstituteAttributeValue(user, ldapAttribute.Value)));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AddRequest addRequest = new AddRequest(dn, attributes.ToArray());&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AddResponse addResponse =&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (AddResponse)connection.SendRequest(addRequest);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (addResponse.ResultCode != ResultCode.Success)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; OnProcessException(&amp;quot;Error adding user &amp;quot; + user.UserId + &amp;quot;: &amp;quot; +&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; addResponse.ResultCode.ToString());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;The DeleteFormat&amp;nbsp;was set in the configuration file as &amp;quot;cn={UserId},ou=OIDUsers,dc=example,dc=ovd&amp;quot;.&amp;nbsp; I simply replaced the UserId with the appropriate UserId for the record being deleted.&amp;nbsp; NOTE: a delete will return a Success result code even if there is no record to delete!&lt;/p&gt;
&lt;p&gt;For the adds, the AddFormat was also set in the configuration file and had the same value.&amp;nbsp; In addition, I created a collection of name-value pairs to hold any other attributes to be added to the new user.&amp;nbsp; As with the UserId, I replaced placeholder values with actual values from the user being added.&lt;/p&gt;
&lt;p&gt;That was it!&amp;nbsp; The process went from over a half a day manual effort to 30 seconds, fully automated.&amp;nbsp; With a little extra effort it would be easy enough to plug directly into the Payroll system and avoid current step of creating the payroll file.&amp;nbsp; As designed, the code would only require a new Reader adapter.&lt;/p&gt;
&lt;p&gt;In summary: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div&gt;Use System.DirectoryServices.Protocols.&amp;nbsp; &lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Use &amp;quot;LDAP Admin&amp;quot; to test your connectivity first, then match the settings in your code.&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;Use an Admin account, in the format &amp;quot;cn=admin&amp;quot;, to avoid issues with throttling or access.&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Have fun!&lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=223" width="1" height="1"&gt;</description></item><item><title>Overview of the ADO.Net Entity Framework</title><link>http://blogs.syrinx.com/blogs/dotnet/archive/2010/02/25/overview-of-the-ado-net-entity-framework.aspx</link><pubDate>Thu, 25 Feb 2010 21:12:00 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:220</guid><dc:creator>joep</dc:creator><slash:comments>1</slash:comments><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;ADO.Net Entity Framework&lt;/p&gt;
&lt;h1&gt;What is it?&lt;/h1&gt;
&lt;h2&gt;Microsoft definition:&lt;/h2&gt;
&lt;p&gt;The ADO.NET Entity Framework is designed to enable developers to create data access applications by programming against a conceptual application model instead of programming directly against a relational storage schema. The goal is to decrease the amount of code and maintenance required for data-oriented applications. Entity Framework applications provide the following benefits: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Applications can work in terms of a more application-centric conceptual model, including types with inheritance, complex members, and relationships.&lt;/li&gt;
&lt;li&gt;Applications are freed from hard-coded dependencies on a particular data engine or storage schema.&lt;/li&gt;
&lt;li&gt;Mappings between the conceptual model and the storage-specific schema can change without changing the application code.&lt;/li&gt;
&lt;li&gt;Developers can work with a consistent application object model that can be mapped to various storage schemas, possibly implemented in different database management systems.&lt;/li&gt;
&lt;li&gt;Multiple conceptual models can be mapped to a single storage schema.&lt;/li&gt;
&lt;li&gt;Language-integrated query (LINQ) support provides compile-time syntax validation for queries against a conceptual model. &lt;/li&gt;&lt;/ul&gt;
&lt;h2&gt;So what does that mean?&lt;/h2&gt;
&lt;p&gt;A way to reference data as &amp;quot;plain old clr objects&amp;quot; (POCO), without regard to how the data is actual retrieved or persisted (unless you want to know).&amp;nbsp; You can query, create, update, and delete using .Net objects and either extension methods or Linq to Entities.&lt;/p&gt;
&lt;h2&gt;History&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Data Readers&lt;/em&gt; - serial data access, no type safety, manual loading into objects.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;DataSets&lt;/em&gt; - disconnected access, sorting, filtering, no type safety, manual loading or databinding.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Typed DataSets&lt;/em&gt; - disconnected, strongly typed, still datasets (&amp;quot;heavy&amp;quot;, lots of dataset methods, easily abused)&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Linq To Sql&lt;/em&gt; - connected, first attempt at using CLR code to access data.&amp;nbsp; Still one-to-one to database entities.&amp;nbsp; Lazy loading both good and bad.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Entity Framework&lt;/em&gt; - connected or disconnected, doesn&amp;#39;t need to map directly to data model, lazy or eager loading, &amp;quot;mostly&amp;quot; POCO.&amp;nbsp; &lt;/p&gt;
&lt;h2&gt;So why would I want to use this?&lt;/h2&gt;
&lt;p&gt;Less code.&amp;nbsp; More time to focus on what matters, not data access logic.&amp;nbsp; Bindable, can be used directly to databind in Asp.Net or WPF.&amp;nbsp; Partial classes, allowing easy extension.&lt;/p&gt;
&lt;h2&gt;Examples&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Acme Construction Consulting.&amp;nbsp; An application written in WPF using Sql Express 2008 for data storage and Entity Framework for data access.&amp;nbsp; Middle tier components accept scalar parameters and return Entity Framework objects to the front end.&amp;nbsp; DataContext is set in WPF UI directly to Entity Framework objects.&amp;nbsp; State management plays nicely with databinding, allowing changes to be tracked for persistence at a time of the developer&amp;#39;s choosing.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Very connected model.&amp;nbsp; Entire object graph can be retrieved with a single statement and bound to the page and elements on the page.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Property Changed events allow &amp;quot;turbo-tax&amp;quot; style updates whenever appropriate data elements are changed.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Large amount of data, can be slow to retrieve, but ok due to the nature of the application.&lt;/p&gt;
&lt;p&gt;Partial classes extended to allow custom formulas to be exposed as properties.&lt;/p&gt;
&lt;p&gt;public partial class SoftCost&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #region Calculated properties.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public double? LumpSum&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (Scenario.TotalConstructionCost == null ||&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PercentofProject == null)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return null;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Scenario.TotalConstructionCostWithoutEscalation.Value * &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PercentofProject.Value;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; #endregion&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;Different types of ways to get at the data (extension methods, linq)&lt;/p&gt;
&lt;p&gt;public IQueryable&amp;lt;DataObjects.RenovationType&amp;gt; GetRenovationTypes()&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; from renovationType in db.RenovationType&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; select renovationType;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;public DataObjects.RenovationType GetRenovationType(int id)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return db.RenovationType.First(r =&amp;gt; r.Id == id);&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;More complex queries possible&lt;/p&gt;
&lt;p&gt;public IQueryable&amp;lt;DataObjects.DepartmentGroupType&amp;gt; GetDepartmentGroupTypes(int sectorId)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; from departmentGroupType in db.DepartmentGroupType&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Include(&amp;quot;DepartmentType&amp;quot;)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; where departmentGroupType.Sector.Id == sectorId&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; || departmentGroupType.Sector.Id == 0 // Include &amp;quot;All&amp;quot; sectors&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; orderby departmentGroupType.Description&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; select departmentGroupType;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;h4&gt;Lessons learned&lt;/h4&gt;
&lt;p&gt;Performance.&amp;nbsp; If you have an object that has nested related objects, you have a few choices as to how to retrieve that related information.&amp;nbsp; You can use the Include method to load all of the data on the database server, returning the full object graph.&amp;nbsp; Or, you can use the Load method to load individual objects after retrieving the initial object.&amp;nbsp; The problem with Include is that it creates a large UNION statement in the database to return one row for each of the lowest-level objects included.&amp;nbsp; This can be VERY slow if there are many child objects or data.&amp;nbsp; Include is certainly an easier approach to use if performance not an issue, but using the &amp;quot;Gatlin Gun&amp;quot; approach (use load many times instead of Include) is much faster.&lt;/p&gt;
&lt;p&gt;Object context.&amp;nbsp; The object context is not always disconnected, even if Context is gone (for example, by using a Using statement).&amp;nbsp; The state tracker (ObjectStateManager) is still there and will complain if you try to &amp;quot;mix and match&amp;quot; objects that were retrieved from different contexts.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Value Added Website.&amp;nbsp; An Asp.Net application using Entity Framework for database access.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Different model than WPF application.&amp;nbsp; Everything is stateless.&amp;nbsp; Each page request is new connection to database, all entities are disconnected.&amp;nbsp; Change Tracking works differently.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;You can use ObjectDataSource with methods that accept or return Entity Framework objects, which can speed up your development time.&lt;/p&gt;
&lt;p&gt;If you want to compile objects into one object graph that come from different business objects, you must be using the same context or you will get an exception.&lt;/p&gt;
&lt;p&gt;&amp;quot;Unit of Work Scope&amp;quot; makes it easy to ensure that you are getting one instance.&lt;/p&gt;
&lt;p&gt;protected DataObjects.Entities db&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; get&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (UnitOfWorkScope.CurrentObjectContext != null)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return UnitOfWorkScope.CurrentObjectContext;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (_db == null)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _db = new DataObjects.Entities();&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return _db;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;To use:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; using (new Service.UnitOfWorkScope(true))&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Criticisms&lt;/h2&gt;
&lt;p&gt;Performance.&amp;nbsp; Can be slower than raw data access code, unless you put in the extra time to optimize.&amp;nbsp; However, you can use stored procedures, can decide how things are loaded, can view actual queries to be run, can compile linq expression.&lt;/p&gt;
&lt;p&gt;Not really POCO.&amp;nbsp; Still has a lot of extra methods.&amp;nbsp; Still has connected capabilities, even when you don&amp;#39;t want them.&lt;/p&gt;
&lt;p&gt;Context can be a pain, as can state management.&amp;nbsp; Mixing and matching, updating some entities while adding others and doing nothing to still others can be very complicated.&amp;nbsp; (MSDN August 2009 has a lot of good information on this).&lt;/p&gt;
&lt;p&gt;No easy way to reattach complex object graphs, though there are patterns for doing it for the more simple entities.&lt;/p&gt;
&lt;p&gt;Designer is sometimes &amp;quot;too&amp;quot; careful.&amp;nbsp; Removing entities from the EDM designer doesn&amp;#39;t always get rid of all parts.&amp;nbsp; Sometimes you need to go into the Xml and manually get rid of elements.&amp;nbsp; Can be easier to remove all and regenerate in many cases.&amp;nbsp; &lt;/p&gt;
&lt;h2&gt;Future&lt;/h2&gt;
&lt;p&gt;POCO.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Improved n-tier support.&amp;nbsp; Attach and change states.&lt;/p&gt;
&lt;p&gt;T4 based code.&amp;nbsp; Use build in templates for common patterns or create your own.&lt;/p&gt;
&lt;p&gt;Foreign Key properties.&amp;nbsp; Right now, can&amp;#39;t set the foreign key (Id), can only set the actual object.&amp;nbsp; This also helps with n-tier and &amp;quot;mix and match&amp;quot; issues.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=220" width="1" height="1"&gt;</description></item><item><title>Twitter question</title><link>http://blogs.syrinx.com/blogs/sharepoint/archive/2010/02/16/twitter-question.aspx</link><pubDate>Tue, 16 Feb 2010 19:24:00 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:219</guid><dc:creator>AndrewG</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;A recent question on Twitter:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;quot;[SharePoint] costs as much to buy/implement/run in&amp;nbsp;money as the productivity loss of not having it - agree or disagree?&amp;quot;&lt;/p&gt;
&lt;p&gt;I would say if you measure this in a vacuum, in the scope of one single project it&amp;#39;s probably a wash (money out == savings). The real ROI starts showing up on projects 2 - 200 where you already have the infrastructure set up, people know how to use the platform, you&amp;#39;ve paid for the licensing, and now you are able to solve new challenges using SharePoint with little effort and cost. Your users start solving business needs themselves (or with just a little help) using doucment libraries, lists, etc. I think that is where the real &amp;#39;wins&amp;#39; happen. &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=219" width="1" height="1"&gt;</description><category domain="http://blogs.syrinx.com/blogs/sharepoint/archive/tags/MOSS/default.aspx">MOSS</category><category domain="http://blogs.syrinx.com/blogs/sharepoint/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.syrinx.com/blogs/sharepoint/archive/tags/WSS/default.aspx">WSS</category></item><item><title>SharePoint Server 2010 Initial Installation</title><link>http://blogs.syrinx.com/blogs/sharepoint/archive/2009/11/17/sharepoint-server-2010-initial-installation.aspx</link><pubDate>Wed, 18 Nov 2009 00:45:39 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:215</guid><dc:creator>RyanT</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;I just wanted to drop a quick note about the installation of the SharePoint Server 2010 Beta released yesterday on MSDN.&lt;/p&gt; &lt;p&gt;I setup a new virtual machine in my Hyper-V server as a new dedicated 2010 Beta server.&amp;nbsp; I installed Office 2010 beta and SharePoint Designer 2010 with no issues whatsoever.&amp;nbsp; SharePoint Server provided to be a little less helpful.&amp;nbsp; It wouldn&amp;#39;t be SharePoint if it didn&amp;#39;t make me work for it!&lt;/p&gt; &lt;p&gt;I want to drop a quick warning in case you run into the 2 issues I had.&lt;/p&gt; &lt;p&gt;1.&amp;nbsp; The prerequisite installs kept failing because it was unable to install PowerShell V2.&amp;nbsp; This boils down to PowerShell V2 refusing to install if V1 exists (although this took a little digging below the surface), which is mysteriously installed on my vanilla Server 2008 Standard via a random KB / Windows Update.&amp;nbsp; Fine, except you can&amp;#39;t find the specific KB to therefore uninstall it.&amp;nbsp; It turns out to be a piece of cake after running in circles.&amp;nbsp; Use the server manager &amp;quot;Features&amp;quot; to remove PowerShell V1 and voila, you should be all set.&amp;nbsp; The traditional methods for remove programs yielded no results.&lt;/p&gt; &lt;p&gt;2.&amp;nbsp; The SharePoint Configuration Wizard told me that my SQL Server was not up to date.&amp;nbsp; The warning made it sound like I needed SP1 for SQL 2008, which I had not installed.&amp;nbsp; I went ahead and got that completed and the error/warning persisted.&amp;nbsp; If you read carefully the message also mentions a specific KB which has a ton of hotfixes embedded within them.&amp;nbsp; I just downloaded both files referenced in the hotfixes from that KB and installed them.&lt;/p&gt; &lt;p&gt;In all I installed SP1 three times with the various KB bundles, but after that the installation went smooth.&amp;nbsp; My machine is now sitting at the Central Admin configuration screen while Visual Studio 2010 beta installs.&lt;/p&gt; &lt;p&gt;I will try to report back on any hiccups / issues with the CA configuration.&amp;nbsp; So far it&amp;#39;s not too bad!&lt;/p&gt; &lt;p&gt;I hope this helps,&lt;/p&gt; &lt;p&gt;-Ryan&lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=215" width="1" height="1"&gt;</description></item><item><title>SPC 2009 Wrap-up</title><link>http://blogs.syrinx.com/blogs/sharepoint/archive/2009/10/29/spc-2009-wrap-up.aspx</link><pubDate>Fri, 30 Oct 2009 03:12:12 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:214</guid><dc:creator>AndrewG</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;The last day of the SPC had some tech-laden sessions hosted by Andrew Connell. The first was about migrating from 2007 to 2010, and how you can add the nice 2010 development features (like the ribbon and the developer dashboard) back into your 2007 master pages when you migrate them. The theme seems to be that you invested in branding and customizing 2007, and Microsoft is making it straightforward to move that content to 2010. The idea is to not have to stop doing work in your 2007 instance waiting for 2010 to release. All in all, it looks like going from 2007 to 2010 should be much easier than 2003 to 2007.  &lt;p&gt;Andrew’s second session was on the ability to create Service Applications. When I first heard it described (local versus proxy execution, service discovery, etc) I started having flashbacks to an app we built back in 1998 in C++ – the Bridge Pattern and CORBA live again! The more I heard the more I was impressed with what had been implemented. It is CORBA-like, but seems to be much easier to use/administer and much faster. Still some hand-rolling of code to bind things together, but all in all some powerful capability if you need it. Who might need it? I can see an ISV who wants to embed some of their product’s capabilities into SharePoint where there are long-running operations or a need for horizontal scalability of compute-intensive operations. There is a decent amount of development overhead to do so, but it’s nice to know the capability is there if needed. One Best Practice mentioned – if you do decide to create a Service Application, make sure to create the Central Admin and PowerShell interfaces to make administration straightforward.  &lt;p&gt;The conference was a great time and was very informative. A few themes &lt;ul&gt; &lt;li&gt;I noticed a lot of people from other countries at the conference – SharePoint is definitely catching on worldwide and is standing up to the multi-lingual challenge.&lt;/li&gt; &lt;li&gt;Microsoft decided to build on the good ideas of Excel Services in 2007 and make it super easy and powerful to do basic BI in Excel Services 2010&lt;/li&gt; &lt;li&gt;The success of Excel Services in 2007 has borne Access Services and Visio Services in 2010. My instincts say that Access Services will be much more popular – making it much easier to take a departmental application and “upsize” it to the enterprise&lt;/li&gt; &lt;li&gt;The sheer size of the conference was an indicator of how huge the product has become, and how much customers and Microsoft are betting on the platform.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Our next steps will be to update our webinars to show some of the new 2010 features and how they relate to the existing features, and to try everything out in the Beta release next month. Looking forward to it!&lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=214" width="1" height="1"&gt;</description></item><item><title>Microsoft SharePoint 2010 (SharePoint Conference 2009)</title><link>http://blogs.syrinx.com/blogs/sharepoint/archive/2009/10/24/microsoft-sharepoint-2010-sharepoint-conference-2009.aspx</link><pubDate>Sun, 25 Oct 2009 00:34:34 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:211</guid><dc:creator>RyanT</dc:creator><slash:comments>2</slash:comments><description>&lt;p&gt;First let me apologize for the lack of blogging for a while.&amp;nbsp; We have been under the gun with a sizable SharePoint development project.&amp;nbsp; I have gown farther down into the innards of InfoPath then I ever thought possible.&amp;nbsp; To give you an idea, we worked over 140 hours in the 2 weeks prior to the conference.&amp;nbsp; I promise to be better, and now I have good reason to do so:&lt;/p&gt; &lt;p&gt;We at Syrinx just got back from a long week loaded with sessions, booths, experts, and information &lt;strong&gt;all&lt;/strong&gt; about SharePoint 2010.&amp;nbsp; All I can say is &lt;strong&gt;*WOW*&lt;/strong&gt;.&amp;nbsp; I predict the trend of SharePoint adoption to continue to to climb at an alarming rate.&amp;nbsp; &lt;/p&gt; &lt;p&gt;I&amp;#39;m sure everyone is out there blogging about all the new features, and that&amp;#39;s great!&amp;nbsp; I&amp;#39;m just going to run down the high-level features from the sessions I attended and information I gathered.&amp;nbsp; This is no way an exhaustive list, but as I dig into the new capabilities I will blog about them.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;SharePoint Online / Sandbox Development and Testing&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;SharePoint 2010 will be offered in a software-as-a-service mode with &lt;strong&gt;WILL&lt;/strong&gt; allow custom coding via a sandbox mode that runs in a protected state.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Business Connectivity Services&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;The evolution of the BDC is bi-directional and uses entities for direct connectivity with LOB applications / databases.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;REST&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;This was one of the coolest features added to SharePoint due to the addition of WCF.&amp;nbsp; SharePoint content can be quickly accessed via simple HTTP and it will return XML or JSON.&amp;nbsp; This could prove very interesting.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Office 2010 real-time collaboration&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Office 2010 fully supports real-time collaboration with robust features to sync and protect data while allowing users to work together on documents at the same time.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;SharePoint Workspace&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Gone is Groove, and here comes SharePoint Workspace.&amp;nbsp; You export whole sites and all their content onto your desktop, see changes, sync versions, etc.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Visio Services&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Bring your Visio diagrams to the web and treat the elements as assets in code allowing you attach business logic to these diagrams to visualize LOB data in diagrams in real-time.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Access Services&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Create entire applications in access and &amp;quot;convert&amp;quot; them to SharePoint web applications with simple synchronization.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;RIP Shared Service Provider&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Now we have Service Applications that are independent and available to any web applications and even to other farms!&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Visual Studio 2010 and SharePoint Support&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;New project types and deployment options are going to make this a lot easier for developers.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;SharePoint Designer 2010 and much improved workflow&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;SPD 2010 was overhauled.&amp;nbsp; Amongst other things is the ability to build reusable workflows, export them into Visual Studio, and package them as WSPs for deployment.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Windows 7 and Vista Development Supported&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Now you can develop on workstation-grade operating systems.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;FAST Search Integration&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;FAST is now fully embedded into SharePoint as an optional upgrade.&amp;nbsp; And it is &lt;strong&gt;AWESOME!&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;I will try to explore and blog about each of these in detail as I test, play, and learn from the beta releases of SharePoint 2010 in the coming months!&amp;nbsp; &lt;/p&gt; &lt;p&gt;It was a great conference and I am truly excited about what is to come!&lt;/p&gt; &lt;p&gt;-Ryan&lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=211" width="1" height="1"&gt;</description></item><item><title>SPC 2009 Day Three</title><link>http://blogs.syrinx.com/blogs/sharepoint/archive/2009/10/22/spc-2009-day-three.aspx</link><pubDate>Thu, 22 Oct 2009 14:27:49 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:210</guid><dc:creator>AndrewG</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;Highlights from the day &lt;p&gt;Steve Walker and Joe Indelicato (of Chevron, Joe formerly of the Houston Texans) put on a good presentation about using BI in both cases to improve the business. At the Texans, Joe pioneered using Microsoft technologies to data mine and exploit weakness in other teams. Joe discovered statistical trends in which plays were most likely to be called, and tendencies of players that had the lowest aptitude test scores in Combine (run plays with motion straight at them – they’re more likely to get confused and falter). At Chevron, they are using BI and geospatial dashboards to surface information about the performance of wells and actions that need to be taken on them.  &lt;p&gt;Kraft detailed their migration of 270+ consumer-facing web sites to SharePoint. The case study available on Microsoft.com was detailed – a $2.2M cost savings by moving the sites to SharePoint, while providing a flexible architecture to support unique branding and creative control of each product’s web page. The combined sites have 100M page views per month, with several billion and 100M dollar brands to support, and 98,000 employees as well as external ad agencies who want control. The migration plan demanded that creative efforts were separated from data processing. An architecture leveraging XML, XSL, CSS, Web Parts, and a clever automated packaging and promotion scheme fit the bill. Rollback capability was provided by checking current pages into a document library before promoting new pages. Case study: &lt;a href="http://www.microsoft.com/CaseStudies/Case_Study_Detail.aspx?casestudyid=4000005209" target="_blank"&gt;Available at microsoft.com&lt;/a&gt; &lt;p&gt;Two folks from Microsoft detailed their migration of an internal application for “After the fact Purchase Order” (ATFPO) approval from MOSS 2007 to SharePoint 2010. Many of the items they had to roll by hand to create a security trimmed view of ATFPO’s for users in 2007 were now available off the shelf in 2010 using BCS. They were able to remove many of the “moving parts” from their solution, shrinking development time from 480 to 80 hours, and lines of code from 2763 to 446! As we saw clients leveraging SharePoint 2007 to speed up development cycles for LOB applications over traditional ASP.NET, I believe we’ll see the trend increase exponentially with SharePoint 2010. &lt;p&gt;Jones Lang Lasalle has bet on SharePoint in a big way, using the platform to support their rapidly-growing company. Leveraging MOSS 2007, they were able to capture web leads for the first time (0 – 5000 in the first year), increase the usage of their research downloads four times, and invert their development/maintenance resource allocation from 30%/70% to 70%/30% respectively. Their array of hundreds of sites and several different languages to support (as well as metric/English measurement and other localization considerations) made MOSS the obvious choice. They are currently looking at upgrading to SharePoint 2010, and as one of the larger SharePoint 2007 installations, they provided some interesting data on their pre-upgrade check. Almost all of their current features migrated with little to no intervention, which bodes well for companies considering the move to 2010. Case study: &lt;a href="http://www.microsoft.com/casestudies/Case_Study_Detail.aspx?CaseStudyID=4000003111" target="_blank"&gt;Available at microsoft.com&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=210" width="1" height="1"&gt;</description></item><item><title>Day Two of the SharePoint Conference 2009 (SPC)</title><link>http://blogs.syrinx.com/blogs/sharepoint/archive/2009/10/21/day-two-of-the-sharepoint-conference-2009-spc.aspx</link><pubDate>Wed, 21 Oct 2009 14:47:25 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:209</guid><dc:creator>AndrewG</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;There were more in-depth info on SharePoint features and client stories, as well as analyst views on Day 2. Booz Allen Hamilton had a great story about their intranet’s social networking features, and how they drove adoption in a conservative environment where such ideas might normally be resisted. BAH used FAST Search, SharePoint, and some home grown solutions to provide a portal where people could post their availability for projects and managers in need of resources could find out about them, their reporting structure, and skills. They showed off a neat org chart tool that allowed you to dynamically browse groups and reporting relationships. Most of their organization was from tagging, and they let people show a little character in the portal in interests (like gardening, reading, golf, etc). They believe that this helps add a more rounded, human side to the profiles, and also helps suggest groups to form within the organization.  &lt;p&gt;Bamboo Solutions showcased the new project management features in 2010 and in their product Project Management Central, with the help of Dax Sy and Julie Auletta. The combined feature set coupled with SharePoint 2010’s extensibility begs the question – is there anything that full-blown MS Project Server can provide that this solution does not? Portfolio management at the top, tasks, dependencies, updating percent complete on tasks, integration with desktop MS Project, creating dashboards, and alert emails you can format for milestones. I’m going to investigate this more, as many of our clients are interested in solutions like this and have shied away from full-blown MS Project Server thus far.  &lt;p&gt;The session with Forrester on custom development in SharePoint was interesting. Their basic thesis – decide how much you want to get involved in SharePoint and go in with your eyes open. Do you consider SharePoint an application? An app plus “it runs our intranet”? Or do you consider SharePoint an enterprise application and integration platform? If you want to get into advanced projects, realize they are advanced and require a full-strength commitment of resources for development, testing, QA, deployment, and maintenance as any other enterprise application would. Many cases where people were unhappy with SharePoint seemed to stem from starting out with treating it as an application, then wanting to use it for more advanced projects while still wanting to treat it as “just an application” and not a development platform.  &lt;p&gt;Other important ideas: &lt;p&gt;SharePoint is being extended in 2010 to allow you to leave current systems in place and have a “single source of truth” (SSOT) that you can surface through the portal, with optional read/write capability. This is a small refinement to the existing BDC but an important idea in that you can leave the data where it lives (PeopleSoft, SAP, SQL Server, etc) and not have to replicate it to SharePoint to expose it. This allows you to make SharePoint the “one stop shopping” portal for information in the company without a lot of expensive integration. &lt;p&gt;SSOT is expanded further with the REST-ful implementation of items like charts in SharePoint 2010. Common use case: There is a chart showing sales for the past four quarters, and a projection of the next two quarters. This chart lives in Excel, gets emailed around the company, and is copied into dashboards, PowerPoint, etc. What happens when the data in the Excel spreadsheet is updated and the chart changes? There is no way to know how many other places the chart has been copied, so stale data is inevitable. In 2010, you can move the data online and publish the chart in SharePoint to a known URL, and link the other items to this URL. Any changes will be picked up by the downstream consumers when the chart changes. The usual alerts and notifications can also be enabled to know when the chart changes. &lt;p&gt;Speed and Usability – don’t forget about them! In the session with Electronic Arts, they talked about the importance of responsive systems that share information efficiently. They advocated using Firebug and ySlow on your web apps to help figure out where performance can be improved. Their SharePoint implementation removed much of the default JS/CSS in pages in favor of a lightweight style definition (just 32 lines of CSS and 12 images to create a “skin”). They also cited Jakob Nielson’s “F-Theory”, that people scan and read things in a pattern similar to the capital letter F. The implication for SharePoint page layout is to create your web parts and then try a two or three column layout approach putting the most important items in the top left, top right, and middle left. &lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=209" width="1" height="1"&gt;</description></item><item><title>MS SharePoint Conference Day One</title><link>http://blogs.syrinx.com/blogs/sharepoint/archive/2009/10/20/ms-sharepoint-conference-day-one.aspx</link><pubDate>Tue, 20 Oct 2009 14:22:37 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:207</guid><dc:creator>AndrewG</dc:creator><slash:comments>1</slash:comments><description>&lt;p&gt;&lt;/p&gt; &lt;p&gt;Syrinx is here in force at the Microsoft SharePoint Conference 2009 in Las Vegas, NV. The Mandalay Bay is packed with over 6,000 people attending the conference from all over the world. The morning was spent in a keynote with Steve Ballmer and a demo of the new SharePoint 2010 capabilities. Highlights for those that cannot be here: &lt;ul&gt; &lt;li&gt;SharePoint 2010 Beta release scheduled for next month (November 2009)&lt;/li&gt; &lt;li&gt;Final release sometime in H1 2010&lt;/li&gt; &lt;li&gt;Windows 7 and Vista will be supported for developer platforms, and there is a developer dashboard built in that helps with profiling code. Downside: New developer tools are designed to work with 2010 only, not MOSS 2007.&lt;/li&gt; &lt;li&gt;SharePoint Server is 64 bit only&lt;/li&gt; &lt;li&gt;Better cloud support, allow uploading code and customizing SharePoint Online, and to mix and match cloud and “on premises” installs&lt;/li&gt; &lt;li&gt;Many more SKU’s in this release, four quadrants of products based on Intranet/Internet and cloud/on premises&lt;/li&gt; &lt;li&gt;Great demo’s of Access Services, Visio Services, SharePoint Workspaces (the new ‘Groove” for working disconnected), FAST Search, BCS (the new BDC – now with read/write capabilities and auto-generated CRUD operations for back-end LOB systems), PowerPivot (super Excel – handle 100M rows in one spreadsheet QUICKLY), co-editing of documents by more than one user at a time, “Insights’ the new PerformancePoint&lt;/li&gt; &lt;li&gt;Scalability – 1M+ items in a list/folder, 10M+ in a document library, 100’s of millions across a farm. &lt;/li&gt; &lt;li&gt;Better ability to create taxonomy or informal tagging to build a “folksonomy”&lt;/li&gt; &lt;li&gt;PowerShell admin ability with 500+ commandlets shipped at release&lt;/li&gt; &lt;li&gt;“Visual Upgrade” to run your 2007 to 2010 migration and allow users to cut over on a page by page basis as they are ready (Unanswered question – does this just apply to look and feel/chrome or does this affect web parts, etc? What don’t you see if you do not turn on the 2010 version?)&lt;/li&gt; &lt;li&gt;Streaming video is supported – make your own “ShareTube” and control bandwidth, allow lookahead, etc.&lt;/li&gt; &lt;li&gt;Better deployment capabilities, including the ability to build a solution in SharePoint Designer and have it move to different lists/libraries, or to upsize it to be worked on in Visual Studio. &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Some General SharePoint product differentiators and customer feedback were mentioned &lt;ul&gt; &lt;li&gt;Customers are responding very well to a platform that allows them to solve so many needs – there really is not a competing product that does everything SharePoint does or gives you the value it does&lt;/li&gt; &lt;li&gt;SharePoint is cost effective by saving money three ways – less for licensing than trying to assemble several other competing products to do the same things, less to implement as it gives you so much out of the box, less to maintain and support as you have one platform to cover the many needs and one admin/developer skill set&lt;/li&gt; &lt;li&gt;Favorite first projects: Intranets, Dashboards, Project Management portals, IT Service portals, moving paper-based LOB systems online, Content Management&lt;/li&gt; &lt;li&gt;Microsoft is betting on the platform in a big way. Customers are as well. Great sessions from clients Tyson Foods and Global Crossing on their early SharePoint 2010 experiences. The Office integration done by Tyson to solve real LOB issues was exceptionally impressive.&lt;/li&gt;&lt;/ul&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=207" width="1" height="1"&gt;</description></item><item><title>How about some (almost) free Business Intelligence?</title><link>http://blogs.syrinx.com/blogs/sharepoint/archive/2009/04/02/how-about-some-almost-free-business-intelligence.aspx</link><pubDate>Thu, 02 Apr 2009 14:29:52 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:197</guid><dc:creator>AndrewG</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;I spent a lot of time at the Microsoft office last week in Waltham, including the Quarterly Partner Briefing on Tuesday 3/24. One of the sessions I attended on BI put on by Bob Lincavicks and Tara Seppa clarified some recent announcements about PerformancePoint being rolled into SharePoint. When I first heard about this in January I did not understand it, but after last Tuesday the roadmap and economics are much more clear.  &lt;p&gt;Summary: If you have Microsoft Office SharePoint Server, MOSS Standard Cal, MOSS Enterprise Cal, and Software Assurance, you are now entitled to get PerformancePoint Server at &lt;b&gt;no additional charge &lt;/b&gt;starting yesterday 4/1/2009. No, this is not an April Fools! You download some new bits and can install and use them. PerformancePoint is Microsoft&amp;#39;s full-blown BI platform that sits on top of SQL Server (SSIS/SSRS) and allows you to do all the reporting, dashboarding, scorecards, drill downs, etc until your heart&amp;#39;s content. Learn more about PerformancePoint here: &lt;a href="http://www.microsoft.com/bi/products/performancepoint-server.aspx"&gt;http://www.microsoft.com/bi/products/performancepoint-server.aspx&lt;/a&gt;&lt;br /&gt;and about the licensing announcement here: &lt;a href="http://www.microsoft.com/bi/products/announcement.aspx"&gt;http://www.microsoft.com/bi/products/announcement.aspx&lt;/a&gt;  &lt;p&gt;Most companies we have run into are either already in the situation stated above, or in one of the two following &amp;quot;YOU ALMOST HAVE IT!&amp;quot; states:  &lt;p&gt;1. Have MOSS ECALs as part of a package they purchased, and have considered implementing MOSS (may be running WSS at the moment, or not)  &lt;p&gt;2. Have MOSS server with standard CALs  &lt;p&gt;If you are in either situation, consider stepping up to Microsoft Office SharePoint Server (MOSS) with Standard &amp;amp; Enterprise CALs w/Software Assurance. Chances are your step-up costs won’t be that big, and will pale in comparison to PerformancePoint&amp;#39;s old $25K/server &amp;amp; $195/Cal price tags. You&amp;#39;ll get the Enterprise capabilities of MOSS (Excel Services, Forms Services, BDC, etc) which are worth it in and of themselves, and then be free-rolling on the PerformancePoint. In 2009, who doesn&amp;#39;t want to use a tool like PerformancePoint to get a better handle on the strategic and operational aspects of their business to spot trends, make better and more timely decisions, and target cost cutting? Getting this capability as part of the package can help loosen up budgeting that might not otherwise apply.  &lt;p&gt;Fine print: PerformancePoint will release one more Service Pack as a standalone product this summer, and then if you INSISTED on running it standalone forever, mainstream support would end in 2013, and extended support would end in 2018. See details here: &lt;a href="http://support.microsoft.com/lifecycle/?p1=12922"&gt;http://support.microsoft.com/lifecycle/?p1=12922&lt;/a&gt; Microsoft will be rolling the Monitoring and Analytics pieces of PerformancePoint directly into SharePoint in the Wave 14 (next year this time) timeframe. When they do that they will drop the Planning module from PerformancePoint. There are three capabilities currently in PerformancePoint (Monitoring, Analytics, and Planning). If you&amp;#39;re not using Planning now (everyone in the above scenarios) you&amp;#39;re not going to miss it and don&amp;#39;t need to worry about it. &lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=197" width="1" height="1"&gt;</description><category domain="http://blogs.syrinx.com/blogs/sharepoint/archive/tags/MOSS/default.aspx">MOSS</category><category domain="http://blogs.syrinx.com/blogs/sharepoint/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.syrinx.com/blogs/sharepoint/archive/tags/SharePoint+CAL+Client+Access+License+Enterprise/default.aspx">SharePoint CAL Client Access License Enterprise</category><category domain="http://blogs.syrinx.com/blogs/sharepoint/archive/tags/Business+Intelligence/default.aspx">Business Intelligence</category><category domain="http://blogs.syrinx.com/blogs/sharepoint/archive/tags/eCAL/default.aspx">eCAL</category><category domain="http://blogs.syrinx.com/blogs/sharepoint/archive/tags/CAL/default.aspx">CAL</category></item><item><title>Windows IT Pro Article on Workflow Released</title><link>http://blogs.syrinx.com/blogs/sharepoint/archive/2009/03/31/windows-it-pro-article-on-workflow-released.aspx</link><pubDate>Tue, 31 Mar 2009 19:44:22 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:194</guid><dc:creator>RyanT</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;I wanted to let everyone know I completed an article on using SharePoint workflow with the emphasis on what you can do out of the box with MOSS entitled:&lt;/p&gt; &lt;h3&gt;SharePoint Workflows &lt;/h3&gt; &lt;h3&gt;Transform business processes without writing code.&amp;nbsp; &lt;/h3&gt; &lt;p&gt;It has been published in Windows IT Pro magazine.&amp;nbsp; Here is a link to the article: &lt;/p&gt; &lt;p&gt;&lt;a title="http://windowsitpro.com/article/articleid/101350/sharepoint-workflows.html" href="http://windowsitpro.com/article/articleid/101350/sharepoint-workflows.html"&gt;http://windowsitpro.com/article/articleid/101350/sharepoint-workflows.html&lt;/a&gt;&lt;/p&gt; &lt;p&gt;It is also in the April print edition as well.&lt;/p&gt; &lt;p&gt;-Ryan&lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=194" width="1" height="1"&gt;</description></item><item><title>Presentation on Enterprise Search at Microsoft</title><link>http://blogs.syrinx.com/blogs/sharepoint/archive/2009/03/31/presentation-on-enterprise-search-at-microsoft.aspx</link><pubDate>Tue, 31 Mar 2009 19:34:19 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:193</guid><dc:creator>RyanT</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;I recently presented a case study at Microsoft on 3/26 about work we have done at Gilbane Building Company on custom search components within their enterprise.&amp;nbsp; I had some requests for the presentation and I wanted to provide a link to the powerpoint.&amp;nbsp; Thanks again to Microsoft for hosting the event, and Jon Rider from Gilbane.&amp;nbsp; Here is the link to the &lt;a href="http://dl.getdropbox.com/u/847935/Syrinx-Gilbane-Search.pptx"&gt;presentation&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;-Ryan&lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=193" width="1" height="1"&gt;</description></item><item><title>Making Business Data Actionable with Dashboards</title><link>http://blogs.syrinx.com/blogs/sharepoint/archive/2009/03/19/making-business-data-actionable-with-dashboards.aspx</link><pubDate>Thu, 19 Mar 2009 14:25:00 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:191</guid><dc:creator>IanD</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;Business intelligence is a rapidly growing sector of IT development and expenditure budgets. Products include financial modeling, data analysis, data mining, reporting and charting tools. The large vendors, Oracle, IBM and Microsoft, all have products in this space and continue to develop new ones and refine the existing ones. These tools generate huge amounts of additional data and charts about the business data. This, in turn, creates a new problem:&amp;nbsp; how do you make all this data readily consumable and, more importantly, actionable? How do you summarize the data? The answer is a BI dashboard.&lt;/p&gt;
&lt;p&gt;Read the full &lt;a class="" title="Making Business Data Actionable With Dashboards" href="http://www.information-management.com/specialreports/2009_127/-10015001-1.html" target="_blank"&gt;article&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=191" width="1" height="1"&gt;</description><category domain="http://blogs.syrinx.com/blogs/sharepoint/archive/tags/MOSS/default.aspx">MOSS</category><category domain="http://blogs.syrinx.com/blogs/sharepoint/archive/tags/SharePoint/default.aspx">SharePoint</category><category domain="http://blogs.syrinx.com/blogs/sharepoint/archive/tags/Reporting/default.aspx">Reporting</category><category domain="http://blogs.syrinx.com/blogs/sharepoint/archive/tags/Business+Intelligence/default.aspx">Business Intelligence</category></item><item><title>Fun with System.Xml.Linq.XDocument</title><link>http://blogs.syrinx.com/blogs/dotnet/archive/2009/02/22/fun-with-system-xml-linq-xdocument.aspx</link><pubDate>Mon, 23 Feb 2009 04:28:00 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:188</guid><dc:creator>JohnF</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;I&amp;#39;ve recently been using some new code to do some standard xml manipulation.&amp;nbsp; Although I am pretty comfortable working with an XmlDocument I was interfacing with some code from another team and they were using the newer XDocument.&amp;nbsp; I decided to give it a try and see how well it worked.&amp;nbsp; Needless to say, it&amp;#39;s very different from an XmlDocument.&amp;nbsp; On the other hand, it provides a very intuitive interface and is very easy to use.&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve provided a few examples of adding and updating Elements (this APIs version of Nodes) and also of moving between the traditional XmlDocument and the newer XDocument.&amp;nbsp; I used the XDocument&amp;#39;s Parse method to create a new object directly from a string and was off to the races.&lt;/p&gt;
&lt;p&gt;Here is the code for the examples:&lt;/p&gt;
&lt;h2&gt;Program.cs&lt;/h2&gt;
&lt;p&gt;namespace BlogConsoleDemoApp&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; class Program&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Main()&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; XDocumentDemo.DemoXDocUsage();&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;h2&gt;XDocumentDemo.cs&lt;/h2&gt;
&lt;p&gt;using System.Xml;&lt;/p&gt;
&lt;p&gt;using System.Xml.Linq;&lt;/p&gt;
&lt;p&gt;using System.Xml.XPath;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;namespace BlogConsoleDemoApp&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class XDocumentDemo&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void DemoXDocUsage()&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; XDocument xDocSource = XDocument.Parse(&amp;quot;&amp;lt;?xml version=\&amp;quot;1.0\&amp;quot; encoding=\&amp;quot;utf-8\&amp;quot;?&amp;gt;&amp;lt;albums&amp;gt;&amp;lt;album id=\&amp;quot;1\&amp;quot;&amp;gt;&amp;lt;name&amp;gt;Get your Ya-Yas Out&amp;lt;/name&amp;gt;&amp;lt;artist&amp;gt;The Rolling Stones&amp;lt;/artist&amp;gt;&amp;lt;rating&amp;gt;5&amp;lt;/rating&amp;gt;&amp;lt;/album&amp;gt;&amp;lt;album id=\&amp;quot;2\&amp;quot;&amp;gt;&amp;lt;name&amp;gt;The White Album&amp;lt;/name&amp;gt;&amp;lt;artist&amp;gt;The Beatles&amp;lt;/artist&amp;gt;&amp;lt;rating&amp;gt;5&amp;lt;/rating&amp;gt;&amp;lt;/album&amp;gt;&amp;lt;album id=\&amp;quot;3\&amp;quot;&amp;gt;&amp;lt;name&amp;gt;Baba O&amp;#39;Reilly&amp;lt;/name&amp;gt;&amp;lt;artist&amp;gt;The Who&amp;lt;/artist&amp;gt;&amp;lt;rating&amp;gt;5&amp;lt;/rating&amp;gt;&amp;lt;/album&amp;gt;&amp;lt;album id=\&amp;quot;4\&amp;quot;&amp;gt;&amp;lt;name&amp;gt;Houses of the Holy&amp;lt;/name&amp;gt;&amp;lt;artist&amp;gt;Led Zepplin&amp;lt;/artist&amp;gt;&amp;lt;rating&amp;gt;5&amp;lt;/rating&amp;gt;&amp;lt;/album&amp;gt;&amp;lt;album id=\&amp;quot;5\&amp;quot;&amp;gt;&amp;lt;name&amp;gt;All Along the Watchtower&amp;lt;/name&amp;gt;&amp;lt;artist&amp;gt;Jimi Hendrix&amp;lt;/artist&amp;gt;&amp;lt;rating&amp;gt;5&amp;lt;/rating&amp;gt;&amp;lt;/album&amp;gt;&amp;lt;/albums&amp;gt;&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; XDocument xDoc = XDocument.Parse(&amp;quot;&amp;lt;?xml version=\&amp;quot;1.0\&amp;quot; encoding=\&amp;quot;utf-8\&amp;quot;?&amp;gt;&amp;lt;myalbums&amp;gt;&amp;lt;album id=\&amp;quot;121\&amp;quot;&amp;gt;&amp;lt;name&amp;gt;Toys in the Attic&amp;lt;/name&amp;gt;&amp;lt;artist&amp;gt;Aerosmith&amp;lt;/artist&amp;gt;&amp;lt;rating&amp;gt;4&amp;lt;/rating&amp;gt;&amp;lt;/album&amp;gt;&amp;lt;album id=\&amp;quot;34\&amp;quot;&amp;gt;&amp;lt;name&amp;gt;Alive&amp;lt;/name&amp;gt;&amp;lt;artist&amp;gt;KISS&amp;lt;/artist&amp;gt;&amp;lt;rating&amp;gt;3&amp;lt;/rating&amp;gt;&amp;lt;/album&amp;gt;&amp;lt;album id=\&amp;quot;23\&amp;quot;&amp;gt;&amp;lt;name&amp;gt;Goodbye Yellow Brick Road&amp;lt;/name&amp;gt;&amp;lt;artist&amp;gt;Elton John&amp;lt;/artist&amp;gt;&amp;lt;rating&amp;gt;4&amp;lt;/rating&amp;gt;&amp;lt;/album&amp;gt;&amp;lt;album id=\&amp;quot;229\&amp;quot;&amp;gt;&amp;lt;name&amp;gt;Girlfriend&amp;lt;/name&amp;gt;&amp;lt;artist&amp;gt;Matthew Sweet&amp;lt;/artist&amp;gt;&amp;lt;rating&amp;gt;3&amp;lt;/rating&amp;gt;&amp;lt;/album&amp;gt;&amp;lt;album id=\&amp;quot;244\&amp;quot;&amp;gt;&amp;lt;name&amp;gt;Live at the Sands&amp;lt;/name&amp;gt;&amp;lt;artist&amp;gt;Frank Sinatra&amp;lt;/artist&amp;gt;&amp;lt;rating&amp;gt;5&amp;lt;/rating&amp;gt;&amp;lt;/album&amp;gt;&amp;lt;/myalbums&amp;gt;&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(&amp;quot;Original Xml&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(xDoc.ToString());&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // create a new rating element and replace the existing element (retrieved using XPath) with the new element&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; XElement oldXElement = xDoc.XPathSelectElement(&amp;quot;myalbums/album[@id = &amp;#39;34&amp;#39;]/rating&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; XElement newXElement = new XElement(&amp;quot;rating&amp;quot;, &amp;quot;5&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (oldXElement != null) oldXElement.ReplaceWith(newXElement);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(&amp;quot;&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(&amp;quot;******************************************************************************&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(&amp;quot;Rating changed on the KISS album&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(xDoc.ToString());&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Get the Matthew Sweet entry using XPath and replace it with Led Zepplin&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; XElement oldXElementToBeReplaced = xDoc.XPathSelectElement(&amp;quot;myalbums/album[@id = &amp;#39;229&amp;#39;]&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; XElement newXElementToReplaceWith = xDocSource.XPathSelectElement(&amp;quot;albums/album[@id = &amp;#39;4&amp;#39;]&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (oldXElementToBeReplaced != null) oldXElementToBeReplaced.ReplaceWith(newXElementToReplaceWith);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(&amp;quot;&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(&amp;quot;******************************************************************************&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(&amp;quot;Matthew Sweet replaced by Led Zepplin&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(xDoc.ToString());&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // create and add this new element&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;lt;album id=\&amp;quot;2007\&amp;quot;&amp;gt;&amp;lt;name&amp;gt;&amp;lt;/name&amp;gt;&amp;lt;artist&amp;gt;Foo Fighters&amp;lt;/artist&amp;gt;&amp;lt;rating&amp;gt;4&amp;lt;/rating&amp;gt;&amp;lt;/album&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; XElement newXElementAdd = new XElement(&amp;quot;album&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; newXElementAdd.SetAttributeValue(&amp;quot;id&amp;quot;, &amp;quot;2007&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; newXElementAdd.SetElementValue(&amp;quot;name&amp;quot;, &amp;quot;There Goes My Hero&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; newXElementAdd.SetElementValue(&amp;quot;artist&amp;quot;, &amp;quot;Foo Fighters&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; newXElementAdd.SetElementValue(&amp;quot;rating&amp;quot;, &amp;quot;4&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (xDoc.Root != null) xDoc.Root.Add(newXElementAdd);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(&amp;quot;&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(&amp;quot;******************************************************************************&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(&amp;quot;Foo Fighters Created on the fly and added&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(xDoc.ToString());&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Convert to XmlDocument&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; XmlDocument xmlDoc = new XmlDocument();&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; xmlDoc.LoadXml(xDoc.ToString());&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(&amp;quot;&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(&amp;quot;******************************************************************************&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(&amp;quot;Convert to XmlDocument for use with existing methods&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(xmlDoc.InnerXml);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Convert Back to XDocument&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; XDocument newXDoc = XDocument.Parse(xmlDoc.InnerXml);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(&amp;quot;&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(&amp;quot;******************************************************************************&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(&amp;quot;Convert back to XDocument when done&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(newXDoc.ToString());&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;I hope it helps - take care until next time.&lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=188" width="1" height="1"&gt;</description><category domain="http://blogs.syrinx.com/blogs/dotnet/archive/tags/.Net/default.aspx">.Net</category><category domain="http://blogs.syrinx.com/blogs/dotnet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.syrinx.com/blogs/dotnet/archive/tags/XDocument/default.aspx">XDocument</category><category domain="http://blogs.syrinx.com/blogs/dotnet/archive/tags/System.Xml.Linq/default.aspx">System.Xml.Linq</category><category domain="http://blogs.syrinx.com/blogs/dotnet/archive/tags/XmlDocument/default.aspx">XmlDocument</category></item><item><title>How to be in two places at the same time - Asynchronous method calls</title><link>http://blogs.syrinx.com/blogs/dotnet/archive/2009/02/02/how-to-be-in-two-places-at-the-same-time-asynchronous-method-calls.aspx</link><pubDate>Mon, 02 Feb 2009 07:41:00 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:187</guid><dc:creator>JohnF</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Overview:&lt;/h2&gt;
&lt;p&gt;Oftentimes developers are faced with time consuming tasks that appear to make the software being developed run slowly.&amp;nbsp; The majority of code developed is sequential and synchronous.&amp;nbsp; That is, step one is processed and when it is completed step two is processed.&amp;nbsp; There are, however times when a process that is not critical to the current output delays the application (for instance, after retrieving a large dataset from a database for a web application and rendering some portion of it to the page we might want to cache the dataset so as not to have to make another call to the database.)&amp;nbsp; Situations such as these are perfect opportunities to implement asynchronous logic and have the application be a bit faster.&lt;/p&gt;
&lt;p&gt;In the following console application I implemented an artificial call that does nothing but wait a set amount of time before continuing with its execution.&amp;nbsp; This is intended to mimic the effort required to execute some piece of useful code within our application (like the caching example in the previous paragraph).&amp;nbsp; The output following the code is very clear as to the action and sequence being taken within the code.&lt;/p&gt;
&lt;p&gt;To implement an asynchronous call one delegate is required.&amp;nbsp; It must have the same signature as the method that you will be calling, in this case the DoSomeUsefulWorkDelegate.&amp;nbsp; This delegate allows us to execute the method using the BeginInvoke method.&amp;nbsp; This method starts the function on the ThreadPool where it gets a new thread to perform its work.&lt;/p&gt;
&lt;p&gt;If some clean-up or exception handling needs to be performed then another delegate is also required.&amp;nbsp; This second delegate is a System.AsyncCallback - the method takes one IAsyncResult parameter (in our console app we use the DoSomeUsefulWorkWrapUp method).&amp;nbsp; This callback is passed into the BeginInvoke method after the original signature values (in our console app, just the secondsToSleep integer value).&amp;nbsp; This method is called when the method has completed its work.&amp;nbsp; The BeginInvoke also takes a final parameter that holds an object that contains state information that needs to be passed around.&lt;/p&gt;
&lt;p&gt;The AsyncCallback method passed into the BeginInvoke will be called receiving an IAsyncResult object as its parameter.&amp;nbsp; This object is the key to Asynchronous method working - it is of type System.Runtime.Remoting.Messaging.AsyncResult but it holds all of the information for the calling method, exception and other useful information in its _replyMsg [((System.Runtime.Remoting.Messaging.AsyncResult)(ar))._replyMsg].&amp;nbsp; It holds the state information passed around by the user in the AsyncState.&lt;/p&gt;
&lt;h2&gt;Console App:&lt;/h2&gt;
&lt;p&gt;using System.Diagnostics;&lt;/p&gt;
&lt;p&gt;using System.Runtime.Remoting.Messaging;&lt;/p&gt;
&lt;p&gt;using System.Threading;&lt;/p&gt;
&lt;p&gt;using System;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;namespace BlogConsoleDemoApp&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; class Program&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static int _counter = 0;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Main()&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const int SLEEP_DURATION_IN_SECONDS = 2;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AsynchronousCall(SLEEP_DURATION_IN_SECONDS);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(&amp;quot;****&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SynchronousCall(SLEEP_DURATION_IN_SECONDS);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DoSomeUsefulWork(15);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static void AsynchronousCall(int SLEEP_DURATION_IN_SECONDS)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PrintTimestamp(&amp;quot;before asynchronous call to method&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DoSomeUsefulWorkDelegate delDoSomeUsefulWorkDelegate = DoSomeUsefulWorkWithAnException;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AsyncCallback ac = DoSomeUsefulWorkWrapUp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Call method asynchronously 6 times.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (int i = 0; i &amp;lt; 6; i++)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; delDoSomeUsefulWorkDelegate.BeginInvoke(SLEEP_DURATION_IN_SECONDS, ac, &amp;quot;passed around state&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PrintTimestamp(&amp;quot;after asynchronous call to method&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static void SynchronousCall(int secondsToSleep)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PrintTimestamp(&amp;quot;before synchronous call to method&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DoSomeUsefulWork(secondsToSleep);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PrintTimestamp(&amp;quot;after synchronous call to method&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static void DoSomeUsefulWork(int secondsToSleep)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // sleep &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Thread.Sleep(secondsToSleep*1000);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static void DoSomeUsefulWorkWithAnException(int secondsToSleep)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((++_counter % 3) != 0)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // sleep &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PrintTimestamp(&amp;quot;before call in work with exception method&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Thread.Sleep(secondsToSleep*1000);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PrintTimestamp(&amp;quot;after call in work with exception method&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int workerThreads, completionPortThreads;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ThreadPool.GetAvailableThreads(out workerThreads,&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; out completionPortThreads);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // build a message to log&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string message =&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String.Format(@&amp;quot;Is Thread Pool Thread: {0}, Thread Id: {1} Available Worker Threads {2}&amp;quot;,&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Thread.CurrentThread.IsThreadPoolThread,&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Thread.CurrentThread.GetHashCode(),&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; workerThreads);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw new Exception(&amp;quot;Exception thrown: &amp;quot; + message);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public delegate void DoSomeUsefulWorkDelegate(int secondsToSleep);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static void DoSomeUsefulWorkWrapUp(IAsyncResult ar)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DoSomeUsefulWorkDelegate doSomeUsefulWorkDelegate = (DoSomeUsefulWorkDelegate)((AsyncResult)ar).AsyncDelegate;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; doSomeUsefulWorkDelegate.EndInvoke(ar);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch (Exception ex)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PrintTimestamp(ex.Message);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static void PrintTimestamp(string message)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Trace.WriteLine(string.Format(&amp;quot;Timestamp {0}: {1}&amp;quot;, message, DateTime.Now.ToLongTimeString()));&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;h2&gt;Output:&lt;/h2&gt;
&lt;p&gt;Timestamp before asynchronous call to method: 2:02:52 AM&lt;/p&gt;
&lt;p&gt;Timestamp before call in work with exception method: 2:02:52 AM&lt;/p&gt;
&lt;p&gt;Timestamp after asynchronous call to method: 2:02:52 AM&lt;/p&gt;
&lt;p&gt;****&lt;/p&gt;
&lt;p&gt;Timestamp before synchronous call to method: 2:02:52 AM&lt;/p&gt;
&lt;p&gt;Timestamp before call in work with exception method: 2:02:53 AM&lt;/p&gt;
&lt;p&gt;Timestamp after synchronous call to method: 2:02:54 AM&lt;/p&gt;
&lt;p&gt;Timestamp after call in work with exception method: 2:02:54 AM&lt;/p&gt;
&lt;p&gt;Timestamp before call in work with exception method: 2:02:54 AM&lt;/p&gt;
&lt;p&gt;Timestamp Exception thrown: Is Thread Pool Thread: True, Thread Id: 13 Available Worker Threads 247: 2:02:54 AM&lt;/p&gt;
&lt;p&gt;Timestamp before call in work with exception method: 2:02:54 AM&lt;/p&gt;
&lt;p&gt;Timestamp after call in work with exception method: 2:02:55 AM&lt;/p&gt;
&lt;p&gt;Timestamp Exception thrown: Is Thread Pool Thread: True, Thread Id: 14 Available Worker Threads 246: 2:02:55 AM&lt;/p&gt;
&lt;p&gt;Timestamp after call in work with exception method: 2:02:56 AM&lt;/p&gt;
&lt;p&gt;Timestamp after call in work with exception method: 2:02:56 AM&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;That&amp;#39;s it for this time - hope it helps.&lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=187" width="1" height="1"&gt;</description><category domain="http://blogs.syrinx.com/blogs/dotnet/archive/tags/.Net/default.aspx">.Net</category><category domain="http://blogs.syrinx.com/blogs/dotnet/archive/tags/BeginInvoke/default.aspx">BeginInvoke</category><category domain="http://blogs.syrinx.com/blogs/dotnet/archive/tags/EndInvoke/default.aspx">EndInvoke</category><category domain="http://blogs.syrinx.com/blogs/dotnet/archive/tags/IAsynchResult/default.aspx">IAsynchResult</category><category domain="http://blogs.syrinx.com/blogs/dotnet/archive/tags/Asynchronous/default.aspx">Asynchronous</category></item><item><title>Customized Content Rating for SharePoint</title><link>http://blogs.syrinx.com/blogs/sharepoint/archive/2009/01/28/customized-content-rating-for-sharepoint.aspx</link><pubDate>Thu, 29 Jan 2009 01:01:45 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:186</guid><dc:creator>RyanT</dc:creator><slash:comments>13</slash:comments><description>&lt;p&gt;I wanted to share with you a recent client undertaking involving adding &amp;quot;star rating&amp;quot; and comments to SharePoint content.&amp;nbsp; As usual, clients prefer not to build everything from scratch, so I looked what was available via 3rd party options and found 2 potentially viable solutions:&lt;/p&gt; &lt;p&gt;&lt;strong&gt;SharePoint Document Rating System&lt;/strong&gt;&amp;nbsp; from codeplex:&amp;nbsp; &lt;a title="http://www.codeplex.com/spdocrating" href="http://www.codeplex.com/spdocrating"&gt;http://www.codeplex.com/spdocrating&lt;/a&gt; and a licensed offering from KwizCom:&amp;nbsp; &lt;a title="http://www.kwizcom.com/" href="http://www.kwizcom.com/"&gt;http://www.kwizcom.com/&lt;/a&gt;&lt;/p&gt; &lt;p&gt;At the time, the codeplex solution seemed a little more difficult to deal with, requiring content types and multiple columns in a list to function.&amp;nbsp; These column also appeared to be based on non-standard formats, and it was not straightforward to use the columns as managed properties to create more fine-tuned search options.&lt;/p&gt; &lt;p&gt;Since the KwizCom solution was simply a custom field type installed into SharePoint based on a common decimal base type, it seemed much easier to implement.&amp;nbsp; The downside was that it was some custom code, not open source, and it was entirely obfuscated so when I needed to make some adjustments based on my requirements, I was really stuck with what they gave me.&amp;nbsp; Here&amp;#39;s what I did in case someone is thinking about doing this:&lt;/p&gt; &lt;p&gt;I added their custom field to my SharePoint environment and created a site column from it called &lt;strong&gt;Ratings&lt;/strong&gt;.&amp;nbsp; Below is a screen shot of what this looks like in a list/library&lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.syrinx.com/blogs/sharepoint/WindowsLiveWriter/CustomizedContentRatingforSharePoint_13003/ratings1_2.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="183" alt="ratings1" src="http://blogs.syrinx.com/blogs/sharepoint/WindowsLiveWriter/CustomizedContentRatingforSharePoint_13003/ratings1_thumb.png" width="214" border="0" /&gt;&lt;/a&gt; &lt;a href="http://blogs.syrinx.com/blogs/sharepoint/WindowsLiveWriter/CustomizedContentRatingforSharePoint_13003/ratings2_2.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="184" alt="ratings2" src="http://blogs.syrinx.com/blogs/sharepoint/WindowsLiveWriter/CustomizedContentRatingforSharePoint_13003/ratings2_thumb.png" width="210" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;The above shows what the column looks like and what it shows you when you hover over the item.&amp;nbsp; When you click on the item you get a pop up where you can rate and read comments similar to this:&lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.syrinx.com/blogs/sharepoint/WindowsLiveWriter/CustomizedContentRatingforSharePoint_13003/ratings3_2.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="477" alt="ratings3" src="http://blogs.syrinx.com/blogs/sharepoint/WindowsLiveWriter/CustomizedContentRatingforSharePoint_13003/ratings3_thumb.png" width="360" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.syrinx.com/blogs/sharepoint/WindowsLiveWriter/CustomizedContentRatingforSharePoint_13003/ratings4_2.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="220" alt="ratings4" src="http://blogs.syrinx.com/blogs/sharepoint/WindowsLiveWriter/CustomizedContentRatingforSharePoint_13003/ratings4_thumb.png" width="504" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Ok, so the easy part is done:&amp;nbsp; Install the product and add it to a list, and fill out some data.&amp;nbsp; They give you that for free :)&amp;nbsp; Now I had to come up with my own solution for the next 2 problems.&amp;nbsp; First, I needed to include the ratings for documents in search results.&amp;nbsp; It turns out to be pretty easy, but there were a couple wrinkles.&lt;/p&gt; &lt;p&gt;1.&amp;nbsp; I had to copy some images over from the KwizCom installation location to where the layout images live in the 12 hive here:&amp;nbsp; C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\IMAGES&lt;/p&gt; &lt;p&gt;2.&amp;nbsp; Then I had to modify the Search Results page (Search Core Results) to include my column in the XML, and then add a series of XSL &amp;quot;when&amp;quot; to display the star rating image &lt;strong&gt;AND&lt;/strong&gt; the link to the comments as this was a requirement.&lt;/p&gt; &lt;p&gt;&amp;lt;xsl:when test=&amp;quot;contentrating=&amp;#39;1&amp;#39;&amp;quot;&amp;gt; - &amp;lt;img align=&amp;quot;top&amp;quot; style=&amp;quot;cursor:pointer;&amp;quot; onclick=&amp;quot;window.ratingelement=this.parentNode;commonShowModalDialog(&amp;#39;/_layouts/RatingRedirect.aspx?ItemURL={url}&amp;amp;amp;SiteName={sitename}&amp;amp;amp;a=1&amp;#39; ,&amp;#39;dialogHeight:450px;dialogWidth:350px;scroll:no;toolbar:no;status:no;resizable:no;&amp;#39;, null, this.parentNode);&amp;quot; src=&amp;quot;_layouts/KWizCom_RatingSolution/Images/1.0.gif&amp;quot;/&amp;gt;&amp;lt;/xsl:when&amp;gt;&lt;/p&gt; &lt;p&gt;The savvy of you may look at this XSL and wonder what &amp;quot;RatingRedirect.aspx&amp;quot; is.&amp;nbsp; Well, this is something I had to come up with because the KwizCom code is locked down.&amp;nbsp; Essentially I had to write a gateway page that took the querystring data available in the search results page and send it to a location that had the ability to look up the proper data required by the KwizCom page to load rating details.&amp;nbsp; The aspx page code I wrote looks like this:&lt;/p&gt; &lt;div class="code"&gt;&lt;font color="blue"&gt;public&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;partial&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;class&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;RatingRedirect&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;:&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;System.Web.UI.&lt;/font&gt;&lt;font color="#2b91af"&gt;Page&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;{&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="blue"&gt;protected&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;void&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;Page_Load(&lt;/font&gt;&lt;font color="blue"&gt;object&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;sender,&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="#2b91af"&gt;EventArgs&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;e)&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;{&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;ProcessRedirect()&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;}&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="blue"&gt;private&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;void&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;ProcessRedirect()&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;{&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="blue"&gt;string&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;itemURL&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;=&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;Request.QueryString[&lt;/font&gt;&lt;font color="#808080"&gt;&amp;quot;ItemURL&amp;quot;&lt;/font&gt;&lt;font color="black"&gt;]&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="blue"&gt;string&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;siteUrl&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;=&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;Request.QueryString[&lt;/font&gt;&lt;font color="#808080"&gt;&amp;quot;SiteName&amp;quot;&lt;/font&gt;&lt;font color="black"&gt;]&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="blue"&gt;string&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;destination&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;=&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;Request.QueryString[&lt;/font&gt;&lt;font color="#808080"&gt;&amp;quot;a&amp;quot;&lt;/font&gt;&lt;font color="black"&gt;]&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="blue"&gt;using&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;(SPSite&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;mySite&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;=&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;new&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;SPSite(siteUrl))&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;{&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="blue"&gt;using&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;(SPWeb&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;myWeb&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;=&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;mySite.OpenWeb())&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;{&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;SPListItem&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;item&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;=&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;myWeb.GetListItem(itemURL)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="blue"&gt;if&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;(item&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;!&lt;/font&gt;&lt;font color="blue"&gt;=&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;null&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;{&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="blue"&gt;if&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;(destination&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;==&lt;/font&gt;&lt;font color="#808080"&gt; &amp;quot;1&amp;quot;&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;{&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;Response.Redirect(item.Web.Url&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;+&lt;/font&gt;&lt;font color="#808080"&gt; &amp;quot;/_layouts/KWizCom_RatingSolution/RatingPopup.aspx?itemId=&amp;quot; &lt;/font&gt;&lt;font color="black"&gt;+&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;item.ID&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;+&lt;/font&gt;&lt;font color="#808080"&gt; &amp;quot;&amp;amp;listId={&amp;quot; &lt;/font&gt;&lt;font color="black"&gt;+&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;item.ParentList.ID&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;+&lt;/font&gt;&lt;font color="#808080"&gt; &amp;quot;}&amp;quot;&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;}&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="blue"&gt;else&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;if&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;(destination&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;==&lt;/font&gt;&lt;font color="#808080"&gt; &amp;quot;2&amp;quot;&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;{&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;Response.Redirect(item.Web.Url&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;+&lt;/font&gt;&lt;font color="#808080"&gt; &amp;quot;/_layouts/KWizCom_RatingSolution/CommentsPopup.aspx?itemId=&amp;quot; &lt;/font&gt;&lt;font color="black"&gt;+&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;item.ID&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;+&lt;/font&gt;&lt;font color="#808080"&gt; &amp;quot;&amp;amp;listId={&amp;quot; &lt;/font&gt;&lt;font color="black"&gt;+&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;item.ParentList.ID&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;+&lt;/font&gt;&lt;font color="#808080"&gt; &amp;quot;}&amp;quot;&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;}&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;}&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="blue"&gt;else&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;{&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;Response.Write(&lt;/font&gt;&lt;font color="#808080"&gt;&amp;quot;&amp;lt;br&amp;gt;&amp;nbsp;&amp;nbsp; Sorry, this item cannot be rated.&amp;quot;&lt;/font&gt;&lt;font color="black"&gt;)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;}&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;}&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;}&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;}&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;}&lt;/font&gt; &lt;/div&gt; &lt;p&gt;The basics here are that I need to some ListItem data that is completely unavailable at the search results page.&lt;/p&gt; &lt;p&gt;Also consider that only list items can contain ratings.&amp;nbsp; Much of the unratable content can be exluded from search results using contentclass exclusions in your search scopes, but the one that tripped me up was a standard site aspx page.&amp;nbsp; If the page did not live in a library but was returned in search results, it would display with zero ratings.&amp;nbsp; When a user clicked on the details they would receive an error because this was an unratable item.&amp;nbsp; You see my rudimentary error handling section in the code above to at least inform people about the status.&lt;/p&gt; &lt;p&gt;We also added a higher level check in the XSL to only return rating data from content sources that actually had the rating installed.&amp;nbsp; Other SharePoint web applications or site collections within the SSP that does not contain rating data needs to be excluded.&lt;/p&gt; &lt;p&gt;These changes allowed my search results to show the ratings details &lt;strong&gt;AND&lt;/strong&gt; allowed users to view the comments &lt;strong&gt;AND&lt;/strong&gt; add their own comments right from the search results page.&amp;nbsp; The only hiccup is that until another crawl is run, the changes won&amp;#39;t be shown in the search results because that data is pulled from the index and not in real time.&amp;nbsp; A small price to pay.&lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.syrinx.com/blogs/sharepoint/WindowsLiveWriter/CustomizedContentRatingforSharePoint_13003/ratings5_2.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="60" alt="ratings5" src="http://blogs.syrinx.com/blogs/sharepoint/WindowsLiveWriter/CustomizedContentRatingforSharePoint_13003/ratings5_thumb.png" width="527" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Finally, I had to deploy this.&amp;nbsp; Essentially the client wanted to add this to any document libraries that already existed in their site collection.&amp;nbsp; It seems every client requires me to write a tool that iterates over a site collection and checks for something in each web/list.&amp;nbsp; It&amp;#39;s either inheritance, permissions, features, etc. that need to be set for every list if some condition is met.&amp;nbsp; So I had some code I could re-use.&amp;nbsp; I won&amp;#39;t paste the whole thing here, but it was pretty simple:&lt;/p&gt; &lt;p&gt;I iterated over every site and did the following:&amp;nbsp; checked for each list to see if it inherited from base templates of document library or link lists.&amp;nbsp; If so, I iterated over the fields to see if the Rating field was present.&amp;nbsp; If not, I would add the field to the list, then add it to the default view of the list.&amp;nbsp; &lt;/p&gt; &lt;p&gt;Then you have to &amp;quot;tickle&amp;quot; the list, and un-tickle it.&amp;nbsp; This one was critical.&amp;nbsp; Due to the nature in which this data is stored, there is an inherent bug with the KwizCom solution.&amp;nbsp; Their design created a hidden list per web that holds the rating data.&amp;nbsp; This list is not created until a least one rating is made in the web.&amp;nbsp; This code must not run with elevated permissions because users without proper permissions to create the list will receive an error.&amp;nbsp; It&amp;#39;s odd that they missed this because their solution only requires read access in order to rate items, so they must have written elevated permission code elsewhere in their solution.&lt;/p&gt; &lt;p&gt;At any rate, the tickle adds a rating to the first item in the list, updates the item, then removes the rating.&amp;nbsp; This ensures the container list exists moving forward.&lt;/p&gt; &lt;p&gt;All in all it did not take too long to implement and the 3rd party price was pretty inexpensive.&lt;/p&gt; &lt;p&gt;I hope this helps,&lt;/p&gt; &lt;p&gt;-Ryan Thomas&lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=186" width="1" height="1"&gt;</description></item><item><title>How to use the Client Script Manager</title><link>http://blogs.syrinx.com/blogs/dotnet/archive/2009/01/19/how-to-use-the-client-script-manager.aspx</link><pubDate>Mon, 19 Jan 2009 07:25:00 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:184</guid><dc:creator>JohnF</dc:creator><slash:comments>233</slash:comments><description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The ClientScriptManager class is used to manage client scripts and add them to Web applications. You can get a reference to the ClientScriptManager class from the ClientScript property of the Page object. &lt;/p&gt;
&lt;p&gt;You can add a client script to a Web page declaratively by including the script in the HTML markup of the page. &lt;br /&gt;This embedded script would look like this on the aspx page:&lt;br /&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function changePostalCodeLabel(selectedValue) &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var lblZipPostalCode = document.getElementById(&amp;quot;lblZipPostalCode&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(selectedValue == &amp;#39;US&amp;#39;){&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lblZipPostalCode.innerHTML = &amp;#39;Zip Code&amp;#39; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } else { &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lblZipPostalCode.innerHTML = &amp;#39;Postal Code&amp;#39; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;lt;/script&amp;gt;&lt;/p&gt;
&lt;p&gt;However, there are situations when adding client script dynamically is needed. To add a script dynamically, use the RegisterClientScriptBlock method (to inset a dynamically created block of script into the page), the RegisterClientScriptInclude method (to dynamically insert a reference to an external script file into the page), the RegisterStartupScript method (to dynamically insert a script that will execute during start-up), or the RegisterOnSubmitStatement method(to dynamically insert a script that will execute on form submission) &lt;/p&gt;
&lt;p&gt;The ClientScriptManager class uniquely identifies scripts by a key String and a Type. Scripts with the same key and type are considered duplicates. Using the script type helps to avoid confusing similar scripts from different user controls that might be in use on the page.&lt;/p&gt;
&lt;p&gt;One of the biggest advantages to using dynamic scripts is the ability to access the ClientID of various controls on the web page as the page is being loaded.&amp;nbsp; As the simple script listed at the top will work on a simple page when master pages are implemented .NET does some name mangling under the covers and the previous script would not work.&amp;nbsp; With master pages the correct script would be more along the lines of the following:&lt;br /&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function changePostalCodeLabel(selectedValue) &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var lblZipPostalCode = document.getElementById(&amp;quot;&lt;b&gt;ctl00_MainContent_lblZipPostalCode&lt;/b&gt;&amp;quot;);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(selectedValue == &amp;#39;US&amp;#39;){&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lblZipPostalCode.innerHTML = &amp;#39;Zip Code&amp;#39;; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } else { &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lblZipPostalCode.innerHTML = &amp;#39;Postal Code&amp;#39;; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;lt;/script&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;There is no way of knowing at design time, in a guaranteed fashion, what the control name will be.&amp;nbsp; By using the client script manager we can create the script on the fly and have the page provide us with the client id that it will be implementing.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The following example uses a simple drop-down containing three countries.&amp;nbsp; The idea behind the script is that if the selected country is the United States then the text box label will show Zip Code, for any other country it will display Postal Code.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;The code for the aspx page is:&lt;br /&gt;&amp;lt;%@ Page Language=&amp;quot;C#&amp;quot; AutoEventWireup=&amp;quot;true&amp;quot; CodeFile=&amp;quot;ClientScriptManagerExample.aspx.cs&amp;quot; Inherits=&amp;quot;ClientScriptManagerExample&amp;quot; %&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;quot; &amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;head runat=&amp;quot;server&amp;quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;title&amp;gt;Client Script Manager Example Page&amp;lt;/title&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;/head&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;body&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;form id=&amp;quot;form1&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;div&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;asp:DropDownList ID=&amp;quot;ddlCountry&amp;quot; runat=&amp;quot;server&amp;quot; Height=&amp;quot;19px&amp;quot; Width=&amp;quot;184px&amp;quot; onChange=&amp;quot;changePostalCodeLabel(this.value)&amp;quot;&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/asp:DropDownList&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;asp:Label ID=&amp;quot;lblZipPostalCode&amp;quot; runat=&amp;quot;server&amp;quot; Text=&amp;quot;Zip/Postal Code&amp;quot;&amp;gt;&amp;lt;/asp:Label&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;asp:TextBox ID=&amp;quot;txtZipPostalCode&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt;&amp;lt;/asp:TextBox&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/div&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/form&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;/body&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;lt;/html&amp;gt;&lt;/p&gt;
&lt;p&gt;The Code-Behind is this:&lt;br /&gt;using System;&lt;/p&gt;
&lt;p&gt;using System.Text;&lt;/p&gt;
&lt;p&gt;using System.Web.UI;&lt;/p&gt;
&lt;p&gt;using System.Web.UI.WebControls;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;public partial class ClientScriptManagerExample : Page&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected void Page_Load(object sender, EventArgs e)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!IsPostBack)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Add a few countries to the drop-down list&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ListItem liUS = new ListItem(&amp;quot;United States&amp;quot;, &amp;quot;US&amp;quot;, true);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ListItem liUK = new ListItem(&amp;quot;United Kingdom&amp;quot;, &amp;quot;UK&amp;quot;, true);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ListItem liCA = new ListItem(&amp;quot;Canada&amp;quot;, &amp;quot;CA&amp;quot;, true);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ddlCountry.Items.Add(liUS);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ddlCountry.Items.Add(liUK);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ddlCountry.Items.Add(liCA);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Create and register the script&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SetPostalCodeJavascript();&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Set an initial value for the label&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (ddlCountry.SelectedItem.Text.Equals(&amp;quot;United States&amp;quot;))&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lblZipPostalCode.Text = &amp;quot;Zip Code&amp;quot;;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; lblZipPostalCode.Text = &amp;quot;Postal Code&amp;quot;;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private void SetPostalCodeJavascript()&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Define the name and type of the client scripts on the page.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; const string csname = &amp;quot;PostalCodeLabelScript&amp;quot;;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Type cstype = GetType();&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Get a ClientScriptManager reference from the Page class.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ClientScriptManager cs = Page.ClientScript;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Check to see if the client script is already registered.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!cs.IsClientScriptBlockRegistered(cstype, csname))&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; StringBuilder cstext = new StringBuilder();&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cstext.AppendFormat(&amp;quot;&amp;lt;script type=\&amp;quot;text/javascript\&amp;quot;&amp;gt;{0}&amp;quot;, Environment.NewLine);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cstext.AppendFormat(&amp;quot;\tfunction changePostalCodeLabel(selectedValue) {0}&amp;quot;, Environment.NewLine);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cstext.AppendFormat(&amp;quot;\t{{{0}&amp;quot;, Environment.NewLine);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // lblZipPostalCode.ClientID is the important part here&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cstext.AppendFormat(&amp;quot;\t\tvar lblZipPostalCode = document.getElementById(\&amp;quot;{0}\&amp;quot;);{1}&amp;quot;, lblZipPostalCode.ClientID, Environment.NewLine);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cstext.AppendFormat(&amp;quot;\t\tif(selectedValue == &amp;#39;{0}&amp;#39;){{{1}&amp;quot;, &amp;quot;US&amp;quot;, Environment.NewLine);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cstext.AppendFormat(&amp;quot;\t\t\tlblZipPostalCode.innerHTML = &amp;#39;Zip Code&amp;#39; {0}&amp;quot;, Environment.NewLine);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;cstext.AppendFormat(&amp;quot;\t\t}} else {{ {0}&amp;quot;, Environment.NewLine);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cstext.AppendFormat(&amp;quot;\t\t\tlblZipPostalCode.innerHTML = &amp;#39;Postal Code&amp;#39; {0}&amp;quot;, Environment.NewLine);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cstext.AppendFormat(&amp;quot;\t\t}} {0}&amp;quot;, Environment.NewLine);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cstext.AppendFormat(&amp;quot;\t}}{0}&amp;quot;, Environment.NewLine);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cstext.Append(Environment.NewLine);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cstext.AppendFormat(&amp;quot;&amp;lt;/script&amp;gt;{0}&amp;quot;, Environment.NewLine);&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cs.RegisterClientScriptBlock(cstype, csname, cstext.ToString(), false);&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;By using the ClientScriptManager we can really leverage javascript on the client-side where appropriate, reducing round trips to the server, providing a better user experience as well as consuming less server time.&amp;nbsp; A win-win situation&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;That&amp;#39;s it for this time - hope it helps.&lt;/p&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=184" width="1" height="1"&gt;</description><category domain="http://blogs.syrinx.com/blogs/dotnet/archive/tags/.Net/default.aspx">.Net</category><category domain="http://blogs.syrinx.com/blogs/dotnet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.syrinx.com/blogs/dotnet/archive/tags/javascript/default.aspx">javascript</category><category domain="http://blogs.syrinx.com/blogs/dotnet/archive/tags/client-side/default.aspx">client-side</category><category domain="http://blogs.syrinx.com/blogs/dotnet/archive/tags/ClientScriptManager/default.aspx">ClientScriptManager</category></item><item><title>Deleting Deeply Entrenched Site Columns - Another Reason for Governance</title><link>http://blogs.syrinx.com/blogs/sharepoint/archive/2009/01/06/deleting-deeply-entrenched-site-columns-another-reason-for-governance.aspx</link><pubDate>Wed, 07 Jan 2009 01:28:38 GMT</pubDate><guid isPermaLink="false">cd544384-c566-47fe-88af-b61e5bbebb03:182</guid><dc:creator>RyanT</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;I was recently called back to a previous client to help with a list of issues and tasks they had accumulated, and I was surprised to find one very difficult one:&lt;/p&gt; &lt;p&gt;The client complained about seeing multiple duplicate columns available for views and filtering in one of their large document libraries.&amp;nbsp; I knew they used InfoPath, so I had assumed that they had run into the problem I blogged about here:&amp;nbsp; &lt;a title="Automatic Creation of InfoPath forms - not as easy as I thought" href="http://blogs.syrinx.com/blogs/sharepoint/archive/2009/01/05/automatic-creation-of-infopath-forms-not-as-easy-as-i-thought.aspx"&gt;Automatic Creation of InfoPath forms - not as easy as I thought&lt;/a&gt; regarding InfoPath re-creating duplicate site columns when in certain cases of re-publishing forms.&lt;/p&gt; &lt;p&gt;This client had not done anything like this with InfoPath, instead they had created approval workflows (out of the box) at the web/site level and applied them Content Types, so far so good.&amp;nbsp; Each of the multiple Content Type had their own approval workflows, and the columns appearing multiple times all happened to be the name of the column created as the WorkflowStatus type used by SharePoint to maintain the state/status of the workflow.&amp;nbsp; I&amp;#39;m not exactly sure what happened,&amp;nbsp; but I&amp;#39;m assuming they created, deleted, re-created, etc. these workflows using the same name a bunch of times, possibly at different levels within the sites, since some of the Content Types lived at the Site Collection level.&amp;nbsp; This caused this column to keep showing up (same Display Name, unique Internal Name) multiple times.&lt;/p&gt; &lt;p&gt;Although normally not a big deal, this was a real bugger to get rid of.&amp;nbsp; The UI won&amp;#39;t let you drop the field because it is read only on the list, and it&amp;#39;s also attached to the Content Type.&lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.syrinx.com/blogs/sharepoint/WindowsLiveWriter/DeletingDeeplyEntrenchedSiteColumnsAnoth_DB2A/Untitled%20picture4_2.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="160" alt="Untitled picture4" src="http://blogs.syrinx.com/blogs/sharepoint/WindowsLiveWriter/DeletingDeeplyEntrenchedSiteColumnsAnoth_DB2A/Untitled%20picture4_thumb.png" width="289" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Here is how I solved it:&lt;/p&gt; &lt;p&gt;1.&amp;nbsp; Gather up all the data to make sure you know which field is current and legitimate by looking at the data contained within it.&amp;nbsp; Keep at note of the internal name by sorting on it in a list view and looking for the &lt;strong&gt;SortField &lt;/strong&gt;querystring parameter.&lt;/p&gt; &lt;p&gt;2.&amp;nbsp; Delete it from the Content Type first by going to list settings and clicking on a your Content Type link.&amp;nbsp; Then click on any of the columns in this list to get to the &amp;quot;Change List Content Type Column&amp;quot; screen.&amp;nbsp; We need to replace some variables in the querystring to locate our hidden field/column.&lt;/p&gt; &lt;p&gt;First, replace the &lt;strong&gt;Field&lt;/strong&gt; parameter with the *Internal Name* of your field.&amp;nbsp; You have that from #1 above.&lt;/p&gt; &lt;p&gt;Second, you need to replace the &lt;strong&gt;Fid&lt;/strong&gt; (FieldID) parameter with the correct GUID of the field you want to delete from the Content Type.&amp;nbsp; The easiest way for me to do this is to use SharePoint Manager 2007, an invaluable tool that is free from CodePlex.&amp;nbsp; Here is a screenshot where I can see and verify the Internal Name and ID.&amp;nbsp; You can see the duplicate field names under the &amp;quot;Customer Specification&amp;quot; Content Type in the left tree view.&lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.syrinx.com/blogs/sharepoint/WindowsLiveWriter/DeletingDeeplyEntrenchedSiteColumnsAnoth_DB2A/Untitled%20picture5_4.png"&gt;&lt;img style="border-top-width:0px;border-left-width:0px;border-bottom-width:0px;border-right-width:0px;" height="334" alt="Untitled picture5" src="http://blogs.syrinx.com/blogs/sharepoint/WindowsLiveWriter/DeletingDeeplyEntrenchedSiteColumnsAnoth_DB2A/Untitled%20picture5_thumb_1.png" width="597" border="0" /&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;Once you have replaced both of these values &lt;strong&gt;MAKE SURE YOU FORCE A BROWSER RELOAD&lt;/strong&gt;.&amp;nbsp; The best way to do this is copy the new url and load it in a new browser window.&amp;nbsp; You should see your column details in the page.&amp;nbsp; If you just swap variables and hit &amp;quot;Delete&amp;quot; the data in the page may still be pointing at the legitimate column you clicked on to get here.&lt;/p&gt; &lt;p&gt;3.&amp;nbsp; Delete the Field from the actual list.&lt;/p&gt; &lt;p&gt;I was not able to find a way to delete the field from the list through the UI no matter how much trickery or querystring replacement I tried.&amp;nbsp; Fields need to have their &lt;strong&gt;Hidden&lt;/strong&gt; and &lt;strong&gt;ReadOnlyField&lt;/strong&gt; status set false before they can be deleted, and SharePoint Manager 2007 wouldn&amp;#39;t let me do this for some reason.&amp;nbsp; I had to resort to a console application.&amp;nbsp; Quick and dirty code pasted below.&lt;/p&gt; &lt;div class="code"&gt;&lt;font color="#808080"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;SPList&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;isoDocs&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;=&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;web.Lists[&lt;/font&gt;&lt;font color="#808080"&gt;&amp;quot;Documents&amp;quot;&lt;/font&gt;&lt;font color="black"&gt;]&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;SPField&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;field&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;=&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;isoDocs.Fields[&lt;/font&gt;&lt;font color="blue"&gt;new&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="black"&gt;Guid(&lt;/font&gt;&lt;font color="#808080"&gt;&amp;quot;3e68ae11-e4a7-4bfe-aca9-d1cac96c14d1&amp;quot;&lt;/font&gt;&lt;font color="black"&gt;)]&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="#2b91af"&gt;Console&lt;/font&gt;&lt;font color="black"&gt;.WriteLine(field.InternalName)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;LogMessageToFile(field.InternalName)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;field.Hidden&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;=&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;false;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;field.ReadOnlyField&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;=&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt;&lt;font color="blue"&gt;false;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;field.Update()&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt;&lt;font color="#808080"&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;font color="black"&gt;isoDocs.Fields.Delete(field.InternalName)&lt;/font&gt;&lt;font color="blue"&gt;;&lt;/font&gt;&lt;font color="#808080"&gt;&amp;nbsp;&lt;/font&gt; &lt;/div&gt; &lt;div class="code"&gt;&amp;nbsp;&lt;/div&gt; &lt;div class="code"&gt;After tediously looking at each column to figure out what was the correct one and determine which ones to delete through the above process, I was able to clean up the environment.&amp;nbsp; &lt;/div&gt; &lt;div class="code"&gt;&amp;nbsp;&lt;/div&gt; &lt;div class="code"&gt;This brings up an important issue I try to stress with all clients:&amp;nbsp; Governance.&amp;nbsp; In most modern organizations there is enough spare hardware to set up a development/test environment for SharePoint and to restore a copy of your production content DB to test changes against a safe, but duplicate environment.&amp;nbsp; Having these options in place will definitely save you time and money over the long run.&amp;nbsp; I almost never make changes to a production environment, even simple ones, without first testing it against a copy of that environment and evaluating the effects.&amp;nbsp; Some planning up front about having the infrastructure in place and a set of change rules to follow could avert disasters.&lt;/div&gt; &lt;div class="code"&gt;&amp;nbsp;&lt;/div&gt; &lt;div class="code"&gt;&lt;strong&gt;****UPDATE****&lt;/strong&gt;&lt;/div&gt; &lt;div class="code"&gt;I wanted to let everyone know that the column duplication and inability to delete them issue was easy to reproduce, and in my opinion should be a bug in SharePoint.&amp;nbsp; If you create an approval workflow and attach it to a content type, it creates a field in the content type and a field and column in the list where the content type resides.&amp;nbsp; If you delete the workflow the field and column remains, unable to be deleted because of the read-only status.&amp;nbsp; Be careful of this in the future.&lt;/div&gt; &lt;div class="code"&gt;&amp;nbsp;&lt;/div&gt; &lt;div class="code"&gt;I hope this helps,&lt;/div&gt; &lt;div class="code"&gt;-Ryan Thomas&lt;/div&gt;&lt;img src="http://blogs.syrinx.com/aggbug.aspx?PostID=182" width="1" height="1"&gt;</description></item></channel></rss>
