Thursday, April 09, 2009

Tweet Delete?

Ack! all of my twitterings since over a month ago have disappeared!

I feel lost! They were only silly irrelevant mutterings for the most part, but they were my silly irrelevant mutterings and I trusted you to store them!

I have logged a ticket with twitter, hopefully they will return from the void…

Wednesday, April 08, 2009

Page.IsAsync broken on ASP.Net MVC

I was just trying to add a condition to my validation code so it would not run when the page was asynchronously posted (my controls were getting highlighted as an error before the user has even had the chance to enter any values because of some ajax that was updating another area of the page), but I found that the Page.IsAsync member is always false.

I managed to find another member that you can access via the ScriptManager:

ScriptManager.GetCurrent(Page).IsInAsyncPostBack

Which seems to work.

Wednesday, March 18, 2009

TextChanged event of TextBox not raised by the Internet Explorer AutoComplete feature

As noted in this msdn article, The TextChanged event of a TextBox control may not fire if the AutoComplete feature is enabled in Internet Explorer. And it appears to be “by design” – I hate that.

Fortunately, it is pretty easy to add some JavaScript to make the ‘right thing’ happen.

All you need to do is raise the onchange event at the appropriate time. For me that is when the TextBox loses focus. As I am doing this from code behind (as usual) I am registering a client script, then when I add the TextBox I set its onblur attribute accordingly:

Page.ClientScript.RegisterClientScriptBlock(typeof(FormPage), "RaiseOnChange", "function RaiseOnChange(ctrl){ctrl.fireEvent('onchange');}", true);
tb.Attributes[HtmlAttributes.OnBlur] = string.Format("RaiseOnChange({0})", tb.UniqueID);

The server side TextChanged event only gets raised if the TextBox.Value has really changed. I needed to do this because I am using the TextChanged event of some TextBox controls to trigger an asyncpostback to update an UpdatePanel. The code that sets the content of the UpdatePanel is in the server side TextChanged handler.

Friday, March 13, 2009

Quoted strings

I posted something about this once before, but having just given myself a headache trying to fix something similar once again I feel like writing some more.

Using the quote delimiter character inside of a quoted string at always a minor problem. There are two ways you can fix it – you can escape the quote using whatever method is valid at the time* or you can change the type of quote delimiter, i.e. you can switch from " to ' or vice-versa. There is a deeper problem though that is only really seen when you are not just embedding a delimiter in a string, but (as seems to be often the case with web development) when you are passing such a string to someone or something else. Say for example you are writing ASP.Net code behind to output a __doPostback where one of the arguments is a string with an embedded delimiter. The string in .Net code will be delimited (say with ") then the argument to __doPostback will also be delimited (say with ') but then the data in that string might contain ' (e.g. O'Neil) which will have to be escaped.

My exact situation this time was slightly more complicated still – I have three levels of indirection! I am in c# code behind, setting the .Text property on a Telerik DataGridItem to be an html anchor tag which will do a postback. So the .Net string is delimited (with " naturally), the onclick of the a tag is delimited (with " also by convention, so escaped for .Net as \"), the argument to the __doPostback function is delimited (with ' because there is no way of escaping nested " characters for html) and finally the data in that argument might have ' characters so it needs to be escaped (by \')! And certain parts need to be UrlEncoded also, but before you put in the \' escaping or else you will UrlEncode the \ character. *Hum*

item[colName].Text = string.Format("<a href=\"#\" onclick=\"__doPostBack('', '{1}{0}{2}')\">{3}</a>", QueryString.PostBackArgSep, postbackType, item[colName].Text.Replace("'", "\\'"), item[colName].Text);

* Mmm, yes. Whatever method is valid at the time. This is not always straight forward with some situations calling for \ to give \' or \", some for a doubling up of the offending character giving '' or "", or even for escaping to be impossible in the current context, leaving you with only the ability to switch delimiters. This last problem with why I try to stick with " as the delimiter most of the time and escaping where required rather than the simpler change to ' so as to save the other character for situations where it is the only method (e.g. html). I think that it is probably possible to get yourself into a situation where there is no possible way to pass the string ‘down the line’ as it were without breaking something. If that happens either you need to encode and decode the whole string somewhere, or admit that you are doing something the hard way and find the right way to do it… I almost think that is what is going on here with my current problem – I think it could be solved by keeping the information that I am passing through to __doPostback somewhere else and just passing a key to it to the code I am calling, but I don’t have the time to do that right now, and this form will be soon superseded by an ASP.Net MVC version.

Wednesday, March 04, 2009

Virtual Root (~) gives 404 error

We had a server reboot after a power failure yesterday, and this morning an ASP.NET application that has been working for months started giving this error:

Server Error in '/' Application.

The resource cannot be found.

Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable.  Please review the following URL and make sure that it is spelled correctly.

Requested URL: /~/direct.aspx


Version Information: Microsoft .NET Framework Version:2.0.50727.3082; ASP.NET Version:2.0.50727.3082

Seems to me that it is not translating the ~ into the Application Root path, but I am at a loss as to why. I have posted a question about the ~ virtual root giving a 404 on the ASP.NET newsgroup, but as is often the case with these WTF kind of posts I am not really expecting a response…

It was easily ‘fixed’ by just making the form action use the absolute path to the aspx file, but I want to know why it is broken.

Tuesday, March 03, 2009

Telerik RadUploadProgressHandler and ASP.NET MVC

Just ran into a small problem with the Telerik radUpload control and ASP.NET MVC.

The upload progress needs to have a httpHandler and httpModule configured in Web.config for it to work correctly – I think it is that which handles the GUID that it tacks onto the end of the url to maintain state (among other things). The path is normally Telerik.RadUploadProgressHandler.ashx but with MVC this will be routed to a controller and the handler will not be found.

I have added an exclusion to my Global.asax.cs file and it seems to work.

routes.IgnoreRoute("Telerik.RadUploadProgressHandler.ashx/{*pathInfo}");

Remains to be seen if this is the right way to do it or if there is anything else wrong, but for now I am just trying to get two existing web applications merged together as one MVC application. A lot of the stuff that those apps are doing is not “correct” from a MVC point of view, but this is version 0.9 :)


[Edit] Meh. Don’t need to do that. There are instructions on the Telerik site for how to configure the httpHandler for RadUpload under ASP.NET MVC

Shake to do something

What? That has to be the most stupid interface trick that I have ever heard of. Why the hell would I want to shake my iPhone to delete the current entry or shake it to start the recording? Jeebus. Perhaps if it was really sensitive and the shaking was totally in context with what you are using the device for, but shake to delete a database entry? That is just a stupid gimmick!

Monday, March 02, 2009

More iPhone icons

I am not quite happy with the template that I made for these icons… The corners are not quite right. But at least the first page of my applications all are about the same brightness now, and they all have the same border look. One for Twittelator* and one for gNotes:

Twittelator gNotes

Next!


* The channels of the png are in the wrong order, or a different order, or something on the iPhone so you have to use fixpng or something to fix it before you can open it for editing… but that seems to modify the colours (fair enough I guess, you are changing the channels…). I thought it was just a straight negative, but I don’t think it is. Rather than fiddling too much though, I quite like the colour of the Twittelator one as it is – better than the aqua and purple one that is the default anyway.

iPhone themes…

Wow, there are a bunch of themes out there for WinterBoard etc.

I am using iGlassSol which is very nice, but there are a couple of things I didn’t like. The clock could have a better time on it, and there was no icon for WideEmail. So I made some:

Clock WideEmail

The other thing that I made was a new dock with 5 icons on it… but it seems like there is a way to make it generate the glassy looking dock on the fly… but I can’t find it, only forum posts talking about it. Anyway, the dock (with WideEmail as the extra icon):

SBDockBG

Fun.

Tuesday, February 24, 2009

Call a method on an object only when that object is not null

I have often wanted an operator or something that will do something like run a method on an object if that object is not null (returning a default value if it is null). An example:

string s = SomeClass.SomeMember.ToString(); 

maybe for output or something. Now this works just fine, unless SomeMember happens to be null, when this code will throw an exception. So the code has to become:

string s = SomeClass.SomeMember != null ? SomeClass.SomeMember.ToString() : ""; 

or something like that. Upon finding the ?? ‘null coalescing operator’ I thought that would do the trick, but that will only munge the ToString (say) return value to "" if it was null, not let you call members on a null reference. You could do something with a chain of ?? operators, but that looks nasty and if anything in the chain is actually a method call rather than a property access then it may be called multiple times…

I think that I have come up with something neat and simple that works.

public static TResult Try<T, TResult>(this T left, Func<T, TResult> func) { 
    return Try(left, func, default(TResult)); 
} 
 
public static TResult Try<T, TResult>(this T left, Func<T, TResult> func, TResult defaultValue) { 
    if(left != null) { 
        return func(left); 
    } else { 
        return defaultValue; 
    } 
} 

Which can be used like this:

string s = SomeClass.SomeMember.Try(m => m.ToString(), ""); 

I named it Try in reference to functions such as TryParse. Perhaps not the best choice of name, but I am pretty phenomenally bad a choosing names for things… If you use it on a null reference you will get back the default value you specify or if you don't specify one you get the default value of type of the lambda expression. This second case (not specifying the default explicitly) is more useful when the type is not nullable... It is useful for calling functions on members of a class that might be null. More than that of course though, as that is a lambda (well actually a Func<T, TResult> Generic Delegate which is most easily populated with a lambda) you can pretty much do whatever you like in there.

Now I understand that this is not for everybody and that it is not going to work in all situations. Sometimes a null return value will not always have the same meaning as the default value for that type, but if you keep this in mind to does clean up a lot of code.

Another example to illustrate:

public class DataObject { 
    public List<string> Strings; 
} 
 
DataObject myDataObject = new DataObject(); 
// int stringCount = myDataObject.Strings.Count; // *boom!*
int stringCount = myDataObject.Strings.Try(l => l.Count); 

So this does not give you all of the same information that you get from receiving the null value, but it makes some common stuff painless, like telling the user how many strings there are. I find myself hiding the null value a lot of the time anyway, converting it to "" or 0 or whatever, so there you go.

Real world ‘improvement’. This:

object obj = ExecuteScript(script);
if(obj != null) {
    return obj.ToString();
} else {
    return "";
}
Becomes this:
return ExecuteScript(script).Try(o => o.ToString(), "");

Incidentally, I really love how well the type inference works now. There is no need to specify the types when calling the function - like myDataObject.Strings.Try<string, int>(l => l.Count) - and the return type gets updated when you add or change the return type of the lambda expression. Very neat.

A little love for Windows Live Writer

Problem solved.

There was some odd “bug fixing” stuff in the blogger theme.

.post-body p {
  line-height: 1.4em;
  /* Fix bug in IE5/Win with italics in posts */
  margin: 0;
  height: 1%;
  overflow: visible;
}

This was confusing WLW a bit obviously. I just removed this (sorry no more support for IE5 *pfft*) and all is well. the problem that I thought I was going to have with the empty p tags between each paragraph that I was getting but do not get when WLW is working properly is a non problem. The actually empty tags: <p></p> are not rendered at all, only the tags that WLW was inserting: <p>&#160;</p> with that non breaking space in there were causing the blank paragraph to be given some space – and these are not generated when your CSS is okay.

So everything work as far as I can see. Looks like a real WYSIWYG editor now. I can click anywhere, I can insert lists, I can probably stop checking the mark-up like a freak…

Thanks Joe Cheng! You rock.

Sunday, February 22, 2009

Bad Xml – to accept or to reject, that is the question.

Was just reading this post which touches on accepting invalid Xml communications. And I agree.

I think it boils down to “make sure you produce good XML, but accept anything with the proviso that there may be odd behaviour if the format is not correct”. Library wise though, permissive reading is fine, but if your library produces bad XML you deserve to be stamped out. I have to say that the Microsoft Xml stuff is really pretty good. They are an option 1 library though, so don’t expect to be able to read in any old just, but they will not produce invalid Xml*.

This is the route that I have gone with all of the stuff that I have been doing lately. It is a little more complicated than that though because the data structure that I am using is created from the DTD** so I need to not only accept invalid XML but convert it into valid XML to store it.


* This is something that I have had to explain a few times… Sometimes is is difficult, sometimes people understand. Mostly I don’t bother complaining too much about receiving nasty Xml, but forcing myself to produce bad Xml because someone’s hand coded parser reacts badly to something valid in my valid Xml (namespace definition).

** Funny story. It’s their DTD, but they can’t manage to produce Xml that validates against it, and they expect values for certain elements that are not valid under it (value="" when value is an NMTOKEN). Chuckle…

WLW tag problems

After looking at this post from someone with formatting problems in WLW, I have switched WLW into editing without the template. Looks nasty, but the mark-up is nice.

Only problem is that now it does not put a blank p tag in between each paragraph. So I would go and change the template to add some margin to the end of a paragraph to get my spacing back but then that is going to stuff up all of the old posts! Ugh. I do not want to go back and edit them all again! I already did that once…

It would be nice if I could modify the tag that WLW puts in for a paragraph to include a class attribute – that way I could modify the template so it only affected these new posts… Actually, that is something that is a bit of a problem with Blogger in general – changes take effect on all old posts. E.g. if you change the time zone. Not much you can do about that though really.

Just store it for me

This is an interesting article: untitled document syndrome

In the past I was firmly in the “no, I really do want to specify where you are putting my file” camp, but increasingly I prefer to succumb to human nature and let someone else do it for me.

I still like to be able to configure the root of the storage. For example to put it into my svn working copy so I have a backup and can get at it from other machines. But once that is done, and as long as I can actually find the files somewhere should I want to, I do quite like the way iTunes (for example) just takes what you put into iTunes and stores it for you.

It would be nice if more applications did this. It might be nice if this was some king of system service that an application could use. I think a lot of my applications could benefit from this – it is certainly true that for most business users the location (or the very existence) of the actual file is of little importance, as long as they can find the work and get it back and use it. You only have to look at some people’s machines and the places they manage to get files saved to realise that most people either don’t know or don’t care that there is even a choice to make about the directory they save a file in.

Saturday, February 21, 2009

Login or Register

When you have a site that uses user accounts, say for returning customers, I really hate the common theme of having a login fields area and a register fields area.

Mainly because I can’t always remember if I am registered or not. Why not make the forms do double duty as login and registration forms? You put in your email address* and what you think is your password and hit the button. If that user exists and the password is correct, let me in. If that user exists and the password is not correct, bounce me with a message. If that user does not exist, go on to a registration page and get the rest of my details**, and keep the hash of my password so you only have to confirm it not get me to type it twice again.

Streamlined. The only thing that I can see that is wrong with this idea is that it does give away some information, namely the form tells you that a certain email address is registered on that site. However the existing registration form does that anyway so…


* I am pretty much a believer in the email address as username idea. There is never going to be a problem with your desired username being take already, and people who complain that they have too many email addresses or they change them often or whatever… pfft.

** Or better yet – don’t ask me for any more information, just to confirm the password. Oh, and make sure I can continue on with what I was doing.

Google JavaScript error AGAIN

What the hell Google? A JScript error again? Last week it was AdSense, this week it is in the Followers gadget.

I just happened to look at my blog before thinking about posting something and up pops a JScript error and then a blank blog page. Nice. Upon debugging I see the error is in this line:
google.friendconnect.container.renderUrlCanvasGadget({'id': 'gadget-canvas'})

Which look like it might be the Followers gadget. I disable it and no more error. So not too hard to get by, but what the hell is with all these scripting errors?

I think there might be some kind of problem with the QA and deployment strategy over at the big g…


[Edit] I went and put the gadget right back again, and the error does not reoccur… I can’t see that line of code anywhere at all, so I don’t know if that was not the problem or if it was fixed quickly or if adding and removing it updated the code or what… Gotta go.

Friday, February 20, 2009

Unfun things

Programmers tend to loathe writing documentation. I always have great documentation in mind while I am developing a nice solution to a problem, but it rarely gets realised. Usually the bare minimum gets done – sometimes less than that.

Another thing that is probably number two on the list of most not fun to do is error handling and logging.

I have just spent a little time cleaning up the error handling in the couple of applications that I am writing right now.

There are various components, running across various platforms – Windows and Web clients, .NET Remoting servers, Windows services, Web services, ASP.NET web sites (that are actually generated from specifications in xml files that are in turn created by a tool – one of the windows client applications). Anyway, the whole thing is getting a little too complex to hold in your head at once, and before it gets too complicated I wanted to put in a common logging component. I have wanted to do it for a while – get away from each component knowing how to ends an email or write the windows log. Now it is mostly done.

I guess the whole point of this ramble was just to say that I got myself to do something pretty unpleasant – fix up exception handling chains, move chunks of code around while deciding which of 3 similar implementations are correct, fix up dll referencing issues, test error conditions – by giving myself something a little but fun to do – write a nice class using generics to build and hold an error message (so a message can be build up as different components have more or less important problems), grow the re-usable library that I have and actually re-use it.

Wednesday, February 18, 2009

Adding text to a WLW post without screwing up the mark-up!

Finally! I have discovered a way to add text at the end or middle of a post without causing horrible nesting problems with the <p> tags.

If you just go clicking at the end of an existing paragraph, or even on it, or even clicking in a space that looks blank, it is pretty easy to end up with this kind of mess:

<p>
  <p>para1</p>
 
  <p>para2</p></p>

But now I have managed to work out how to avoid it! As an example, to add a paragraph to the end of a post:

  • Hover over the invisible box that represents the blank <p></p> that WLW sticks after each paragraph with text in it. You are looking for the North South East West arrow cursor.

  • Click to select it. You need to end up with the eight little squares in the corners and on the edges showing that the whole element is selected, not the insertion point indicating that it is trying to add text inside the element.

  • Now press the right arrow key. You should end up with the insertion point below the element you clicked on. Now you can type and the text will go into the paragraph element and pressing enter at the end will close the current paragraph, insert a blank one and start a new one. Remember also that you do need to press enter at the end of the paragraph, even the last one, to get the tag to close properly.

To insert a paragraph between two existing ones, you want to do the same thing with the invisible blank paragraph element between two with text in. When you press the right arrow it will look like you are in the next paragraph with text, but you aren’t. Once you get to the end of your paragraph and hit enter all will be well again.

I feel like I am 90% of the way to being able to use WLW without switching to the source pane all the time – which is how you bloody well should be able to use it. It is just a bit unfortunate that I have to do it by being careful where I click and type and so on.

Gmail 2.0 and scrolling in IE7

Gmail’s new version 2 interface might be a slight improvement visually, but it sure does not like Internet Explorer 7 very much.

If you use the scrollbar at all the cpu usage for iexplore.exe gets pegged to 100% for a couple of seconds. I have not looked into what it is actually doing yet – not interested enough perhaps. If you switch back to the old interface (there is a link up on the top right of the page) the problem goes away. The only hassle is that this setting is not saved, the next time you log in you are back to the regular interface.

Curiously if you scroll with the keyboard it works fine. Scrolling with the scroll wheel or the edge of the touchpad hangs it up too. Seems to be in the handling of the onScroll (or whatever) event.


[Edit] It seems to be a problem with FlashGet. Disabling the FlashGet GetFlash Class makes the problem go away. Interestingly enough FlashGet still seems to work just fine…

Remote debugging

Yesterday I had quite a bit of fun trying to get remote debugging of a web application working.

I did solve this problem a little (very short) while ago… but I forgot what I had done.

So after executing a couple (quite a few) iterations of a Modify, Compile, Deploy, TryToDebug, Uninstall loop I know what you have to do to get it working. At least if you are using a deployment project to put the files up on the server.

You have to add the debug output from any project that you want to debug into to the deployment project*.

You must make sure that those debug outputs are in the right directory in the File System configuration pane so that the TargetName will have the files going into the correct directory on the server**.

Then you can install and debug. The setup of the remote debugger is a bit complex too. Basically the way I got it to work was by adding my own domain user (I log into my machine by logging into the domain) to the Administrators group on the server, and then logged in (via mstsc /console) to the server as myself (so that user could reconnect back to my machine). Bingo.


* You can’t just copy them up to the server it seems. I don’t know what the difference is, but it just does not manage to find them. I have even tried loading the symbols from the modules window directly – if complains that the symbols are not for the same version of the dll. I have not seen what happens if you are not actually deploying with an msi – there could be trouble. It is just one of those cases where there is some mechanism there that is storing some information somewhere and when it works everything is rosy, but when it does not work it can be fairly opaque. I guess that is what comes from not technically knowing what you are doing, but we can’t all be experts on the internal workings of everything – there is just not time, and when most of the time it just automagically works there is not much point either.

** The target name for the debug output of some project types (e.g. ASP.Net Web Application) will be bin/AssemblyName.pdb so the output needs to be placed in the Web Application Folder (where they seem to go by default), whereas other types (e.g. Class Library) will just be AssemblyName.pdb so their output needs to be put into the bin folder – they won’t be there by default, they will be one level up in the Web Application Folder. If you do not get this right the debug symbols will fail to load. You can look at information about what is being loaded from where in the Modules window found in Debug > Windows > Modules when you are in debug mode.