Thursday, September 14, 2006

Login failures with ASP.NET 2.0 Membership

I sometimes end up with a puzzled look on my face after trying to log into one of my web applications and getting a "login failed" message back despite being sure I've got the username and password right. The usual culprit is that I've forgotten to change the applicationName attribute in the config for the Membership section (explained nicely in a post by Scott Guthrie), but despite checking and re-checking when I had the same problem yesterday, it just wouldn't let me log in.

I started doing some tests, and found that if I wrote the code to do so, it would happily retrieve the password for a given username for me, but if I then used that same username and password in a call to Membership.ValidateUser() it still failed.

To cut a long story short, the problem turned out to be that the transaction log for the database was full, and the disk had run out of space. As such it's one of those rare occurrences that you may never encounter, but as it's rather obscure and there's no indication of what the problem is when the login attempt fails, maybe this post will help someone with the same issue one day.

Wednesday, August 23, 2006

Changing owner in SQL Server

Given the number of times I've ended up having to search for this and promptly forgotten it 5 minutes later, I thought I'd put this up here so I know where to find it.

In order to change the owner of an object in SQL Server, use something like the following:

sp_changeobjectowner 'Database.dbo.Table', 'newowner'

Monday, July 31, 2006

Resolving links from the application root

One of the things that I've got used to taking for granted is the ability to use the tilde (~) to specify the application root when specifying a link, in a HyperLink control, for example. Having recently ventured into the realm of writing my own controls I need to parse links like this for myself.

A quick Google later and it looks like the Control.ResolveUrl() method is the way to go, although as an aside, there appears to be a new Control.ResolveClientUrl() method in 2.0 as well. The docs don't really go out of their way to explain the difference as far as I can tell, but from my own tests it would appear that the former will provide an absolute path (using the TemplateSourceDirectory property according to the docs), whereas the latter will give you a relative path.

Quick example:
From a page at /WebApp/dir/page.aspx that wants to create a link to "~/otherdir/link.html":

ResolveUrl() gives: /WebApp/otherdir/link.html
ResolveClientUrl() gives: ../otherdir/link.html

Thursday, June 08, 2006

Databinding with a LoginView inside a FormView

No posts at all in April and now two within a day. Go figure.

I'm not sure if the title I've picked is the best way to describe this but it'll do. I've been using a LoginView within the ItemTemplate of a FormView to determine what the "available actions" are for a page. Here's an example:

This works fine when first coming into the page. The LoginView picks out the right template depending on the user's role, and when my Application object is databound to the FormView, the visibility of the individual buttons is set correctly. (Note that this is my own custom Application object, nothing to do with the framework.)

However, all is not well when making some changes to the application elsewhere on the page and then rebinding the FormView (i.e. this time we're dealing with a postback). This time, the LoginView fires its ViewChanging and ViewChanged events. I guess technically it's correct, as what I'm looking at on the page (i.e. my "view") may have changed if the various button visibilities have changed. However, my role hasn't changed, and hence the template the LoginView is using hasn't changed, which is kind of what I was expecting the ViewChanged event to mean.

Anyway, the problem comes in that somewhere in the middle of this "ooh, my view's changed" moment that the LoginView has, it blats its control hierarchy and recreates it, only this happens after the FormView was databound, and thus all the button visibilities are lost, resulting in them all going back to their default setting.

My workaround for now is to perform a Response.Redirect() and let everything create itself from scratch again as the way my page is setup allows this without any problems. However, if you need to remain within the context of a postback, I suggest using something like a MultiView instead of a LoginView, and manually set the correct view in there yourself at an appropriate time.

Suggestions for better solutions are, as always, welcome.

Wednesday, June 07, 2006

NextStepIndex in a Wizard control

I've been using one of the new(ish) 2.0 Wizard controls in a project and it's been working nicely. That is, until I wanted to change it so that for one of the steps, you could leap out to a different page, update some other stuff, and then leap back in again to the step you were at before.

When coming back to the page and starting off at step number 2, I found that clicking the previous button didn't take me to step 1 as I expected (and wanted). A quick bit of breakpoint-setting and debugging later, I found that in the event handler, the NextStepIndex wasn't 0 (i.e. the first step), it was 1. Thus clicking the previous button simply left me on the second step.

This actually makes complete sense when placed in context, which a post on this thread was able to do for me. It's not previous in the sense of the last physical step as laid out in the .aspx file; it's previous in the sense of the last step in the history of your moves through the wizard. Since I was effectively starting off with a fresh copy of the wizard when coming back to the page, there was no history, and thus there was no previous step for me to go back to.

In the end, the solution is simply to specify what step you want next based on the CurrentStepIndex in the relevant event handler. Simple!

Monday, May 15, 2006

Membership configuration in ASP.NET 2.0

Fine work on the documentation for this one. The documentation for Membership.MinRequiredNonAlphanumericCharacters suggests that the attribute in the <add> element when defining a provider should be minAlphanumericCharacters, or alternatively minRequiredNonAlphanumericCharacters, depending on which bit of the page you read.

In fact neither of these work, and you should use minRequiredNonalphanumericCharacters instead.

Friday, March 17, 2006

UK Postcode Implementation

I've been meaning to put this up here ever since the day after my post about regular expressions but time has eluded me until now. I had a stab at coming up with some code for a postcode to save doing the same old checking (or alternatively none at all!) every time; let me know what you think.

Friday, February 24, 2006

Undocumented regular expression pattern

UK Postcode validation is the theme for me today, and the standard has been very useful. Digging a little deeper even provides a couple of regular expression patterns for doing the validation with, both a simple one and a more complicated one.

Examining the patterns has led me to a construct that I can't find documented anywhere. I've looked through all the linked pages in the "Regular Expression Language Elements" section in the VS2005 help, but with no joy. It seems to work though.

[A-Z-[CIKMOV]]

Fairly self-explanatory hopefully, with this particular example matching any one of twenty capital letters. If it is actually documented somewhere, please do point me at it.

Thursday, February 23, 2006

Multiple keys with KeyedCollection

I'm currently dealing with some objects that have two different unique identifiers. One is a public, user-friendly identifier, and the other is an internal, essentially meaningless one. Meaningless, that is, other than the fact that I can ensure that it stays the same for all time, as opposed to the one that users can see, which therefore will no doubt need to be altered 30 times as random punter X changes their mind yet again.

As a result I wanted a collection where it's possible to grab an item quickly and easily using either of the identifiers. Deriving from KeyedCollection<TKey, TItem> does the job nicely for a single key, so I thought I'd extend that a bit farther and come up with my own cunningly named DoubleKeyedCollection<TKey, TSecondKey, TItem>.

To my shame, I've not even tested this code before posting it up here as it's already long past the end of the day, although it does compile, which is always encouraging if nothing else. I'm not hugely fond of the choice of GetItem() as a method name as it's a bit ambiguous, especially if your two keys are of the same type. GetItemBySecondKey() seemed a bit meaningless to an end client using a class derived from DoubleKeyedCollection though. Any thoughts on the subject are welcome (as is notification of any blatant errors that I've managed to completely overlook).

As an aside, I think I'll be examining the possibilities of changing the layout of this page. The narrow column doesn't exactly lend itself to code listings. I've done what I can to make it readable. EDIT: Template now changed - not as pretty imho, but makes the code a lot easier to read!

Thursday, February 09, 2006

Multiple search patterns with DirectoryInfo.GetFiles()

Another visit to Google today showed various requests about how to specify more than one pattern to search for when grabbing the files from a directory, so for example, get all the .mp3 and .wma files in one call.

As far as I can see, you can only specify one pattern at a time (unless there's something new in 2.0 that I've missed) so I thought this was a good candidate for a simple wrapper. The code below should be fairly easy to modify if you have any specific requirements in your situation.

FolderBrowserDialog.ShowNewFolderButton

A quick Google will tell you that this has been discussed plenty of times before, but seeing as I stumbled across it of my own accord today, I thought I'd give it a mention.

Set the property (the title of this post) to false, then display the dialog on a Windows 2000 machine. Whoops, the "New Folder" button is still there. Oh well.

Apparently it works on Windows XP - I guess you just have to live with it if you're running Win2k.

Saturday, January 21, 2006

Deploying to a Windows Mobile device

A few months ago I got myself a Dell Axim X50v, convincing myself that it was a "good investment" as I'd be able to look into developing for the Pocket PC. In time-honoured fashion, I've never actually managed to get past a quick "Hello World" program on it, although I did think it was pretty cool the way you could just hit F5 in Visual Studio and up came the app on my PDA.

Anyway, I just decided I'd give it another bash with Visual Studio 2005 (Last time I tried I was using 2003) and upon hitting F5 I got the less than useful message "The configuration data for this product is corrupt. Contact your support personnel". Fortunately, Google is here to save the day again, and I found a post on a message board somewhere saying to close down Visual Studio, delete the directory C:\Documents and Settings\<localuser>\Local Settings\Application Data\Microsoft\CoreCon, and then restart and try again.

Did the trick for me, and I hope it works for you too if you find yourself here on a Google search of your own.

I get the impression that this folder is/was an artifact of an old beta install of VS2005 although I don't know that for certain. If anyone knows for sure where it comes from please do feel free to enlighten me!

Wednesday, January 18, 2006

Serialization and type versions

After stating in my previous post that I write messages in en-GB, I go and ruin that by putting "Serialization" in the title of this one. Go figure.

Another nice addition in .NET 2.0 are five attributes in the System.Runtime.Serialization namespace. These help with telling v2 of a class how to cope when dealing with objects of type v1. The attributes are as follows:

OnDeserializedAttribute
OnDeserializingAttribute
OnSerializedAttribute
OnSerializingAttribute
OptionalFieldAttribute

Read the docs for usage, but essentially if you mark the new member fields in v2 with [OptionalField] then it doesn't fall over when attempting to deserialize an object of type v1, as it knows that the info might be missing. You can then use a method marked with [OnDeserialized] to do sensible things like set a default value for a missing field for example.

Wednesday, January 11, 2006

"Neutral" Resources

The system may have a concept of a "neutral language", but in the real world I tend to write my default messages in a concrete language (which for me is en-GB). When it comes to doing localisation, there's no need to then duplicate the effort and create a separate en-GB resources file - simply mark your "neutral" version with what it actually is.

You can do this with an attribute (in AssemblyInfo.cs), like so:

[assembly: NeutralResourcesLanguage("en-GB")]

EDIT: Should have guessed this already really, but I've just realised that in VS2005 with its new GUI to edit the AssemblyInfo.cs file, this attribute is a drop down inside the Assembly Information page anyway. Simplicity itself.

Tuesday, January 10, 2006

Null coalescing operator

Fancy title to get things going.

This is one of those things that'll be second nature once I start using it in anger, but until I do that, I'll consistently forget it.

C# 2.0 introduces nullable types, and the null coalescing operator (??) is a binary operator that works pretty much the same way as T-SQL's ISNULL() function.

So for:
a ?? b

think:
ISNULL(a, b)

One small caveat here is that b could of course be a nullable type as well, in which case the result of a ?? b is still a nullable type. If it's not, the result isn't either. See example below (ripped from C# 2.0 spec).

int? x = GetNullableInt();
int? y = GetNullableInt();
int? z = x ?? y;
int i = z ?? -1;

First post

I figured it was probably fairly obligatory to have a "first post" post. So here it is. At this point I have absolutely no idea if I'll continue this blog beyond the initial novelty value length of a day or two.

Essentially my only motivation for doing this is as a repository for little tidbits of info I find out whilst wading my way through the world of .NET programming, as I've lost count of the number of times I've thought, "I remember reading about how to do that... now if only I could find it..."

With any luck if I convince myself to dump it in here then I'll be able to find it again later. So if you've got no interest in programming, look elsewhere. I don't feel the need to share with the world what I had for tea last night, who I babysat for at the weekend, or why I'll be choosing gloss rather than matt paint for decorating.

Enjoy.