Archive

Archive for the ‘Technical’ Category

ASP.NET MVC Html.DropDownList Example

May 24th, 2013

I’ve been struggling for a while to find a decent example of how dropdown lists work in ASP.Net MVC. It seems like a pretty simple thing to do – show a dropdown list with a selected item, allow the user to select a different item then save the new selection back on the server when the user submits the form containing the dropdown. However, it took me a few hours of searching and experimenting to get my dropdown working.

Here’s how I got it working …

1. In the model used to pass data to the view, ensure there are two fields – one containing the list of items to show in the list on the web page, the other field containing the value of the selected item. Here’s a cut down version of my model class:

public class CustomerModelData
{
    // The list of payment terms. This is a list of strings
    // converted into the SelectList type for use by the
    // Html.DropDownList HTML helper.
    //
    public SelectList PaymentTerms { get; set; }

    // The value of the selected item. Note that this is
    // a string, i.e. the same type as the list members.
    //
    // Note that the name of this field is used by the
    // Html.DropDownList helper later in the example.
    //
    public String PaymentTermID { get; set; }
}

2. In the controller, when the view is initially loaded, populate the model fields above with the list of items for the dropdown and the value of the selected item.

// Load the data from the database.
//
CustomerModelData Model = new CustomerModelData();

List<PaymentTermData> DBTerms = DatabaseManager.PaymentTerms;
List<String> DBTermsText = new List<string>();

foreach (PaymentTermData PT in DBTerms)
{
    DBTermsText.Add(PT.ToString());
}

PaymentTermData SelectedTerm = DatabaseManager.SelectedTerm(); 

// Set the list of items for display converting from a
// list of strings to a SelectList.
//
Model.PaymentTerms = new SelectList(DBTermsText);

// Set the selected item for the drop down.
//
Model.PaymentTermID = SelectedTerm.ToString();

3. In the view, plase the Html.DropDownList helper:

@Html.DropDownList("PaymentTermID", Model.PaymentTerms)

Note that there are two parameters to the DropDownList call:

a. “PaymentTermID” – This is the name of the field in the model that contains the selected item.

b.  Model.PaymentTerms – This is the list of items for the drop down.

4. When the user makes a selection on the drop down and then submits the form containing the drop down, e.g. by pressing the Save or Submit button on the form, the same model class (CustomerModelData) can be used to pass data back to the controller:

[HttpPost]
public ActionResult CustomerDetails(CustomerModelData Data)
{
    // The value chosen by the user is now held in the model.
    //
    String TheSelectedValue = Data.PaymentTermID;
    // The list of values is NOT passed back to the controller.
    // This field is now null.
    //
    SelectList TheValues = Data.PaymentTerms;

Note that the value selected by the user has been updated in the model BUT that the list of values is now null. If the view is reloaded at the end of the controller action, the list will need to be repopulated in the model.

There may be other, more efficient ways of handling dropdown lists in ASP.Net MVC but this example works for me and took a surprising amount of time and trials to get to a working state. Initially, I had tried to think of the DropDownList helper as though it was a Winforms combo box where I could pass a list of objects, e.g. the actual PaymentTermData class, together with an instance of the class as the selected item. However this didn’t work and in the end I reverted to a simple type (String) for both the list and selected item in the drop down.

Also check out this post http://www.sliqtools.co.uk/blog/net/asp-net-mvc-disable-cache-to-keep-ajax-working-ok/ for tips on disabling the cache with Ajax requests as I have come across situations where the dropdownlist (and other stuff) appears not to work with the caching enabled.

Unable to update the EntitySet because it has a DefiningQuery and no InsertFunction element exists

May 14th, 2013

While working with SQL Server and Entity Framework the following error was raised after adding a new table into the SQL Database and updating the model in my project from the DB:

"Unable to update the EntitySet 'Customers' because it has a DefiningQuery and no <InsertFunction> element exists in the <ModificationFunctionMapping> element to support the current operation."

The error was raised as an exception on calling the SaveChanges method on the context after adding a new record into a list/ table on the database.

The solution to the problem was simple – although my new SQL table had an ID column, I hadn’t set the column as the primary key. Setting the column as a primary key in SQL Server Management Studio then going back to my Visual Studio project and rebuilding the entity model from the database made the error go away and let me successfully save new records to the table.

SQLite: How to get the row ID after inserting a row into a table

February 1st, 2013

When working with SQL databases it can often be useful to keep a record of the ID of the row in a table from which a piece of data was read. For example, if you have a Customers table in a database then if you populate a list of Customer objects in your application from the rows in the table, storing the row ID for each object lets you easily update the correct row if you edit the values in one of the Customer objects.

In SQLite, if you have a field of type INTEGER PRIMARY KEY in a table, the database engine will automatically fill the field with the ID for the row. When you insert a new row in the table, e.g. add a new customer into the Customers table taking the example above, then you will need to find out the ID of the new row so you can write it back into the Customer object you’ve just added.

SQLite has a special SQL function – last_row_id() – that returns the ID of the last row inserted into the database so getting the ID of a new row after performing a SQL insert just involves executing the last_row_id() command.

Here is an example in C# showing how to get the ID of the last row inserted into a table in a database.

Create the SQLite database and open a connection to it:

 String mPathName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "testdba.db3");

 SQLiteConnection.CreateFile(mPathName);

 // Open a connection to the database.
 SQLiteConnection Conn = new SQLiteConnection("Data Source = " + mPathName);

 Conn.Open();

Create a table (Customers) in the SQLite database:

 // Create a table.
 //
 String SQL = "CREATE TABLE Customers (ID INTEGER PRIMARY KEY, UNIQUEID VARCHAR(30), ADDRESS VARCHAR(100))";

 SQLiteCommand Command = new SQLiteCommand(SQL, Conn);

 // Create the table.
 //
 Command.ExecuteNonQuery();

Insert a row of data into the table:

 // Reuse the command object and insert a row into the table.
 //
 Command.CommandText = "INSERT INTO Customers (UNIQUEID, ADDRESS) VALUES (@UNIQUEID, @ADDRESS)";

 Command.CommandType = System.Data.CommandType.Text;

 Command.Parameters.Add(new SQLiteParameter("@UNIQUEID", "Fred Bloggs"));
 Command.Parameters.Add(new SQLiteParameter("@ADDRESS", "Acacia Avenue"));

 int Status = Command.ExecuteNonQuery();

Now get the ID of the last row inserted:

 Command.CommandText = "select last_insert_rowid()";

 // The row ID is a 64-bit value - cast the Command result to an Int64.
 //
 Int64 LastRowID64 = (Int64)Command.ExecuteScalar();

 // Then grab the bottom 32-bits as the unique ID of the row.
 //
 int LastRowID = (int)LastRowID64;

Note that in SQLite the row ID is a 64-bit integer but for all practical database sizes you can cast the 64 bit value to a 32-bit integer.

For more SQLite database tips check out:

http://www.sliqtools.co.uk/blog/net/sqlite-how-to-determine-if-a-columns-exists-in-a-table/

SQLite: How to Determine if a Column Exists in a Table

January 20th, 2013

As part of developing a new application using the SQLite database I need to perform some standard database checks when the application starts. Firstly I need to check that the application’s database exists and then either create the database if it doesn’t exist, or, if the database does exist, check that the tables in the SQLite database contain the columns expected by the app.

Checking whether the Database Exists

Checking that the SQLite database exists is easy, I can simply use code like:

if (!File.Exists(mPathName))
{

i.e. I can use the normal System.IO methods in .Net to check whether the database is present.

Creating a SQLite Database

Creating a SQLite database is also straightforward in SQLite. I can create the database file as follows:

// Create the database file.
SQLiteConnection.CreateFile(mPathName);

// Open a connection to the database.
using (SQLiteConnection Conn = new SQLiteConnection("Data Source = " + mPathName))
{
    Conn.Open();

    // Create the required tables. In this example, I'm creating a Customers table with 3 fields - ID, UNIQUEID and DATAFIELD.
    String SQL = "CREATE TABLE Customers (ID INTEGER PRIMARY KEY, UNIQUEID VARCHAR(30), DATAFIELD VARCHAR(100))";

    using (SQLiteCommand Command = new SQLiteCommand(SQL, Conn))
    {
       Command.ExecuteNonQuery();
    }

    Conn.Close();
}

This is all pretty standard SQL and ADO.Net.

Checking if Columns Exist in the SQLite Database

Checking whether columns exist was a little harder to work out for SQLite. Some other databases I’ve used has special methods to get the tables, columns and their attributes. SQLite didn’t have a class to enable me to do this quite so obviously but after some research and experimentation, I found the following code worked:

// Open a connection to the database.
using (SQLiteConnection Conn = new SQLiteConnection("Data Source = " + mPathName))
{
    Conn.Open();

    // Get the schema for the columns in the database.
    DataTable ColsTable = Conn.GetSchema("Columns");

    // Query the columns schema using SQL statements to work out if the required columns exist.
    bool IDExists       = ColsTable.Select("COLUMN_NAME='ID' AND TABLE_NAME='Customers'").Length != 0;
    bool UNIQUEIDExists = ColsTable.Select("COLUMN_NAME='UNIQUEID' AND TABLE_NAME='Customers'").Length != 0;
    bool ElephantExists = ColsTable.Select("COLUMN_NAME='ELEPHANT' AND TABLE_NAME='Customers'").Length != 0;

    Conn.Close();
}

A statement like

ColsTable.Select("COLUMN_NAME='ID' AND TABLE_NAME='Customers'")

returns an array of DataRows. If the column doesn’t exist an array of length 0 will be returned, hence the .Length != 0 check.

Adding a Column if it doesn’t Exist in the SQLite Database

Adding a column to a SQLite database can be performed using standard SQL statements.

String SQL = "ALTER TABLE Customers ADD COLUMN ELEPHANT VARCHAR(100)";

using (SQLiteCommand Command = new SQLiteCommand(SQL, Conn))
{
    Command.ExecuteNonQuery();
}

It turns out that performing these basic operations on a SQLite database is pretty straightforward when you know how. One thing I haven’t bothered to find out yet is to determine whether a column has the correct attributes, e.g. my example ELEPHANT column may change from a 100 character to a 200 character wide column between different versions of the application. However, I’ve never had a good reason for doing such a database update in the past. I’m also relying on the SQLite feature where the database will store any sort of data of almost any length in any column.

For more SQLite tips, see:

http://www.sliqtools.co.uk/blog/technical/sqlite-how-to-get-the-id-when-inserting-a-row-into-a-table/

Human-Centered Design – An Introduction to Designing for Ease of Use

January 18th, 2013

Designing products that are easy to use is not a simple exercise. After a number of years spent designing a range of PC and industrial products, my experience is that those products which appear the simplest, cleanest and easiest to use are, more often than not, the ones that took the most amount of effort to design and complete. Constructing a product that simply exposes every possible feature at once to the user is relatively easy. What’s more difficult is prioritising the user interface, making the most frequent and essential elements readily available while pushing the more advanced, less frequently used features into the background.

human-centred-design

One of the biggest obstacles to overcome when beginning to design anything that is easy to use is the designer’s ego. Almost all designers, whatever their field, e.g.  software, mechanical, usually hold some sort of innate belief about what the user wants and what the best solution should be. This is a natural and essential requirement for any designer. Without the self-belief and initiative to construct a solution a designer would not be able to form an innovative solution for a user need. However, in any mature development process, the ultimate design of a product should not be allowed to rely on what may turn out to be a prejudice, personal desire or pet theory of the loudest or most assertive engineer (or manager) on the team.

One process that can be adopted in any development program is Human-Centred or User-Centred Design. For a process that has sounds rather complicated, it’s actually based on some very simple and low-tech ideas. To describe HCD, let’s break the development process into 3 distinct stages:-

1. Understand the user’s requirements for the product.

In particular try to gain an understanding of the user’s pain point or difficulties.

2. Innovate and design a solution for the user’s product requirements.

3. Test and evaluate the solution with users.

Take the lessons learned and go back to stage 1.

Repeat steps 1, 2 and 3 as required. Any development is a compromise and engineering judgement needs to be used to decide when the improvements are no longer worth the effort of repeating the cycle. HCD techniques come into play mainly in stages 2 and 3 giving the solution developers a set of techniques for presenting and evaluating solutions with users as well as techniques for prioritising evaluation results.

I opened this post by saying that designing for ease of use is not a simple exercise. Although there are only 3 steps listed above they all involve a lot of work, usually over a significant period of time. Adopting HCD techniques can help you increase the chances of a successful development. I’ll elaborate on the HCD techniques in a follow-up post.

Windows 8 Tablets – Two Tablets for Different Users?

November 18th, 2012

Tablet computers like the iPad are extremely convenient for mobile use, e.g. sending emails or browsing the internet. However they aren’t so handy for performing the kinds of task you might use a PC for, e.g. using Word or Excel. Personally, I love the iPad for browsing the internet but for data entry, e.g. using an application like Word or Excel, or even simple actions like copying and pasting text between web pages I much prefer using a PC.

Recently, Microsoft have released Windows 8 and at the same time a new Windows 8 tablet – the Microsoft Surface RT. At first glance the Microsoft RT seems like an ideal mix – a handy, touch-sensitive tablet like the iPad that will also run your familiar applications like Word, Excel (or even our own SliQTools applications :)). However, bear in mind that there is more than one form of the new tablet and you should make sure you are buying the correct version.

microsoft-surface

Microsoft Surface RT – an iPad-like device

The current release of the Surface is the Microsoft Surface RT.

The first thing to know is that the current Microsoft Surface – the Microsoft Surface RT – will NOT run the normal desktop applications you can run on Windows 7. The Surface RT is much more like an iPad than a laptop computer running Windows 7 and the Surface RT will only run the new tablet-like Windows Apps, purchased from the new Microsoft Windows Store. The new Windows 8 Apps are more like iPad apps than the normal programs we’ve all been running on Windows 7.

The exception to the “does not run old application rule” for the Surface RT is that it does comes preloaded with a special version of Microsoft Office 2013 specifically designed for the RT so you can work with your older Word and Excel documents on the new RT.

Microsoft Surface Pro – Laptop PC + iPad-like device in one

In the new year, Microsoft will release the Microsoft Surface Pro. This is the killer machine in my view. It will work like an iPad, with a touch-sensitive screen, run the new Windows 8 Apps from the Microsoft Windows store, but also run ALL your old programs that you were using on Windows 7, Vista, XP etc. The Surface Pro will cost more than an iPad but will double up as a laptop with a proper keyboard and mouse pad for effective data entry.

One clear area where the new Surface machines win out on over the iPad or Android tablets is in connectivity. The Surface machines come with USB ports,  microSD card slot, headphone, micro-HDMI, keyboard dock and charging ports as well as an in-built camera.

Conclusion

Information on the new Microsoft Surface and Windows 8 releases can be confusing. Make sure you know what you want to do with the Surface and that you are choosing the right version when you buy. Personally, I’m waiting for the Surface Pro to be released as the ability to browse the internet conveniently as I can with my iPad but also run my normal desktop apps means I’ll get the best of both worlds in terms of portability and flexibility.

For more Windows 8 topics, see http://www.sliqtools.co.uk/blog/windows-help/windows-8-how-to-set-live-mail-as-the-default-email-client/ and http://www.sliqtools.co.uk/blog/general/how-to-turn-off-a-windows-8-pc/.

Problems running .Net 2.0 programs on Windows 8

November 1st, 2012

Unlike Windows 7,  a Windows 8 install does not always include .Net 3.X and .Net 2.X versions. I’ve upgraded a Windows 7 PC which already had the older versions of the .Net frameworks installed and the frameworks were preserved in Windows 8 but on a fresh install to a PC only .Net 4.5 was included.

Since .Net 2.0 is not always present on Windows 8, this makes it difficult to know whether older programs will run successfully. It turns out that support for .Net 2.0 and 3.5 is an optional part of Windows 8. Quite why they’re optional I don’t know. However, if you are trying to run an older program on Windows 8 and as soon as you try to run it, Windows says “XXX has stopped working”, the first thing I’d recommend checking is whether .Net 2.0 and 3.5 are included.

With earlier versions of Windows, you’d have to manually download and install the frameworks but Windows 8 includes a neat way of adding features like the .Net framework. For those unfamiliar with Windows 8 (which included me), finding the features dialog took some searching. Here’s how to find the dialog and turn on support for the older .Net 2.0 and .Net 3.5 frameworks:

1. Show the Windows 8 charms (a set of buttons down the right hand edge of the screen), by moving your mouse cursor into the very top right corner of the screen as shown in the following picture:

windows8charmsmousemovement

I must say this way of bringing up the charms didn’t feel very intuitive, especially as I had to move the mouse right to the very top of the screen rather than just to the right where the actual charms buttons appear.

2. Press the Search charm button to bring up the Search panel. Then click on the Settings button and type in Windows Features to the search box:

windows8search

Windows will then show the Settings items matching “windows Features” on the left of the screen.

3. Click on the Turn Windows Features On and Off button:

windows8turnwindowsfeaturesonandoff

Windows will then show the Windows Features dialog.

4. In the Windows Features dialog, make sure that the .Net Framework 3.5 (includes .Net 2.0 and 3.0) option is checked:

Windows8WindowsFeaturesDialog

5. Then click OK.

Windows 8 will then install the required files. At the end of the install, a reboot may be required. After the reboot, older programs needing .Net 2.0 or 3.0 etc. should run OK.

Visual Studio and the breakpoint that won’t go away

October 11th, 2012

For the past couple of years I’ve had a breakpoint in a piece of code that wouldn’t go away. From time to time I’d run the offending piece of code in the debugger and hit the breakpoint when I didn’t want to.

The project was originally in Visual Studio 2008 and for a few months I lived with the debugger breaking at a certain point in the code. Once the breakpoint was hit I could remove the breakpoint by clicking on the source line and pressing F9. However, if I stopped and restarted the debugger, the breakpoint reappeared.

Recently I upgraded the project to Visual Studio 2010 and the breakpoint still refused to go away permanently. Turns out all I had to do to get rid of the breakpoint permanently was go to the Debug menu and click the Delete All Breakpoints option. Now the project is free of all unwanted breakpoints.

Storing Images in XML files using C#

September 29th, 2012

XML files contain data in the form of text. Any data can be stored in and retrieved from an XML file as long as you can convert the data to text before writing to the XML file and then convert the text from the XML file into the correct data type when reading it back.

To convert and image in to a string so that you can store the image in an XML file, there are a couple of steps to go through:-

1. Convert the image to an array of bytes.
2. Convert the array of bytes to a string.

For this second step there is already a standard encoding scheme – Base64 – for encoding binary (byte) data into a string format. Luckily for both these conversion steps, .Net already includes the necessary classes and methods to do the work for us.

Here is a C# example of converting a PNG file into a string that could then be stored in an XML file:

String TheImageFile = @”c:\about.png”;

Image TheImage = Image.FromFile(TheImageFile);

TypeConverter converter = TypeDescriptor.GetConverter(typeof(Image));

String TheImageAsString = Convert.ToBase64String((Byte[])converter.ConvertTo(TheImage, typeof(Byte[])));

Converting back from a string to an image is a matter of reversing the steps …

Byte[] TheImageAsBytes = Convert.FromBase64String(TheImageAsString);

MemoryStream MemStr = new MemoryStream(TheImageAsBytes);

Image I = Image.FromStream(MemStr);

If you have a document containing a mix of text and images that you want to tidily save into a single file, you can use code like the above to easily store any embedded images as well as the text.

Windows OS Usage as Windows 8 approaches

September 3rd, 2012

With Windows 8 due out in late October this year, I thought I’d summarise some stats on existing OS usage.

As the picture below shows the most, Microsoft operating systems still dominate the desktop market in the UK with OS X being the main Mac OS in use at 11% of the market. I’ve also included iOS (iPad) for comparison. A good proportion of the people we encounter using OS X also run Windows (usually Windows 7) under some kind of virtualisation software such as Parallels or VMWare which tends to weaken the figure for OS X a little. Showing stats for the mobile market would give a total reverse of course, with Apple OSes dominating while Microsoft OSes take the minority share.

OSShare

The real success story in these figures for Microsoft is Windows 7 which has grown to half the market share in little more than 2 1/2 years where its predecessor Vista crept up to about 19% of the market in roughly the same time.

The latest news from Microsoft is that Windows 8 will be available as an upgrade for only £24.99 in the UK. What’s even more surprising is that the upgrade will be available to owners of Windows XP and Vista as well as Windows 7. This means that people who haven’t bought a Microsoft OS for nearly 12 years will be able to upgrade for a very small fee.

It’s exciting times for Microsoft OSes and developers over the next few months with Windows 8 and the new Microsoft Surface tablet being released. Personally, although my wife wanted an iPad for her birthday, I can’t wait to get my hands on a Surface tablet. There has been quite a lot of negative press about Windows 8, with a lot of complaints about the loss of the Start menu that has been a feature of every Microsoft Windows OS since Windows 95. As time has gone on though, I’ve now begun to think of the Windows Metro interface as the Start menu replacement and Windows 8 has begun to feel even quicker and more fluid than Windows 7.