ASP.Net Archive

0

James Hares’ “5 little wonders” series for C# / .Net

A while ago, Scott Guthrie (Product Manager of the .NET Framework) tweeted a link to James Hare’s “C#/.NET Five Little Wonders That Make Code Better (1 of 3)”. James has since published parts 2 and 3, and I provide the links below as a handy reference:

C#/.NET Five Little Wonders That Make Code Better (1 of 3)

C#/.NET Five Little Wonders That Make Code Better (2 of 3)

C#/.NET Five Little Wonders That Make Code Better (3 of 3)

The tips are short, well-written and cover items such as the null coalescing operator, the StopWatch class, object / collection initialisers, a talk on the use of var and (LINQ) extension methods.

Well worth a read :)

0

C# – converting an IEnumerable item’s single property to a CSV

I recently had to extract some items from an IList and pass their Guid identifiers to a legacy SQL Server stored procedure that required a list of comma-separated values.

Rather than loop round the list, appending items to a string with a comma at the end, then stripping the last comma off, or adding the chosen property to a IList, converting it to an array and then String.Join-ing that array, I came up with the following:

string divisionsCSV = String.Join(",", ((List)divisions).ConvertAll(d => d.DivisionID.ToString("b")).ToArray());

(There’s a casting of divisions to an List<IDivisionView> because a) divisions is an IList and b) ConvertAll is on the concrete implementation of IList)

I'm using ConvertAll to, er, convert a single property of every item in the list, in this case the Guid identifier of the division to a string. Incientally, I'm keeping the Guid parentheses thanks to the "b" parameter of the ToString call. The ToArray call then stuffs it all into an array ready for the String.Join call.

Any thoughts, comments or improvements?

0

A better app_offline.htm for ASP.Net

As we know, the presence of an app_offline.htm in an ASP.Net site will take the site down for maintenance or update, displaying whatever is in the file, e.g. an image, and some informative blurb. As ScottGu says, make sure the file is larger that 512 bytes to avoid the IE6 “friendly errors” feature.

Whilst it’s a convenient way to bring down a site, it brings it down a bit harshly, shutting down the App Domain and all sessions, which is really nice if your visitors are half-way through a financial transaction. I wanted a way to keep active users in their session, send new visitors to the site offline page and track how many people are still connected to the site.

My solution is two-fold: a simple HttpModule and a PerfMon graph. First, the HttpModule:

  1. Create a new class, calling it SiteUnavailable and make sure it inherits from IHttpModule.
  2. Use the smart tag to implement the IHttpModule members, which should give you Init and Dispose.
  3. In the Init, add the following:
    context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
  4. Add the following method:
    void context_PreRequestHandlerExecute(object sender, EventArgs e)
    {
    HttpApplication app = (HttpApplication)sender;
    HttpContext context = app.Context;
    if (System.IO.File.Exists(context.Server.MapPath("~/site_unavailable.htm")) && context.Session.IsNewSession)
    {
    context.Response.Redirect("~/site_unavailable.htm");
    }
    }
  5. In the Dispose method, remove the NotImplementedException and replace with a pithy comment of your choice ;)
  6. Add the following line to your web.config file in the httpModules section:
    <add name="SiteUnavailable" type="YourNamespace.SiteUnavailable"/>

That’s it – just create a file called site_unavailable.htm in the site root, filling it with an informative text, a logo, etc., and make sure it’s over 512 bytes. Now, when a vistor comes to the site and that page exists, they’ll be redirecetd to it. If you create / rename the file when users are active, they’ll still get to use the site until they end their session and try to visit the site again.

How’s it work? Well, the code speaks for itself: it checks for the site unavailable file and whether the session is a new one. If it is, then the user is redirected. The PreRequestExecuteHandler event is used because the Session object is available at that point, but main processing hasn’t really started yet. Yes, it’s looking for a hard-coded filename, but that’s what you’ve got with app_offline.htm as well.

That’s half the problem solved, now how do we see how many users are connected to the site? Enter Perfmon…

  1. Run Perfmon, and then right-click the graph and select Add Counters…
  2. For the Performance object, select Web Service
  3. Select the Current Connections counter, and then select your website from the “Select instances from list”, er, list
  4. Click Add, and then marvel at the metrics as they show the number of users connected to your site.

Now, when you enable the siteunavailable.htm page, you can watch the perfmon website connection counter go down as users finish their sessions. When it gets to zero, you can go ahead with your update, then rename the siteunavailable.htm page (to _siteunavailable.htm, for example) and hey presto, your site’s back and updated.

As an aside, it may help the perfmon connection counter reach zero quicker if the content of your siteunavailable.htm page says something like “please close this page to enable us to complete the upgrade quicker”, and it would be helpful to provide an estimated time of completion.

Thoughts? Comments?

0

Where should I be?

Not existential angst, but wondering where I need to position myself as a developer. I’ve missed out on some technologies, and I’m wondering how far down the rabbit hole I should go with some of them.

I’m still very much a web developer, so I certainly should be looking at ASP.Net MVC and jQuery, as well as upgrading my knowledge in the standard Web Forms, not forgetting the AJAX toolkit as well. Behind the scenes, looking at data storage layers such as LINQ to SQL and their enterprise patter, as well as applicable patterns such as the Repository Pattern and even the Active Record pattern.

That’s where things get, frankly, a bit dull and convoluted. I read a great post recently about how coding these days is how to link one library to another, or just whack some XML together to control a Spring.Net DI solution. I, like the author, can’t find the fun in that. Sure, it may get projects done quicker, and it’s standard, but it can also be a lot of overkill. That’s why I’d prefer a simple approach to projects, nice and lightweight, no navel-gazing about what might be required two years down the line, not coding an interface for every single class because “it’s the right thing to do” although it’ll never be used, adding tests to every single method (even private ones) because “it’s the right thing to do”, etc.

I’m a firm believer in Jeff Attwood’s mantra YAGNI – you ain’t gonna need it. If the customer hasn’t asked for it, and if there’s no chance it will be required within a year or so, don’t code it. Write your code in such a way that things can be replaced easily (and yes, I guess that does mean some interfaces, but surely not on every single bloody class), and keep it simple. I use as many syntactical shortcuts as I can, as I’m lazy, but that’s why they were added to the language.

Anyway, a bit off topic – I’m really writing this as a store for where I should be heading. I am a Microsoft chap, and I enjoy the products they put out and their technoology approaches. I find it amusing when I suggest a Microsoft solution (such as ASP.Net’s Forms Authentication) and am told by a colleague that he’ll write it themselves – how many people does Microsoft employ to work on stuff like this? How much R&D do they do? And one person thinks they can do it better? Heh, it’s another contradiction, I guess – I said I don’t like merely linking up one library with another, but I guess you could say that’s all I’m doing with the Forms Authentication, but hey, it’s sometimes a pain to get right and it’s fun wreslting with it BUT it provides a hell of a lot out of the box…

And don’t get me started on form validation – “oh, we don’t use the validation controls because they don’t work”. Yeah, ok, I’ve used them countless times and they seem just dandy.

Gah, back on topic. I really should be looking at what’s new in Windows Forms and the top best practices in that area as well, and look at Silverlight as well.

Hmmm, lots to cover – I’d better get started…

0

Indented hierarchical drop-down lists in ASP.Net

When constructing drop-down lists for an ASP.Net page with hierarchical data, it is usually desired to indent each hierarchical entry to illustrate the "tree" of data, e.g.:

Books
  Non-fiction
    Biographies
    Reference
  Thrillers
    Historical
    Spy
CDS
  Classical
  Dance

The way to do this is by using a non-breaking space &nbsp; . However, just slapping &nbsp; in the new ListItem constructor won't work:

ddl.Items.Add(new ListItem("&nbsp;&nbsp;Apple", productID.ToString()));

The above would render out this entry in the list:

&nbsp;&nbsp;Apple (you would see the mark-up as well as the word Apple)

The way around this is to use the hex value of the non-breaking space character, 160. This is obtained by using &#160;, e.g.

ddl.Items.Add(new ListItem("&#160;&#160;Apple", productID.ToString()));

However, you will still end up with mark-up similar:

&#160;&#160;Apple (you would see the mark-up as well as the word Apple)

This is because the &#160; needs to be decoded as it's being passed into the ListItem constructor, e.g.:

ddl.Items.Add(new ListItem(HttpUtility.HtmlDecode("&#160;&#160;Apple"), productID.ToString()));

This will give you a space-indented entry.

However, this would be of more use:

ddl.Items.Add(new ListItem(HttpUtility.HtmlDecode(MakeSpace(level)) + category.Name, category.CategoryID.ToString()));

where category is an item in a list (ArrayList, List, whatever) and level is the level it should be indented to (more on that next post). The method MakeSpace is as follows:

private string MakeSpace(int level) {
  string spaces = String.Empty;
  for (int i = 0; i < level; i++) { spaces += "&#160;&#160;";}
  return spaces;
}

(if anyone knows of a better way of writing MakeSpace, please let me know)

UPDATE 05/02/09: Ok, there is a better way for MakeSpace, as suggested by my colleague and unofficial mentor, Duncan Godwin:

private string MakeSpace(int level) {
  return new String('-', 2 * level).Replace("-", "&#160;");
}

Of course, you could place that directly in the Items.Add method, but I find that less readable.

0

ASP.Net – confirmation before delete

I realise this is a bit of a departure from my usual posts (i.e. I’m not ranting), but I’d thought I’d share a rather useful bit of ASP.Net code I’ve been using.

When a user is presented with a GridView of data they can delete, it’s usually a good idea to give them a “Are you sure?” confirmation dialog using Javascript, like so:

<asp:Button ID="uxDelete" runat="server" Text="Delete" OnClientClick="javascript: return confirm('Are you sure you want to delete this record?');" />

(The above is an ASP button, to be placed in a TemplateField in a GridView)

Now that will give a plain “Are you sure?” message, but it’s a bit vague – what if the GridView has twenty-five, fifty or one hundred records displayed? Will the user be sure they clicked the right delete button for the right product / entry / whatever?

By some clever use of the Eval statement, the dataitem you want to delete and some character escapes, it’s possible to put an identifiable piece of data in the Javascript confirm call:

<asp:Button ID="uxDelete" runat="server" Text="Delete" OnClientClick='<%# Eval("ProductCode", "javascript: return confirm(\"Are you sure you want to delete {0}?\");") %>' />

Now, when the user clicks delete on an item, the name of the item will appear in the confirm dialog, reinforcing their decision to delete.

Another reason I’ve blogged this is to have it somewhere where I can always get hold of it – I don’t remember stuff as well as I used to ;)