Darrell Hawley: Home Page

Thursday, October 26, 2006

Search Engines, IE7 v Firefox, Grok Talks and Congrats to Josh

Well it's been 2 weeks since my last post. I know I really need to finish my WSE series, but there are a few items that I think are worth noting.

First, I came across Clusty when someone was critiquing search engine rankings for a website that I did. It does a meta-search using MSN, Ask, Gigablast, Wisenut and Open Directory. What makes Clusty unique however, are the "clusters" of results it displays along the left side of the page. It takes the results of the search and then builds groups (clusters) based on content. Very convenient if one of the clusters happens to center around the search you had in mind. I haven’t had enough time to put this to the test, but my initial impressions are very positive.

Second, Google has a new custom search engine feature. Why do you want to build your own search engine? Well, if you are reading this blog post, there is an excellent chance you are always searching for .NET related items. Sure there is the Microsoft search, but that still is a massive amount of results to sort through. Furthermore, I'm a developer not systems engineer - despite my MCSE certification - so I only want items pertaining to developers. So my first step was to enter "C# VB.NET" into a textbox. Then I decided I like the results I get from msdn.microsoft.com and my website (naturally) so I entered those two sites into another textbox. I didn’t want to search these sites exclusively, so I checked a radio button. And that’s it. I'm still experimenting with this so look for a post on this later.

Microsoft just released the new version of Internet Explorer. I had been using a beta for several weeks and had been very happy with it despite a couple of minor problems. So when IE7 hit the market I downloaded it right away. The most important feature, IMHO, is the separation from Windows Explorer meaning IE does not access your kernel directly. I may take some heat on that statement, but that is my understanding of how this works. Then we get into the feature that makes surfing so much more enjoyable: tabbed browsing. Now instead of having 10 separate IE apps open, I only have 1 with 10 tabs. Much neater.

-pardon for the interuption in flow, but would it make sense to create a browser as an mdi application as opposed to tabs? Maybe a combination of both? hmmmmm…

Naturally, the comparisons to Firefox start. Yes, IE7 looks very similar to FireFox, but then again, how different can 1-inch of real estate at the top of your screen really look? When I was using the beta, I noticed the IE7 started much faster then Firefox, but Firefox seemed to load pages faster. I'm no longer sure that this is the case, especially since fireFox has also updated itself. So among my many projects, I'm comparing the two. Undoubtedly, my opinion will largely be based upon how often I have to shut one or the other down.

I just remembered something else! GANG hosted a grok talk last Wednesday. And I must say that it was probably the worst talk I have ever given. Within 30 seconds of speaking, I realized that I had enough material to last at least 30 minutes, probably longer. John Hopkins, president of GANG and close personal friend, was kind enough to give me 5 additional minutes over and above the 10 allowed to cram as much as I could into the presentation. I had a demo prepared, but because I hadn't timed the presentation, I wasn't sure that i could do it. Live and learn. Thankfully, I did a good enough job to elicit questions from the audience.

For posterity, the speakers were Jason Follas, me, Patrick Steele, Brian Burge (first presentation and a great job at that), Martin Shoemaker (two presentations), Bill Wagner (one of my mentors and the closest thing I have to a boss) and Josh Holmes (the newly instated Breadth Architect Evangelist for the Heartland District).

One last thing. I have not yet publicly congratulated Josh on his new position as the Breadth Architect Evangelist for the Heartland District with Microsoft. Well, congratulations, Josh!

Thursday, October 12, 2006

Locked Out of SQL Express

I got locked out of a SQL Server Express database - as the administrator - the other day. Luckily, i found this post at Chaz Blogs. In summary, open up Sql Management Studio, Click options on the login screen and sign into the Master database. Go to the above post for more details.

Wednesday, October 11, 2006

Extended Property Manipulation Script

Interesting bit of T-SQL here. I wanted to create a script that would allow me to quickly manipulate extended properties in a SQL Server Express database, so I came up with the following. Note that this has been tested on SQL Server Express only, so I can't guarantee you will be able to use this in any other version of SQL Server.

declare @Property nvarchar(20), --Name of extended property to add
@PropertyVal nvarchar(100), -- value of extended property
@Table nvarchar(50), -- table that will be getting extended property
@DropOnly bit -- if set to 1, then extended property will be dropped and not readded

set @Property = 'GenerateObject'
set @PropertyVal = '1'
set @Table = 'User'
set @DropOnly = 0

-- if the property we are looking for already exists, drop it.
if (Exists (select * from ::fn_listextendedproperty (@Property, N'SCHEMA', N'dbo', N'TABLE', @Table, default, default)))
Begin
exec sys.sp_dropextendedproperty @name=@Property,
@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE',
@level1name=@Table
End

-- if the DropOnly flag is not set...
if @DropOnly = 0
Begin
-- add the extendedproperty along with the appropriate value
EXEC sys.sp_addextendedproperty @name=@Property, @value=@PropertyVal ,
@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE',
@level1name=@Table
End

-- no matter what happened above, search for the property. if DropOnly was set, nothing will be returned.
select * from ::fn_listextendedproperty (@Property, N'SCHEMA', N'dbo', N'TABLE', @Table, default, default)

-- list all tables with this property
select * from ::fn_listextendedproperty (@Property, N'SCHEMA', N'dbo', N'TABLE', default, default, default)

Tuesday, October 10, 2006

WSE: Consuming the Service

I created a little application that takes a username and password and then calls the "Hello WSE" webservice I created. For comparison sake I created a method for calling a basic, unsecured webservice using the following code in a button click:


MyWebService.Service service = new Client.MyWebService.Service();
this.Message.Text = service.HelloWorld();


But we want the "WSE way", for crying out loud! As you can see, the amount of additional code required is minimal.


MyWebService.ServiceWse proxy = new Client.MyWebService.ServiceWse();
UsernameToken token = new UsernameToken(this.User.Text, this.Password.Text,
PasswordOption.SendPlainText);
proxy.SetClientCredential(token);
proxy.SetPolicy("MyPolicy");
this.Message.Text = proxy.HelloWSE();


Probably the most complex bit of this code is knowing - I wouldn't even call it understanding - where that ServiceWse() object came from. It was autogenerated! For every WebService you create, an associated "Wse" method (Web Service name with "Wse" appended to it) is generated when you use the WSE Wizard (say that 5 times fast).

That wraps it for the basic WSE stuff. You have a client, a server and the two can communicate using WSE. But are you secure? NO! What I have outlined in this series of posts allows you to send cleartext messages between client and server within the confines of WSE. Now we have to consider encryption before releasing this to this wild.

One last note, I'm going to create a new solution and build a webservice and client from scratch to make sure that the I have covered everything. I'm also worried about a couple of errors that I have run into along the way. My next post is going to cover an error (maybe two) and confirm that, yes, if you follow my directions, WSE will work.

OK. I have another last note. GO TIGERS!!! This life-long Cleveland fan is pulling hard for you.

Thursday, October 05, 2006

WSE: Not-So-Minor Details

I know. So many posts in such a short amount of time. It's crazy. But if you want this to work, there are a couple of steps you still have to take. By the end of this post, the client should be able to connect to the webservice using WSE. It won't be secure yet, but we will have the basis for a secure line of communication. Let's get started.

First let's take a look at a simple webservice that I setup in my sample project.


[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[Policy("MyPolicy")]
public class Service : System.Web.Services.WebService
{

public Service()
{
//Uncomment the following line if using designed components
//InitializeComponent();
}

#region Basic
[WebMethod]
public string HelloWorld()
{
return "Hello, World";
}

#endregion

#region WSE

[WebMethod]
public string HelloWSE()
{
SecurityToken token = RequestSoapContext.Current.IdentityToken;
if (token != null)
{
string Name = token.Identity.Name;
return String.Format("Hello, {0}", Name);
}
return null;
}

#endregion
}


If you go simply add a new webservice to your web project, it will give you the skeleton with all of the absolutely necessary attributes - almost all of them, anyways - in the right places. We just need to add the PolicyAttribute located in the Microsoft.Web.Services3 namespace to the webservice class. We are looking for the attribute that takes the string arguement. What do we put here? Do you remember the name of the policy you entered here? Pass that name - type-friendly, of course - to the PolicyAttribute.


Next, open up you web.config file in the web project. If you followed my directions, you should see something that looks like the following:



<securitytokenmanager>
<add type="WebService.TokenManager, Microsoft.Web.Services3, Version=3.0.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"
namespace="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-
secext-1.0.xsd" localName="UsernameToken" />
</securitytokenmanager>


We need to make this look like this:



<securitytokenmanager>
<add localName="UsernameToken" type="WebService.TokenManager"
namespace="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-
secext-1.0.xsd"/>
</securitytokenmanager>


The localname attribute is the type-friendly name of the token that will be passed to our token manager and the type attribute is the namespace and class of my token manager.



That is the end of the tweaking phase, next we'll setup the client to consume the service using WSE.

Wednesday, October 04, 2006

A Little Off Topic...

I have to thank my wife, Angie, for making me go to see the Barenaked Ladies. It was short - only 6 songs, i think - but a really great time. I was way in the back so didn't have the best possible view, but it was at least as good as 10th row floor seats at your typical concert. Among the playlist were Brian Wilson, Old Apartment and One Week. Definitely a memorable show.

WSE: Custom TokenManager

Before I begin, I just need to say that this is my most interesting blog posts ever. Not because what I am preparing to say is revolutionary, but because I'm blogging while I'm waiting for the Barenaked Ladies to start playing at the Borders in downtown Ann Arbor. Nice!

We have a client, we have a service, now we need to be able to secure the lines of communication. So let's build a Token Manager that will use the previously described database. I'm not going to go over creating the new methods. If you're reading this, I'm assuming that this is old hat. What I did do was to create a method that returns a strongly-typed datatable with all of the account information given a username and password. Check out the code below:




namespace WebService
{

public class TokenManager : UsernameTokenManager
{
public TokenManager()
{
}

public TokenManager(XmlNodeList nodes)
: base(nodes)
{
}


protected override string AuthenticateToken(UsernameToken token)
{
DataAccess.WebDataSetTableAdapters.AccountTableAdapter ta = new
DataAccess.WebDataSetTableAdapters.AccountTableAdapter();
DataAccess.WebDataSet.AccountDataTable dt =
ta.GetDataByUsernamePassword(token.Username, token.Password);
if (dt.Rows.Count == 1)
{
return token.Password;
}
else
{
throw new Exception("SHAME ON YOU, INVALID USER!!!");
}
}
}
}

Is there anything in this code that sends up red flags? To me there is. If the password being sent in the token does not match the string being returned (ie, a password), authentication fails. Nonetheless, I will give this idea some thought before making up my mind. These patterns are well thought out, after all and I can't possibly be the first person to consider this. Next post, getting things to work together.

Monday, October 02, 2006

Really. I was just way too busy...

I'd love to be able to say I was way too busy - or that I was on some grand adventure that involved exotic destinations, brushes with danger and long-lost treasure. But I can't. I was simply avoiding it. Blogging is a lot of work. Take a look at my last few posts. They involve a lot of screenshots which in turn involve a lot of cutting-and-pasting and all-around messing around. Well, once you start avoiding, you start forgetting. And when you remember, you start scrambling for excuses. So I have decided to go ahead and admit that I stink. I stopped blogging because I didn't want to and willingly avoided the advice offered by Bill Wagner (stop blogging and people assume you are dead).

Of course, I have a couple people to thank for bringing me out of my funk. In order of "appearance", Dave Halliwill (Get a blog, Dave, and make sure it's geeky), Josh Holmes and Darryl Whitmore. When Darryl told me he got his own blog "thanks to me", I knew it was time to start posting again. Good luck, Darryl.

As for the WSE thing I was doing, I'm back on it. In fact, I'm trying to throw together an abstract right now for a grok talk on Wednesday, October 18 at Great Lakes Area .NET User Group (GANG). Hopefully, a new post within the next 24 hours. If not, definitely in the next 48.