Monthly Archives: August 2008

How to respond with code 404 (Not Found) in ASP.NET

Suppose you configured custom 404 page in web.config file in the customErrors section. So whenever user requests non-existent aspx page, ASP.NET run-time returns well formatted message to the user.

Also you have a page that shows articles from a database according to article ID passed in the url (for example: article.aspx?id=345). But if user passes article ID that doesn’t exists the page must return code 404 (Not Found) and show the custom 404 page like in the previous situation.

Fortunately you don’t need to parse the customErrors section to get name of the custom 404 page. Just throw HttpException:

throw new HttpException(404, “Article not found”);

ASP.NET run-time will catch the exception and will redirect to the custom 404.

Gallery of Thunderstorm Wallpaper [Wallpaper]

lightning-wallppaper.pngIf our featured desktop Lightning at Sunset inspired you to look for some inclement wallpaper of your own, check out Digital Photography School’s 15 spectacular lightning images.

Credit card perks you didn’t know about (part 2)

See Part 1 of credit card perks you don’t know about.

Marketers know that it’s much more cost-effective to serve your existing customers rather than spending a ton of money to acquire new customers. Cost-effective, yes, but it’s sure sexier to spend money on Superbowl ads and stupid social-media spends.

The same is true of our personal finances. You could spend 10 hours per month moving your money from one high-interest account to another to eek out an extra 0.5% interest, or you could just take advantage of what you already have. One way to start is with your credit cards.

A lot of people ask me why I use my credit card for 95% of my spending. I do this for three reasons: Convenience (easily downloadable, trackable, categorizable), to build credit history, and huge consumer benefits.

Yesterday I got this list of perks in the mail, and it included a few I didn’t even know about. These perks are standard on most cards, so call yours to find out what you have.

Perks on your credit card
See a bigger version

I’ve copied the best ones below. Did you realize you got all (or most) of these perks with your credit card?

You have our dedicated concierge staff to assist you.
The 24-hour personal concierge service will make your dinner reservations, purchase tickets to events, coordinate business arrangements worldwide and locate hard-to-find items. Your concierge can assist you with gift selections as well as other requests to simplify your life.

Car rental insurance
Provides up to $50,000 in secondary coverage against collision or theft when you reserve and charge your car rental to your card and decline the car rental company’s collision, loss/damage waiver insurance.

Retail purchase protection
Protects most purchases made on your card against theft, fire and accidental breakage of up to $500 for up to 90 days from the date of purchase.

Price protection
If you buy something with your card and then see it advertised in print for less within 60 days, you will receive a refund for the difference up to $250. (Excludes internet purchases and certain items.)

$0 liability for unauthorized purchases, online or off
Complete protection against the unauthorized use of account.

Extended warranty
Coverage duplicates the terms of the U.S. manufacturer or store warranties of one year or less up to a maximum of 12 months on most items you purchase and is limited to the lesser of the amount charged to your card or $10,000.

Trip cancellation/trip interruption coverage
If you are prevented from taking or continuing a trip you billed to your account, you are eligible to receive up to $1,500 in Trip cancellation/trip interruption coverage

Lost luggage coverage
You are eligible for up to $3,000 in lost luggage coverage for you and your dependents when you charge your entire common carrier fare to your Citi World MasterCard. This benefit covers permanently lost, stolen or damaged baggage or personal articles checked with a common carrier.

Roadside assistance
If your car breaks down, help is just a phone call away.

My take: If you’re already spending on your credit card, you might as well use as many perks as possible. And consider that with one use of the perks for roadside assistance or purchase protection or extended warranty, you save more than you would with stupid 0%-balance-transfer/bank-transfer games.

Episode 61- IWF 2008

Download Low Resolution
Download High Resolution

Although for me, IWF was about representing my sponsors and meeting up with readers/viewers, nearly everyone else has one thing on their mind: tools. So we did our best to get some footage of the most talked about tools of the show. I know we missed quite a few (specifically, Jet’s new oscillating drum sander). But with our tight schedule and impending exhaustion, we did the best we could. Nothing fancy, nothing funny, just tools!

Here are the companies we visited:

Leigh, Blum Tool Co., Ex-Factory, DeWalt, Powermatic, Delta, and Laguna.

For more IWF coverage, check out these great resources:
Fine Woodworking Editors Blog
Popular Woodworking Blog

Folder Guide Adds Quick Folder Access to Your Right-Click Menu [Featured Windows Download]

folder-guide.pngWindows only: Free Windows utility Folder Guide adds user-defined folders to your right-click menu for quick, easy access to any number of favorite folders. Once you add a folder, Folder Guide makes it a very simple affair to navigate to that commonly used folder in just two clicks. Explorer’s Favorites menu already uses the same basic concept, but it’s not as readily available as the right-click menu and it also integrates with Internet Explorer, which means any of those bookmarks clutter your folder shortcuts. If you like the quick access idea behind Folder Guide but don’t like the execution, check out previously mentioned Direct Folders or previously mentioned Finder Style to put your favorites in the sidebar.


Dynamic Data and Custom Metadata Providers

In my previous post on Dynamic Data, I mentioned that you can use the MetadataType attribute to point Dynamic Data at class that contains additional metadata for your model. This additional metadata will give you more control over how your UI elements render. If you don’t want a column to display in your GridView, want to change the column header text from EmployeeID to Employee ID or want the cell values formatted a little differently this metadata class is where this information gets specified. The code snippet below shows how this class can be used for customization.

Download

//  Attach the Employee Metadata to the Employee
//  entity that the LINQ to SQL designer generates
[MetadataType(typeof(EmployeeMetadata))]
public partial class Employee
{
}

//  Attach some additional metadata
public class EmployeeMetadata
{
    //  Rename the EmployeeID column to Employee ID
    [DisplayName("Employee ID")]
    public object EmployeeID { get; set; }

    //  Format the Hire Date
    [DisplayFormat(DataFormatString = "{0:d}")]
    public object HireDate { get; set; }

    //  Hide the HomePhone column
    [ScaffoldColumn(false)]
    public object HomePhone { get; set; }
}

That is pretty cool. And what’s even better is that if you don’t like storing this information as attributes, you can swap out the default implementation and replace it with a solution that better fits your needs. Stuff your metadata in an XML file, flat file, in-memory, or database – it is pretty much up to you. All you need to do is write the TypeDescriptor logic that rebuilds the metadata from where ever it is you have placed it.

Below shows three different ways of specifying the a MetadataProviderFactory. Internally, ContextConfiguration uses the AssociatedMetadataTypeTypeDescriptionProvider if a custom factory is not provided so the first two calls to RegisterContext do exactly the same thing. In the third example I have provided my own custom provider, XmlMetadataDescriptionProvider, that reads the metadata from an xml file.

//  Example 1:
//  just use the default metadata provider
model.RegisterContext(typeof(NorthwindDataContext), new ContextConfiguration()
{
    ScaffoldAllTables = true
});

//  Example 2:
//  this is exactly the same as above
model.RegisterContext(typeof(NorthwindDataContext), new ContextConfiguration()
{
    ScaffoldAllTables = true,
    MetadataProviderFactory = (type => new AssociatedMetadataTypeTypeDescriptionProvider(type))
});                

//  Example 3:
//  here I am using a custom provider that reads the metadata from
//  an xml file
model.RegisterContext(typeof(NorthwindDataContext), new ContextConfiguration()
{
    ScaffoldAllTables = true,
    MetadataProviderFactory = (type => new XmlMetadataDescriptionProvider(type, "metadata.xml"))
});  

Implementing a Custom Metadata Provider

While building my Simple 5 Table Dynamic Data Northwind example last week, I found myself typing in the same type of metadata information for each of the properties I was showing on my screens. I was adding attributes for things like …

  • Add spaces into the column headers. So ShippedDate would become Shipped Date.
  • Stripping the time component from my DateTime properties
  • Formatting my decimal properties as currency

So I created a new TypeDescriptionProvider that I have configured to supplement the AssociatedMetadataTypeTypeDescriptionProvider with additional metadata that is generated by a handful of rules. Stuff like …

  • DateTime properties should have a default format of {0:d}
  • decimal properties should have a default format of {0:c}
  • Split the property name into its word components and use that as its display name

It turns out there isn’t a whole lot to my custom provider (download the code and take a peek). I just run a piece of code that checks to see if the property already has the DisplayName and DisplayFormat attributes defined. If so its a no-op. If not, I use some simple rules to generate these attributes and add them to the PropertyDescriptor. Below is the core logic. A few things to note …

  • Line 12: I first check to see if the property already has the DisplayNameAttribute defined. If it does I don’t do anything. But if it doesn’t have this attribute defined, I use the properties name to generate the friendly display name using the ToHumanFromPascal function (which I stole from here).
  • Line 24: I do the same here. If the property doesn’t have the DisplayFormatAttribute I get the default display format for the property type and apply that.
public override PropertyDescriptorCollection GetProperties()
{
    List propertyDescriptors = new List();

    foreach (PropertyDescriptor propDescriptor in base.GetProperties())
    {
        List newAttributes = new List();

        //  Display Name Rules ...
        //  If the property doesn't already have a DisplayNameAttribute defined
        //  go ahead and auto-generate one based on the property name
        if (!HasAttribute(propDescriptor))
        {
            //  generate the display name
            string friendlyDisplayName = ToHumanFromPascal(propDescriptor.Name);

            //  add it to the list
            newAttributes.Add(new DisplayNameAttribute(friendlyDisplayName));
        }

        //  Display Format Rules ...
        //  If the property doesn't already have a DisplayFormatAttribute defined
        //  go ahead and auto-generate one based on the property type
        if (!HasAttribute(propDescriptor))
        {
            //  get the default format for the property type
            string displayFormat = GetDisplayFormat(propDescriptor.PropertyType);

            //  add it to the list
            newAttributes.Add(new DisplayFormatAttribute() { DataFormatString = displayFormat });
        }

        propertyDescriptors.Add(new WrappedPropertyDescriptor(propDescriptor, newAttributes.ToArray()));
    }

    //  return the descriptor collection
    return new PropertyDescriptorCollection(propertyDescriptors.ToArray(), true);
}

So what does all of this produce? Well, with this metadata …

//  Attach the OrderMetadata to the Order class
[MetadataType(typeof(OrderMetadata))]
public partial class Order {}

[TableName("My Orders")]
public class OrderMetadata
{
    //  Columns I want hidden
    [ScaffoldColumn(false)]
    public object RequiredDate { get; set; }
    [ScaffoldColumn(false)]
    public object ShipVia { get; set; }
    [ScaffoldColumn(false)]
    public object Freight { get; set; }
    [ScaffoldColumn(false)]
    public object ShipName { get; set; }
    [ScaffoldColumn(false)]
    public object ShipPostalCode { get; set; }
    [ScaffoldColumn(false)]
    public object ShipCountry { get; set; }
}

and this configuration …

model.RegisterContext(typeof(NorthwindDataContext), new ContextConfiguration() {
    ScaffoldAllTables = true
});

the orders grid looks like this. Notice the concatenated column headers and the OrderDate and ShippedDate cell values …

image

but with the same metadata and my custom metadata provider …

model.RegisterContext(typeof(NorthwindDataContext), new ContextConfiguration()
{
    ScaffoldAllTables = true,
    MetadataProviderFactory = (type => new DefaultTypeDescriptionProvider(type, new AssociatedMetadataTypeTypeDescriptionProvider(type)))
}); 

it looks like this …

image

Conclusion

I am sure a few people are wincing that I am applying these rules at run-time when they are statically known. No problem, move these rules from the TypeDescriptor and into your build process and auto-generate the metadata class or move the stuff to an xml file and write your own custom provider. Or you can even use a hybrid approach like I have done here that supplements the default attribute implementation with a few basic rules which are evaluated at run-time. The cool thing here is that you can choose what best fits your needs.

That’s it. Enjoy!

Chain.js – data binding for jQuery

chain_js_20080821.jpg

Rizqi Ahmad, a high-school student in Germany, created a pretty useful data binding service for jQuery called Chain.js. It allows you to easily manipulate data driven content from javascript by directly manipulating the DOM, without resorting to templates or a lot of complicated code. You create the markup the way you want the data to display, give class names to DOM elements that should have their content substituted, and pass an associative array containing the variable data to the chain() method.

There is also support for managing lists of elements, allowing you to add and remove elements dynamically inside the defined markup. Rizqi also created the Interaction library that works on top of the data binding library to provide drag, drop, and sort support for lists.

Make sure to check out his demos. They show off some of the flexibility of the library and they’re easy to tweak for your own needs.

Data Binding Solution for jQuery
Chain.js – Data Binding Service for jQuery
Interaction.js – drag/drop/sort support for Chain.js

Ancient Bench Built from Modern Materials

Planemaker Gary Blum introduced a new workbench
design for sale here at the International Woodworking Fair. Well, it’s not really
fair to call it new. The base design is a couple hundred years old, but Blum has added
Baltic Birch plywood, bronze bushings and pipe clamps to make it a thoroughly modern
bench.

The bench looks like the English-style workbench immortalized in Peter Nicholson’s
“Mechanic’s Companion” of the 19th century. It is essentially a torsion box on top
of some stiff legs.

The top of Blum’s ingenious bench is also a torsion box made from 3/4” Baltic birch
plywood throughout – the front apron is actually a sandwich of two layers of Baltic
birch. Below the torsion box top is a set of red-oak legs and stretchers joined with
bolts, which allow the bench to be knocked down. The legs are angled out to give the
bench a firm stance.

Weighing in at about 240 pounds, the bench is 24” deep and 6’ long, though Gary says
he will make the bench 7’ or 8’ long upon request. The user also can specify the height
of the bench.

The most clever aspect of the bench is how Blum incorporated Jorgensen pipe clamps
into the design to work as the face vise and the end vise.

In the face vise position, Blum built a twin-screw vise by placed two pipe clamps
in bronze bushings on 18” centers. The clamps press a large removable wooden chop
against the front edge of the benchtop. You might be wondering if pipe clamps have
enough throw to be useful as a woodworking vise. They don’t. If you need to clamp
really thick work, the pipe clamps can be slid out and locked in position to hold
thick stock.

Blum put a similar clamping system on the end of the bench, but he also incorporated
a dog system into the end vise so you can clamp panels to your benchtop between dogs.

The base model of the bench will cost about $995. Longer versions will cost more.

I got to work with the bench for about 15 minutes today and was very impressed. It
is a solid bench, and the torsion box will ensure that the top remains rigid and flat
(unless you leave your bench out in the rain).

So for those woodworkers looking for a solid English-style bench, drop Blum
a line
. It’s a heck of a deal at that price.

— Christopher Schwarz

Add Double Scroll Arrows to Both Ends of the Scroll Bar [Mac OS X Tip]

double-scroll-arrows.pngAll-things-Mac weblog TUAW highlights a handy Terminal trick for adding OS X’s double scroll arrows to both sides of your scroll bar. Just fire up Terminal (it’s in the Utilities folder of your Applications folder) and paste (one line):

defaults write "Apple Global Domain" AppleScrollBarVariant DoubleBoth

You’ll need to log out and back into your Mac before the changes take effect. If you prefer more traditional variants, you can actually tweak the other two options—place scroll arrows together on one side or separately at the top and bottom—in the Appearances section of your System Preferences. Since the point of keeping the scroll arrows next to each other is to minimize mouse movement, though, have the double arrows at both ends makes a lot of sense.


ASP.NET Dynamic Data – Simple 5 Table Northwind Example

I have been anxiously awaiting the Dynamic Data release. And now that it is here (it was released with VS 2008 and .Net 3.5 SP1) I decided I would start getting a feel for what is has to offer by building a real simple Dynamic Data web site that allows you to browse the 5 core Northwind tables – Customers, Employees, Orders, Products and Suppliers. Read on for the details and don’t forget to download the code. DiscountASP hasn’t quite upgraded to SP1 so I don’t have a live demo setup. Hopefully they will get the upgrade completed soon, but I made sure to include lots of screen shots so you can get a good idea of what the screens look like.

Download

image

What is Dynamic Data?

I try to keep a close eye on ASP.NET, but I didn’t know Dynamic Data was shipping as part of SP1. I asked around the office and found out this took a few other people by surprise too. And more than a few people had actually never heard of Dynamic Data. In case you fall into that category, here are a couple of quotes that describe what DynamicData is all about.

From Wikipedia

ASP.NET Dynamic Data is a web application scaffolding framework from Microsoft, shipped as an extension to ASP.NET, that can be used to build data driven web applications. It exposes tables in a database by encoding it in the URI of the ASP.NET web service, and the data in the table is automatically rendered to HTML. The process of rendering can be controlled using custom design templates. Internally, it discovers the database schema by using the database metadata.

From asp.net

ASP.NET Dynamic Data provides a framework that enables you to quickly build a functional data-driven application, based on a LINQ to SQL or Entity Framework data model. It also adds great flexibility and functionality to the DetailsView, FormView, GridView, and ListView controls in the form of smart validation and the ability to easily change the display of these controls using templates.

So for this demo app, I am planning on using Dynamic Data to build a web application that allows me to browse the Northwind database.

Create the Dynamic Data Web Site

To get started building a Dynamic Data Web Site, you do the usual File -> New -> Web Site and select either the Dynamic Data Entities Web Site or Dynamic Data Web Site templates. If you plan on using the ADO.NET Entity Framework for data access you can select the first option, otherwise if you are using LINQ to SQL you select the second template. For this example I am using LINQ to SQL so I chose the Dynamic Data Web Site template.

image

When VS finishes loading, you will notice a number of files/folders have been included in the solution. The solution includes a DynamicData folder that is filled with other folders and each is filled with both UserControls and regular ASP.NET Pages.

image

Create and Register the LINQ to SQL DataContext

I am going to use LINQ to SQL to access the my Northwind data, so I used the VS designer create the LINQ to SQL classes for the tables I want by dragging my tables over from the server explorer and dropping them onto the design surface.

image

After creating the DataContext, I update the Global.asax and register my NorthwindDataContext with the DynamicData system. The web site template generates the code that handles all of this, you just have to read the comments and plug in your custom context type. Here is what it ends up looking like …

public static void RegisterRoutes(RouteCollection routes)
{
  MetaModel model = new MetaModel();
  // IMPORTANT: DATA MODEL REGISTRATION
  // Uncomment this line to register LINQ to SQL classes or an ADO.NET Entity Data
  // model for ASP.NET Dynamic Data. Set ScaffoldAllTables = true only if you are sure
  // that you want all tables in the data model to support a scaffold (i.e. templates)
  // view. To control scaffolding for individual tables, create a partial class for
  // the table and apply the [Scaffold(true)] attribute to the partial class.
  // Note: Make sure that you change "YourDataContextType" to the name of the data context
  // class in your application.
  model.RegisterContext( typeof(NorthwindDataContext), new ContextConfiguration() { ScaffoldAllTables = true });

  // The following statement supports separate-page mode, where the List, Detail, Insert, and
  // Update tasks are performed by using separate pages. To enable this mode, uncomment the following
  // route definition, and comment out the route definitions in the combined-page mode section that follows.
  routes.Add(new DynamicDataRoute("{table}/{action}.aspx") {
    Constraints = new RouteValueDictionary(new { action = "List|Details|Edit|Insert"}), Model = model
  });

  // The following statements support combined-page mode, where the List, Detail, Insert, and
  // Update tasks are performed by using the same page. To enable this mode, uncomment the
  // following routes and comment out the route definition in the separate-page mode section above.
  //routes.Add(new DynamicDataRoute("{table}/ListDetails.aspx") {
  // Action = PageAction.List,
  // ViewName = "ListDetails",
  // Model = model
  //});

  //routes.Add(new DynamicDataRoute("{table}/ListDetails.aspx") {
  // Action = PageAction.Details,
  // ViewName = "ListDetails",
  // Model = model
  //});

 }

And really after you have done this you have a pretty nice looking and functional web site. A landing page that lets you know about what tables are available …

image

Grids for viewing the contents of these tables (paging and sorting included) …

image

And pages for Inserting, Updating and viewing Details …

image

Customization

If I was happy with how all of the default pages look, I could have stopped here and had a functional web application that supports basic CRUD operations. That’s pretty cool. And that took all of what … 5 minutes? But what if I would like to change a few things?

Customizing the List Page Template

The List template is located in the DynamicData/PageTemplates folder. The default List page look pretty good, but I wanted to see what it would take to make a few changes. So I opened the List.aspx page and started making my changes.

  • First, I added a black border by wrapping the GrdView in a series of DIVs that use background images to style the border.
  • Next, I increased the PageSize from 10 to 15.
  • Then added a different Data Pager
  • Finally, I want my site to be read-only so I removed the Insert, Edit and Delete links

Nothing too major, but styles provide quite a bit of change.

image

Customizing the Details Page Template

Next, I made similar changes to the Details page template.

image

Adding Custom Metadata to the Model

There are a few things that you will notice in the screen shots above with my custom pages that are different from the default pages.

  • The grids column counts are different (my custom pages have fewer columns)
  • Some of the column headers have different names
  • Some of the grid’s cell values are formatted differently
  • The display name for the table

To customize these items, you need to create a metadata class that provides Dynamic Data with a little more information about your entities. I will be honest, this part seems a little weird to me, but that might just be because it is new. Anyway, to accomplish this you need to create two more classes for each of the classes in your DataContext. So for my 5 table sample, I need to create 10 more classes to attach my metadata.

First you add a partial class with the same name of the entity class in the data model and then apply an attribute to this partial class that ties it to the additional metadata we have defined for the class. The code snippet below is what does this for the Order entity in our sample application. The following bit of code tells Dynamic Data the following …

  • The display name for the Order table is ‘My Orders’ – Applied with the TableName attributes
  • The OrderDate, ShippedDate, ShipAddress and ShipCity columns all have overridden display names – Applied with the DisplayName attribute
  • The OrderDate and ShippedDate columns have a custom format – Applied with the DisplayFormat attribute
  • The RequiredDate, ShipVia, Freight, ShipName, ShipPostalCode, and ShipCountry columns should be hidden from the UI – Applied with the ScaffoldColumn attribute
// Attach the OrderMetadata to the Order class
[MetadataType(typeof(OrderMetadata))]
public partial class Order {}

[TableName("My Orders")]
public class OrderMetadata
{
  // Override the display name
  [DisplayName("Date Ordered")]

  // Format the Date
  [DisplayFormat(DataFormatString="{0:d}")]
  public object OrderDate { get; set; }

  // Override the display name
  [DisplayName("Date Shipped")]

  // Format the Date
  [DisplayFormat(DataFormatString = "{0:d}")]
  public object ShippedDate { get; set; }

  // Override the display name
  [DisplayName("Address")]
  public object ShipAddress { get; set; }

  // Override the display name
  [DisplayName("City")]
  public object ShipCity { get; set; }

  // Columns I want hidden
  [ScaffoldColumn(false)]
  public object RequiredDate { get; set; }

  [ScaffoldColumn(false)]
  public object ShipVia { get; set; }

  [ScaffoldColumn(false)]
  public object Freight { get; set; }

  [ScaffoldColumn(false)]
  public object ShipName { get; set; }

  [ScaffoldColumn(false)]
  public object ShipPostalCode { get; set; }

  [ScaffoldColumn(false)]
  public object ShipCountry { get; set; }
}

Conclusion

Well that was my first pass through building a Dynamic Data site. I am pretty impressed and I am looking forward to exploring this further – stay tuned.

That’s it. Enjoy!

WP Like Button Plugin by Free WordPress Templates