Using the Dynamic Data Database Embedded Image Field Template

Introduction

Hi all.  I’ve been working with the old ASP.NET Dynamic Data website templates, as I wanted a quick and easy to use web UI for managing the data at http://rs-photography.org.

As the site is (obviously) image-centric, I wanted to make some modifications to the out-of-the-box Dynamic Data project to include native image rendering/loading and updating.

I thought this was going to be relatively straightforward, being that there is a NuGet packaging encouragingly called “Dynamic Data Database Embedded Image Field Template” as well as a package called “Microsoft.Web.DynamicData.Handlers” which promises “Asp.Net image handler for rendering images from database”.

image

image

image

The good news is that this is a relatively straightforward implementation, but sadly lacking in clear instructions once the packages are successfully added.  This post will clarify exactly what you must do to get images displaying in your Dynamic Data site.

Note: the only references I could find online were quite old (i.e. 2007-2008), and pre-dated the NuGet packages, hence I felt the need to write this article.

The Scenario – NuGet Packages installed

imageI’m going to assume that if you are reading this article, you’re familiar with Dynamic Data websites.  If you aren’t, I’d suggest you get up to speed by reading a couple of tutorials (e.g. this one) – it’s a synch to get a site built, takes only a couple of minutes.

Once you have your site loading correctly, you’ll need to ensure you have a column in a table which is of sql type “image”.  The Entity Framework models this (correctly) as a property of type byte array (byte[]).  By default, Dynamic Data templates don’t have a field template for the byte array type, so the column is ignored when scaffolding occurs.

Assuming you have the NuGet packages installed, you’ll automatically have two new field templates added to the DynamicData folder, like so (left).

Your web.config file will also be updated to include a http handler for image requests, like so:

<system.webServer>
    <handlers>
      <add name="ImageHandler" path="ImageHandler.ashx" verb="*" 
           type="Microsoft.Web.DynamicData.Handlers.ImageHandler"/> </handlers> </system.webServer>

The handler is implemented in a binary which is included in the project – Microsoft.Web.DynamicData.Handlers.

image

The Data Schema

Now, if you run up the site and drill into the table you’ve defined your image field in, you’ll probably notice the image column is missing.  As stated above, because of the data type, by default there’s no handler.  This is where you need to do some work to help the scaffolding and field templates map properly.

Here’s my table schema and entity definitions so you can see exactly what I’ve done:

The “Files” Table:

CREATE TABLE [dbo].[Files] (
    [FileId]       INT            IDENTITY (1, 1) NOT NULL,
    [Filename]     NVARCHAR (100) NULL,
    [CatalogId]    INT            NULL,
    [SizeId]       INT            NULL,
    [IsDefault]    BIT            DEFAULT ((0)) NOT NULL,
    [Height]       INT            NULL,
    [Width]        INT            NULL,
    [ImageData]    IMAGE          NULL,
    [HasImageData] BIT            CONSTRAINT [DF_Files_HasImageData] DEFAULT ((0)) NOT NULL,
    PRIMARY KEY CLUSTERED ([FileId] ASC),
    CONSTRAINT [FK_Files_Catalog] FOREIGN KEY ([CatalogId]) REFERENCES [dbo].[Catalog] ([CatalogId]),
    CONSTRAINT [FK_Files_Sizes] FOREIGN KEY ([SizeId]) REFERENCES [dbo].[Sizes] ([SizeId])
);

The File class (entity):

public partial class File
{
    public int FileId { get; set; }
    public string Filename { get; set; }
    public Nullable<int> CatalogId { get; set; }
    public Nullable<int> SizeId { get; set; }
    public bool IsDefault { get; set; }
    public Nullable<int> Height { get; set; }
    public Nullable<int> Width { get; set; }
    public byte[] ImageData { get; set; }
    public bool HasImageData { get; set; }
    
    public virtual Catalog Catalog { get; set; }
    public virtual Size Size { get; set; }
}

Adding Attributes

You’ll need to extend on the partial class(es) in your Entity Framework model.  You need to keep the column definitions the same, so you need to just extend the class for metadata purposes (i.e. attributes).  If you add the attributes directly to the generated classes, they’ll be overwritten when you refresh the data model.

To add the appropriate attributes, I did the following:

using System.ComponentModel.DataAnnotations;

 

[MetadataType(typeof(File_MD))] public partial class File { } public partial class File_MD { [ScaffoldColumn(true)] [UIHint("Image")] [ImageFormat(100, 100)] public byte[] ImageData { get; set; } }

Examining the Attributes – the important one is [UIHint] as this provides the scaffolding the name of the type template to use (suffix/prefixes are used automatically), ergo by specifying “Image” we are implying the use of Image.ascx or Image_Edit.ascx.  To learn more about how scaffolding works, check out the following MSDN article.

Note that the extended partial class must be in the same namespace as the data model.

Once we have these attributes in place, and reload the site – given a row that has data in the image column, we should see something more favourable:

image

Presto!  Nothing more to do.  We can also now use a file picker to upload an image for new and existing records:

image

..and here it is in the SQL table:

image

If you want to make your column naming a bit more pleasing, add the following attribute to the column definition (in your metadata extension):

[Display(Name=”Image”)] 

image

Summary

That’s it.  It comes down to getting the entity property attributes set properly, and the rest is easy as.  It’s essentially adding image handling support out of the box for Dynamic Data sites, the last part is something a NuGet package can’t do – which is to interpret your data model.

I’ve tested this with IIS Express, Visual Studio 2013 and SQL Server 2012 and Entity Framework v5 (the last version compatible with Dynamic Data sites).  Note that the Entity Framework v6 will not work with Dynamic Data sites due to the namespace refactoring.

Enjoy.

Useful Links

http://www.olegsych.com/2010/09/understanding-aspnet-dynamic-data-entity-templates/

Leave a comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.