4/30/2007

Microsoft Silverlight 1.1 Alpha is here!

If you pick up a starving dog and make him prosperous, he will not bite you. This is the principal difference between a dog and a man. - Mark Twain



At the MVP Summit in March, Scott Guthrie and friends previewed the 1.1 Alpha of Silverlight (named of course, after my good friend David Silverlight, who runs XMLPitstop.com and other fine sites).

We weren't allowed to talk about it until now - and the 1.1 Alpha is now available - along with some nice Quickstart SDK samples.

Among other fine features, this offers a reduced-set WPF runtime hosted in Internet Explorer, streaming video, and - SURPRISE - Managed code in the browser -- including Javascript access to managed code!

Get it while it's hot!

Now the big question you'll hear is whether this is going to be a "Flash killer". I don't think that will happen right away, but when you look at the streaming video codec and DRM support, support for managed code, dynamic XAML loading and much more, it certainly represents a refreshing technology innovation to me!

Think about this: Silverlight represents an officially-supported cross-platform implementation of the .NET Framework. That's cross-platform AND cross-browser.

But there's more: MS built a common platform to implement dynamic languages like Python (.e.g IronPython) and Ruby on top of .NET. It's the Dynamic Language Runtime, and it plugs into the CLR, and you can plug in your own dynamic languages. This was also previewed at the MVP Summit by David Ebbo and others, along with parts of the Entity Framework, which links Object Services (LINQ) to Data Models, Mapping, and Sources. The DLR will be open sourced under the BSD license, available for all on Codeplex.com, and IronRuby is right behind IronPython. In fact, one of the Silverlight samples uses Python code right now.

Microsoft also offers the Silverlight Streaming hosting solution (FREE!) with up to 4GB space, for hosting your Silverlight streaming media applications. The Streaming SDK offers a simple REST-ful API that is easy to use.

There is probably some confusion about the differences between Silverlight 1.0 BETA and the Silverlight 1.1 ALPHA. Here are some features in ALPHA:

  • Supports communication via XML over HTTP so you can do cool AJAX - like "stuff".
  • You can write "code behind" for your Silverlight apps in C# or VB.NET
  • You can write your Silverlight apps using the Dynamic Language Runtime, which means you can use VB9 or IronPython.
  • Offers all the rich media/video support that Silverlight 1.0 has - plus - true Streaming video.
  • Create a "Silverlight" project from Visual Studio "Orcas" Beta 1.

    NOTE: You can run samples with just the Alpha installed, but if you want to build Silverlight projects, you'll need Orcas Beta 1. The "Microsoft Silverlight Tools Alpha" for Orcas is also available. There is also a preview Expression Media Encoder for creating Silverlight content (the product key for the trial - is on the page - you have to copy and paste it out). The Alpha 1.1 SDK download is here...



Microsoft ASP.NET Futures (May 2007) is also here!

Posts that contain Silverlight per day for the last 30 days.
Technorati Chart


HINT: If you want to find some good custom resources on Silverlight, put that into the custom Google Search widget just below this post. I've got over 1300 custom blogs and resources about .NET that will be searched.

ISSUES:

ORCAS PROJECTS: The first thing I noticed when attempting to load and run any of the sample Silverlight ALPHA 1.1 ORCAS solutions was that they run fine for me with Firefox, but in IE 7 (on Vista) all you get to see is the "Get Silverlight" badge. I've noticed that several users have already posted this on the Silverlight community "Installation and Setup" forum, but I haven't yet seen a fix. I suspect it has to be something like running IE as Administrator. Damned Vista! If you've got info or a fix, post a comment!

DOCUMENTATION: As one might expect, complete documentation is the last thing that makes it into an ALPHA release, and Silverlight is no exception. The CHM documentation has lists of all the objects in the framework, but virtually none of them are "filled in" as one would expect. Just do a search on (System.Windows.Browser.Net.) BrowserHttpWebRequest and you will see what I mean. Hopefully soon we'll see a bit more flesh on them bones...

C# vs VB.NET Case - Sensitivity: what to do

Hegel was right when he said that we learn from history that man can never learn anything from history. -- George Bernard Shaw

This one seems to keep coming up, and basically revolves around developer misunderstanding (or more frequently, lack of knowledge) of Naming Guidelines.

The typical question often looks like the following:

"I have a class implented in a c# dll which has two different properties of same name Say "A" and "a".

Now, is their any way to use any one or both of these properties of this class in a vb.net project.because it will give the following error

Error 2 'A' is ambiguous because multiple kinds of members with this name exist in class 'ClassLibrary3.Class1'"

Yes, there is a solution: Write your classes and methods correctly in the first place!

Case Sensitivity
To avoid confusion and guarantee cross-language interoperation, follow these rules regarding the use of case sensitivity:

Do not use names that require case sensitivity. Components must be fully usable from both case-sensitive and case-insensitive languages. Case-insensitive languages cannot distinguish between two names within the same context that differ only by case. Therefore, you must avoid this situation in the components or classes that you create. Do not create two namespaces with names that differ only by case. For example, a case insensitive language cannot distinguish between the following two namespace declarations:

namespace ee.cummings;
namespace Ee.Cummings;

Do not create a function with parameter names that differ only by case. The following example is incorrect.

void MyFunction(string a, string A)

Do not create a namespace with type names that differ only by case. In the following example, Point p and POINT p are inappropriate type names because they differ only by case.

System.Windows.Forms.Point p
System.Windows.Forms.POINT p

Do not create a type with property names that differ only by case. In the following example, int Color and int COLOR are inappropriate property names because they differ only by case.

int Color {get, set}
int COLOR {get, set}

Do not create a type with method names that differ only by case. In the following example, calculate and Calculate are inappropriate method names because they differ only by case.

void calculate()
void Calculate()

There! That wasn't so hard, was it?

4/26/2007

Enterprise Library 3.0 (April 2007) Goodness

The significant problems we have cannot be solved at the same level of thinking with which we created them. - Einstein



I'm working on a migration of an Application Framework from EntLib 2.0 to Enterprise Library 3.0 (April 2007) for a big client, and I'm quite impressed with Enterprise Library 3.0. This has gotten to the point where it is much more mature, and now sports some very AOP-ish bits with Policy Injection and Validation that really are nicely done -- and extensible.

This is reminiscent of some of the GAT work with dependency injection that Daniel Cazzulino and Victor Aprea were doing a little over a year ago when I talked with them at the 2005 MVP Summit.

There are still a few rough edges, namely that WCSF integration (coming late May to a machine near you) is not complete. However, some developers, such as David Hayden, can't wait, and David has done his own integration (probably cursing all along the way) which you can download.

I can see a growing tide of developers who are ready to embrace these P&P Guidance and Library bits and really start to integrate them into enterprise - level frameworks to build better and more rigorous applications with standardized ways to "do stuff we want to do". If you are building an enterprise-specific application framework, you can base the whole thing on EntLib and standardize across all your developers and teams. Think about it: wouldn't it be nice to have 20 developers all doing their DAL dance the same way, instead of 20 different ways, none of which are as robust or well - thought - out as the single solution?

Recommended. Some study required.

4/24/2007

CCR - Concurrency and Coordination Runtime for asynchronous processing

The Microsoft Robotics Studio (http://msdn.microsoft.com/robotics/), which was recently released, has a unique set of assemblies called Concurrency and Coordination Runtime (CCR). The CCR.Core assembly is only 154KB. Unfortunately, the only way you can get it (currently) is to download and install the entire April 2007 CTP:

(http://www.microsoft.com/downloads/details.aspx?FamilyId=71D96DE4-E3D9-496E-B48E-B35697C88FF1&displaylang=en) -- at 54.3 MB.

The central feature of the CCR is that it makes programming asynchronous behavior much simpler than the typical challenge of writing threaded code.

When an application's thread performs synchronous I/O requests, the application is giving up control of the thread's processing to the I/O device (a hard drive, a network, etc.). The application's responsiveness then becomes unpredictable. When threads are suspended waiting for I/O requests to complete, the application tends to create more threads in an attempt to accomplish more work. The problem is that creating, scheduling, and destroying a thread requires time and memory and can actually hurt performance rather than improve it.

The CCR offers a number of classes that provide the developer with a simple object model that you can use to express complex coordination patterns for dealing with completed I/O operations. CCR offers its own high-performance thread pool you can use to execute tasks in response to completed I/O. The thread pool offers great scalability, and when you couple the CCR with some of the new C# language features (such as anonymous methods and iterators), you have gotten an easy way to write more responsive and scalable applications.

With the CLR's thread pool, if 1,000 items are queued, there is no way for a new item to be processed until all of the first 1,000 items have been extracted from the thread pool's queue. With the CCR you can use one DispatcherQueue object for most work items and use another DispatcherQueue object for high-priority work items. The Dispatcher's threads dequeue entries from all the DispatcherQueue objects associated with it in a round-robin fashion, making your total processing much more efficient and scalable.

The Dispatcher class creates a Dispatcher object that creates and manages a set of threads. In effect, it is a thread pool. Like the CLR's thread pool, these threads call methods (via delegates) in order to execute tasks. Unlike the CLR's thread pool, there is no special thread that runs periodically checking the workload and trying to predict whether threads should be dynamically added or removed from the thread pool.

After you've created a Dispatcher, you'll construct a DispatcherQueue object. This maintains a queue of delegates that identify methods ready to execute. The Dispatcher's threads wait for entries to appear in the DispatcherQueue. As entries appear, Dispatcher threads wake up and execute the methods.

A generic Port object represents a queue of items, all of type T. Port is a way to queue an input argument to a callback method, which is analogous to the state object argument that you pass to ThreadPool's QueueUserWorkItem method.

The Arbiter class is what you use to tap into CCR coordination features. Arbiter is a static class that defines methods that are factories for creating other objects. When you call one of Arbiter's static factory methods, the method constructs an arbiter that has fields that refer to one or more ReceiverTask objects that are also constructed. There is a whole list of types of Arbiters that can be used. You can find more information about the various types of arbiters at the Channel 9 CCR wiki.

Jeffrey Richter has an excellent article that illustrates most of what you need to know to use the CCR (http://msdn.microsoft.com/msdnmag/issues/06/09/concurrentaffairs/default.aspx). There is also a forum: http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=1424&SiteID=1 .

I would package the CCR.Core.dll assembly with Richter's sample code demo from the article and make it freely downloadable so if, like me, you aren't really interested in the rest of the 54MB download, you would be able to get the CCR alone -- but I'm afraid it might be violating the EULA or some similar sinful act.

Up until now, I had never seen anything that approached a solution to these common async threading issues other than Ami Bar's SmartThreadPool project, which stands on its own as a very useful and scalable piece of code.

CCR: Highly Recommended for developers who need more flexibility and scale when writing coordinated asynchronous processing! And also, a thank you to Jon Skeet whose C# language newsgroup post reminded me that I had seen Richter's article but never took the next step, until now.

N.B. I've left a suggestion post on the forum that they break out the CCR assemblies and make them available separately. If you agree, adding a "Me too" probably wouldn't hurt the effort.

-- And here is the answer:

"we have heard this feedback many times indeed. While we do definately see alot of interest in the CCR from non robotics users, currently our team can only afford the non-trivial release management process MSFT requires, for one product/SDK. Other than the size of the download however, which i do agree is alot for a 200k lib, the CCR can be used in any application you want, with no burden or requirements on anything else in MSRS (it was and will continue to be developed as a seperate, independent component).

Another thing to note ofcourse, given its current packaging, is that the CCR is not free for commercial use. Its cost per deployment is about
2$ (our commercial license gives you 200 runtimes for 399$ for a single dev license)"


S0: the bottom line as I interpret this is that if I want to use CCR for any kind of commercial application, I have to purchase the minimum dev license for $399.00. Umm, OooKay...

4/22/2007

Orcas and Visual Studio 2005: So happy together...

Well, unless you've had your head buried in endless code and don't ever come up for air, you know that Visual Studio Codename "Orcas" BETA 1 is out, and you have two choices:

1) Download all the pieces for a VPC installation and run it in a VM, or
2) Download the iso image and install it on the machine proper.

I've never been enamored of number 1; I just don't like the feeling of running something in a virtual machine and dealing with all the memory and other issues; and besides, I want to really test this thing out and the best way to do that, in my book, is to take the plunge.

Now of course the question becomes -- is it going to be happy with being on the same OS as Visual Studio 2005, and vice-versa? For me, the answer is "yes". So far I have noticed nothing unusual at all. Each guy acts like he knows nothing about the other, and as far as I'm concerned, that's perfectly fine with me! They do mention prominently that when you uninstall Orcas BETA 1, you may need to perform a repair on Visual Studio 2005. No biggie.

The other issue you'll run into is a technology issue: when you download that big 5,585,460 KB iso image, you may get the feeling that it just might have some difficulty fitting onto a 4 GB DVD... and, of course, you'd be right. It's a UDF file system. That means WinISO or WinRar arent' gonna be able to see the files. Unless you've got the licensed version of ISOBuster, he won't let you extract them either.

So! You can't burn it to a DVD, and you can't extract the files, so what do you do? Well, you download Daemon Tools, which is free, and you mount the ISO on a virtual DVD drive!

Orcas will install perfectly when you use this technique, since, at least to Orcas, it's exactly where it is supposed to be - on a DVD! On the only reboot, it tried to continue before Daemon Tools had completely come up and remounted, but a few seconds later a click on the Retry button did the trick.

I should hasten to add that this is a very long install since there is a whole buncha stuff that gets installed. I recommend using the custom option so you can deselect stuff you know you can do without (in my case that would be Crystal Reports and Dotfuscator Community Edition.) The single reboot came very soon after the beginning, so as soon as you take care of that you can go out and get yourself a nice spaghetti dinner and some wine with the Significant Other and show them that you, erm, actually do "have a life"...

Orcas, by the way, was named after Orcas Island, which is right off the coast of Washington State. Have fun! Orc, Orc! And now, eine kleine LINQ with some lambda expressions!

4/19/2007

ISP's DNS Got you down? Try This.

I don't know about you, but Brighthouse (Time Warner, RoadRunner, whatever you call it) has some real DNS issues here in cfl (that's "Central Florida" as in cfl.rr.com). Sometimes it just goes completely out, other times it works for some sites and not for others.

If you have a similar problem, obviously the first step is to complain to the provider. Of course, that doesn't always work. One suggestion I tried is to use the OpenDNS Service (it's free).

You can visit their welcome page here (if you aren't hooked up yet, they will guide you through it). It doesn't matter if you have a wireless router or whatever. Just update the "Preferred DNS" entries in your network connection, reboot, and you are up.

It seems to be fast and reliable. It automatically protects against known phishing sites, and it even automatically corrects your url spelling mistakes!

For a real quickie, the entries:

OPENDNS:
208.67.222.222
208.67.220.220

These people at OpenDNS are solid. They handle over a billion DNS requests daily. Take a look for yourself.

4/18/2007

Simple XOR Encryption With T-SQL and Built-in Functions

Some time ago I presented an article about why XOR encryption can be a useful "just enough" technique to easily handle encryption and decryption of strings such as connection strings in configuration files.

By carefully choosing the value to use as the operand in the XOR function, we can create an encrypted string that is "XML Safe". One such ASCII value I found was the integer 129. The advantage of XOR is that it is bidirectional - when you XOR the result of a previous XOR operation, you get back the original value. This means you only need one method to both encrypt and decrypt a string.

I should hasten to note that XOR encryption is NOT a strong encryption algorithm - it's probably one of the first things a determined hacker would try. However, for simply keeping your stuff "away from prying eyes" -- it can often be "just enough".

The following example illustrates how one can create a UDF in SQL Server to perform the same operation.



CREATE FUNCTION [dbo].[ufn_EncryptDecryptString] ( @pClearString VARCHAR(MAX) )
RETURNS NVARCHAR(MAX) WITH ENCRYPTION AS
BEGIN
DECLARE @vEncryptedString NVARCHAR(100)
DECLARE @vIdx INT
DECLARE @vBaseIncrement INT
SET @vIdx = 1
SET @vBaseIncrement = 128
SET @vEncryptedString = ''
WHILE @vIdx <= LEN(@pClearString)

BEGIN
SET @vEncryptedString = @vEncryptedString + NCHAR(ASCII( SUBSTRING(@pClearString, @vIdx, 1)) ^129)
SET @vIdx = @vIdx + 1
END
RETURN @vEncryptedString
END
GO

This sample results in an encrypted string:


Declare @test varchar(200)
Select @test= dbo.ufn_EncryptDecryptString( 'this is a string to be encrypted.')
Print @test

Result:
õéèò¡èò¡à¡òõóèïæ¡õî¡ãä¡äïâóøñõäå¯

Now if we pass the result back into the function:


Declare @test varchar(200)
Select @test= dbo.ufn_EncryptDecryptString( 'õéèò¡èò¡à¡òõóèïæ¡õî¡ãä¡äïâóøñõäå¯')
Print @test

Result:

this is a string to be encrypted.

Using this in a stored proc or other SQL is easy. Assume you have a table NOTES with a column "NOTE":


INSERT INTO NOTES (NOTE)
VALUES (dbo.ufn_EncryptDecryptString('this is some text to encrypt via XOR' ))


SELECT
dbo.ufn_EncryptDecryptString( NOTE)
FROM NOTES


NOTE: SQL Server 2005 offers new encryption functions such as EncryptByPassPhrase and DecryptByPassPhrase, but they require the use of a varbinary column, which introduces a higher level of diffculty; the main issue being the conversion of the HEX string of encrypted text to varbinary for passing into the Decrypt function. Here is an example of usage:


Declare @string nvarchar(MAX)
set @string = 'this is text to encrypt.'
declare @encrypted_str NVARCHAR(MAX)
select @encrypted_str = EncryptByPassPhrase('pigscanfly', @string)
DECLARE @decrypted_str VARBINARY(MAX)
SET @decrypted_str = DecryptByPassPhrase('pigscanfly', @encrypted_str);
-- display decrypted text
SELECT CONVERT(NVARCHAR(MAX), @decrypted_str) AS PlainText;


Finally, you can "custom generate" your own random unique keys of any desired length. Here is an example of a stored proc that does just this:


CREATE PROCEDURE [dbo].[sp_GenerateKey]
(
@Length int,
@Key nvarchar(MAX) OUTPUT
)
AS
DECLARE @RandomID varchar(32)
DECLARE @counter smallint
DECLARE @RandomNumber float
DECLARE @RandomNumberInt tinyint
DECLARE @CurrentCharacter varchar(1)
DECLARE @ValidCharacters varchar(255)
SET @ValidCharacters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
DECLARE @ValidCharactersLength int
SET @ValidCharactersLength = len(@ValidCharacters)
SET @CurrentCharacter = ''
SET @RandomNumber = 0
SET @RandomNumberInt = 0
SET @RandomID = ''
SET NOCOUNT ON
SET @counter = 1
WHILE @counter < (@Length + 1)
BEGIN
SET @RandomNumber = Rand()
SET @RandomNumberInt = Convert(tinyint, ((@ValidCharactersLength - 1) * @RandomNumber + 1))
SELECT @CurrentCharacter = SUBSTRING(@ValidCharacters, @RandomNumberInt, 1)
SET @counter = @counter + 1
SET @RandomID = @RandomID + @CurrentCharacter
END
Set @key= @RandomID

The reason I bring this to light is that it's become very popular to use GUIDs (newid()) as a primary key today. However, the GUID is QUITE LONG. If you know that you may only ever have say, 10 million rows, you can use a method like the above to generate unique keys that are much shorter.

With the use of "Rand()" you aren't guaranteed that what you get back will be absolutely unique as is the case with a GUID. So, the best bet is to have your stored proc "Look up" the generated key in the table where you intend to use it, and ensure it is unique. If not, you would simply execute the sproc again. If your inserted "key" is in a Primary Key or unique index column, you would get back an error on the insert that tells you to generate another key. Also, with this you want to use the Collation order "CS" - Case Sensitive.

I use a technique like this (although not with SQL) to generate the "short urls" for my ittyurl.net site.

4/13/2007

Musings About Software Pricing

Do you believe that much of the commercial software you see in the marketplace as a developer is overpriced? I'm talking about software that developers buy - tools, frameworks, special-purpose stuff that you could probably write by yourself, but you feel it would be cheaper in terms of your valuable time to purchase it instead?

I muse about this because recently my site partner and I purchased some ad - serving software for our site. We got a discount from the $700 price, but I still thought it was kind of pricey.

Like any developer, the first thing I looked at was "how easy is this to install and configure". The other thing I did was go to the vendor's site and look around.

The first thing I noticed was that there was one of those annoying animated drop-down "in your face" advertisements when their home page loaded. I don't think I have to explain why this tactic immediately puts you on my "do not visit this site again" list. It's tacky, unprofessional, and just downright rude!

The next thing I noticed was that these people had apparently developed this product in VB.Net for ASP.NET 1.1 and the information on their site doesn't reflect the current state of affairs at all. For example, their features state you can use SQLExpress with it as the database, but if you do, you can't use their FullText "keyword search" feature because SQLExpress doesn't support FullText. WRONG! The latest "souped up" version of SQLExpress DOES support FullText, and a lot more, and it's been available for a long time.

The next thing I did was what any self-respecting developer would do - fire up Reflector and take a look under the hood. I noticed two things that really turned me off :

1) The product has only a few stored procedures. 90% of the SQL code in embedded in the assembly as textual SQL. That's nowhere near as efficient as stored procs. Probably they did this to support OleDb providers, but the fact that you take delivery of the product "locked into" this inefficient model, which you cannot change, really pisses me off.

2) All their ad serving is done via ASP.NET PAGES - instead of more efficient ASHX WebHandlers - and those handlers should be ASYNCHRONOUS to boot! If you are writing software that needs to serve advertisements or images, and there is no need to show a "Page" - then you need to get rid of all the baggage of the ASP.NET Page class for speed and scalability - that's what ASHX WebHandlers are for. Apparently this was either too much trouble for these blokes, or they just aren't sophisticated enough to know about it.

3) The product does not seem to be open to any plug-ins or extensibility. At least, I didn't see any way you could. What you bought is what you're stuck with. If you need a feature, there's no way to add it.

4) This product literally has 3 separate logins - admins, advertisers, etc. They made NO EFFORT to upgrade this to the ASP.NET 2.0 Membership, Profile and Role model, which is much more efficient and extensible. ASP.NET 2.0 has been around a long time now, and these people never put in any time to bring their app up to current technology.

On the plus side, I will say that their database schema and logic is pretty sophisticated. But when you couple this with their crappy ASP.NET full-page delivery system and text SQL instead of stored procs, frankly, it's like putting a Ferrari engine in a Volkswagen; it just doesn't compute for me.

Now how much would I REALLY pay for software like this? You know what? It would frustrate me so much, I'm not sure I would buy it at all - no matter what the price. I suppose if they gave it to me complete with source, and I had the time, I might take a few weeks and completely overhaul and upgrade it, since I believe there is a big gap in the market for a quality, mid-range price ( say, $100 -$200) ASP.NET ad server product. But it isn't my software, so why should I have to pay somebody to get what I believe is an inferior, overpriced piece of software and then have to spend my valuable time just upgrading it to meet my standards?

I understand marketing - normally, 40% or more of the price of a product is the cost of marketing it. The problem is - if you hype the hell out of your crappy product and overprice it to compensate, in the hopes that "some" people will buy it, you haven't helped people like me any!

Like most ASP.NET developers in my caliber, I am particularly discriminating. I do not mind paying market value for quality. But - I DO NOT like being fooled by being hyped about how great some piece of software is, only to purchase it and find out that it is not "up to grade".

This isn't scientific, but I'd venture a guess that somewhere around 70 percent of all the software, tools, controls suites and such that we developers (and our corporate employers) purchase is grossly overpriced, and another 15 percent is moderately overpriced. That leaves about 15 percent that's fairly priced in the marketplace. I think there's some real room for improvement here!

If your product is good, there is a magic "best price point" at which you can make the maximum profit over time. This can only be found through diligent study of the competition and the marketplace. The market doesn't care how big your development team is, or how much you've had to pay to get their talent, nor does it care how high your office rent and other expenses are.

The software market is rife with overblown, over-hyped and OVERPRICED software. Caveat Emptor, Developer!

4/12/2007

New! SiteMap xml AutoDiscovery with Robots.txt

Apparently Google, Yahoo and MSN all getting together about agreeing to use the Sitemap xml format to index your web site is having some good fallout.

They've all agreed to look at your robots.txt file (which all crawlers look for) and you can now point to your sitemap url from there, and they will happily chew upon it!

To do this, simply add the following line to your robots.txt file:

Sitemap: http://www.example.com/sitemap.xml

You need to provide the complete URL for your Sitemap on this line. They will pick it up --wherever you put it in your robots.txt file. This directive is not specific to user-agent. If you have multiple Sitemaps, you can point to your Sitemap index file on this line.

Details about the Sitemaps protocol including this addition are available on the protocol website here: http://www.sitemaps.org.

The Google sitemap invention and protocol is a great SEO tool for your web site or blog. We have used this on our eggheadcafe.com site since the inception of sitemaps. On my IttyUrl.net site, i actually have a page that reads and caches my own autogenerated sitemap xml and turns it into a "page of links" - just so non-sitemap bot crawlers have something to consume.

Now that MSN, Yahoo and Google are all digesting this stuff, you've got yourself a triple with the same amount of effort as just getting on to first base.

4/10/2007

How to use Word and Excel in ASP.NET: Don't!

I have seen so many of these that it just makes me shake my head: "How can I use Excel on IIS in ASP.NET (or Word, or any Office program)"....

The answer is, you can try, but it is neither supported or recommended. Here is why:

1.User Identity: Office Applications assume a user identity when they are run, even when they are started via Automation. They attempt to initialize toolbars, menus, options, printers, and some add-ins based on settings in the user registry hive for the user who launches the application. Many services run under accounts that have no user profiles (such as the SYSTEM or IWAM_[servername] accounts), and therefore Office may fail to initialize properly on startup, returning an error on CreateObject or CoCreateInstance. So, right off the bat, you've got a real problem, OK?

2. Interactivity with the Desktop: Office Applications assume that they are being run under an interactive desktop, and may in some circumstances need to be made visible for certain Automation functions to work properly. If an unexpected error occurs, or an unspecified parameter is needed to complete a function, Office is designed to prompt the user with a modal dialog box that asks the user what they want to do. A modal dialog box on a non-interactive desktop (your web server) cannot be dismissed, which causes that thread to stop responding (hang) indefinitely. That's why trying to do what you are doing (e.g., run Excel from an ASP.NET page on your webserver) is NOT SUPPORTED.


3. Reentrancy and Scalability: Server-side components need to be highly reentrant, multi-threaded COM components with minimum overhead and high throughput for multiple clients. Office Applications are in almost all respects the exact opposite. They are non-reentrant, STA-based Automation servers that were designed to provide diverse but resource-intensive functionality for a single client. In sum, the threading model is completely inconsistent with ASP.NET. Even if you do get it to work, you have essentially "shot yourself in the foot" from a scalability perspective.

4. Server-Side Security: Office Applications were never intended for use server-side, and therefore do not take into consideration the security problems that are faced by distributed components. Office does not authenticate incoming requests, and does not protect you from unintentionally running macros, or starting another server that might run macros, from your server-side code. Based on the security settings that were last set, the server can end up running macros under an Administrator or System context with full privileges -- and compromise your network. Let's simplify the above: How would you like it if your ASP.NET application loaded a Word document that a user uploaded, which would promptly attempt to delete all the files on your webserver's C:\ drive?

There are a number of excellent components by third party vendors that were desigined to avoid these and other serious issues, and the Office Web Components installation from Microsoft does so as well.

Finally, besides the technical problems, you need to consider the feasibility of such a design with respect to licensing. Current licensing guidelines prevent Office Applications from being used on a server to service client requests, unless those clients themselves have licensed copies of Office. Using server-side Automation to provide Office functionality to unlicensed workstations is not covered by the End User License Agreement (EULA).

In sum: Don't waste your time. I didn't "come up" with the above information, most of it is found in several KB articles on the subject. All I did was distill it into a more easily digestible form.

And don't post to newsgroups asking for help, because usually, the above is what you'll get as a response! If you need Word, Excel or Powerpoint functionality in your ASP.NET application, use OWC or a third - party component that was designed for this purpose.

4/07/2007

How to Delete All the Stored Procedures in a SQL Server 2005 Database

I've been going through the learning curve with CodeSmith and the initial results are pretty interesting, especially with the free NetTiers template set. Man, does that generate a bunch of stored procs, entity and domain objects and controls! If you get used to the model, you are virtually going to get yourself an entire application in one 5-second CodeSmith "Swoop"!

One of the things I came up with while monkeying around with the Database schema was the need to delete all the generated stored procs so CodeSmith can be pointed back at a "procedure-less" database for another take.

The problem is you don't want to just select everything with type 'p' from SysObjects - because there are system procedures there such as for diagrams. Also, you cannot just do an ad-hoc delete, because you'll get an error message; Sql Server is trying to prevent you from shooting yourself in the foot.

Here is an easy way to do it:

First, right - click on the query pane and choose "Results to text".

Next, execute this script:



Select 'Drop Procedure ' + name from sys.procedures Where [type] = 'P' and is_ms_shipped = 0 and [name] not like 'sp[_]%diagram%'

What you'll get is a nice list of "Drop Procedure" statements that you can paste into the query editor window and execute.

Voilà! All those nasty stored procs are gone. (Or as one of my redneck friends would say, "Walla! Dose procs done left the buildin' , man!")

4/05/2007

Er, Ms.Secretary Pelosi? How about it?

House Speaker Nancy Pelosi provided a good example yesterday why members of Congress should not attempt to "help out" the Secretary of State when traveling abroad.

After a meeting with Syrian dictator Bashar al-Assad in Damascus,Pelosi announced that she had delivered a message from Israeli Prime Minister Ehud Olmert that "Israel was ready to engage in peace talks" with Syria. She added that Mr. Assad was ready to "resume the peace process" as well.

The problem: The Israeli prime minister said no such thing. In fact, Mr. Olmert told Ms. Pelosi that "a number of Senate and House members who recently visited Damascus received the impression that despite the declarations of Bashar Assad, there is no change in the position of his country regarding a possible peace process with Israel." Ms. Pelosi not only misrepresented Israel's position but was virtually alone in failing to realize that Assad's statements were propaganda. Mr. Olmert specifically told Pelosi that he thought her trip to Damascus was a mistake. Apparently, Pelosi, who seems to think she's "on a roll", didn't get the message.

President Bush criticized Pelosi for visiting Damascus at a time when the administration has frozen high-level contacts with Syria. Bush said that thanks to the Speaker's "freelancing" Assad was getting mixed signals from the United States. Ms. Pelosi responded by pointing out that Republican congressmen had visited Syria without drawing presidential censure. That's fine, but those other congressmen didn't try to introduce a new U.S. diplomatic initiative in the Middle East. And - they're not the Speaker of the House.

The real issue here is the attempt by a congressional leader to substitute her own foreign policy for that of a sitting president. The party involved (Democrat, Republican) is not germane to the issue. Two weeks ago Pelosi rammed legislation through that would strip Bush of his authority as commander in chief to manage troop movements in Iraq. Now she wants to introduce a new Middle East policy that directly conflicts with that of the president.

Now Sen. Harry Reid, along with other Democrat leaders, is threatening to introduce a bill that would completely defund our troops by March 2008. This is in direct contradiction to Reid's statement of November 2006, when he firmly stated: "We're not going to do anything to limit funding [for our troops] or cut off funds!"

It's bad enough that we've got a real "loose-cannon" hot-shot for Speaker of the House. The Speaker of the House presides over the House of Representatives, that is all they are supposed to do. The office is not Secretary of State, it's not the Cabinet, and it certainly isn't the Oval Office. But now Ms. Pelosi has also demonstrated that she is a fool. Let Secretary Rice handle this. She's probably fuming, since she's been remarkably quiet about the whole thing.

4/03/2007

Making your assembly run "as Administrator" in Vista

This came from one of my favorites in the C# newsgroup, Willy DeNoyette. I'll simply post the questions and answers directly, since there is no need to modify it except for some formatting and cleanup:

Q) I need to restart the "Windows Audio Service" (audiosrv) via C#. I'm using the ServiceController Class to do this.
It is no problem under XP and no problem under vista if UAC is disabled.
But with enabled UAC i'm getting a "access refused" exception.
I also tried to do it via console with "net start ..." but the same error appears.
Three questions:
1. Is it possible to restart the "windows audio service" if UAC is
enabled ?

A) Yes when running as full "Administrator". That is start the console (cmd interpreter) by right clicking "Run as Administrator".

2. Why does the exception occur? If I do some other stuff, e.g. starting regedit via Process.Start() the user gets asked if he really wants that. I would expect the same behaviour for restarting
services.

A) The exception occurs because you are running as a standard user, only admins can start, stop .... services.
If you want the same behavior you'll have to insert a "manifest" in your executable file.

<?xml version="1.0" encoding="utf-8" ?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" >
<assemblyIdentity version="1.0.0.0"
processorArchitecture="X86"
name="someExecName"
type="win32" />
<description>Program description</description>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" />
</requestedPrivileges>
</security>
</trustInfo>
</assembly>



To add above manifest to the executable assembly, you have to run mt.exe like this:

mt -manifest somename.exe.manifest -outputresource:somename.exe;#1

PS change the someExecName and Program description to suit your needs...

3. If it's not possible at all: Can I find out programmatically
whether UAC is enabled?

A) See above

To further clarify:save the above manifest in a file called "some.exe.manifest", where someApp is the name of your executable file. Say you have "audioCntrl.exe", then you could name your manifest "audioCntrl.exe.manifest" and run mt.exe like:

mt -manifest audioCntrl.exe.manifest -outputresource:audioCntrl.exe;#1