ASP.NET MVC Model binding to a list.

(scroll down for an in depth explanation)

I’m writing this post since I had a lot of problems finding out how Model binding works in ASP.NET MVC.

This behavior has changed in the beta and the final. This causes that some blog posts on the internet are inaccurate.

But let’s set things straight.

Create a MVC Project, leave everything default and add Product in your Models folders with the following (very simple) code:

namespace BlogPost.Models
{
    public class Product
    {
        public string Name { get; set; }
    }
}

Then add a ProductsController (in the Controllers folder) with the following code:

using System.Collections.Generic;
using System.Web.Mvc;
using BlogPost.Models;

namespace BlogPost.Controllers
{
    public class ProductsController : Controller
    {
        public ActionResult Add()
        {
            return this.View();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Add(IList<Product> products)
        {
            return this.View();
        }
    }
}

And add the following view for the Add function:

image

With the following markup:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Add up to 10 products to the database
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>
        Add up to 10 products to the database</h2>
    <%
        using (Html.BeginForm())
        {
            for(int x = 0;x <= 9;x++)
            {
                %>
                <fieldset>
                    <legend>Product <%=x %>:</legend>
                    <input type="text" name="products[<%=x %>].Name" />
                </fieldset>
                <%
            }

            %><input type="submit" name="submitForm" value="Save products" /><%
        }
    %>
</asp:Content>

Now put a breakpoint in the Add function in your ProductsController that handles the Http Post.

image

Hit f5 and go to <your url>/Products/Add:

image

Enter 10 names, and hit the submit button at the bottom.

Visual Studio will break on your this.View(). Hover over your products parameter and you’ll see something in the lines of this:

image

Not too hard is it?

A little bit more in depth:

ASP.NET MVC binds your HTML input to your parameter through the default model binder. I recommend you read the source code available on http://aspnet.codeplex.com/SourceControl/changeset/view/23011

image

If you want to step through the source code using your application I refer you to Steve Sanderson’s excellent blog post.

If you take a look at the generated HTML source code you’ll notice this:

<fieldset>
    <legend>Product number 0:</legend>
    <input type="text" name="products[0].Name" />
</fieldset>
<fieldset>
    <legend>Product number 1:</legend>
    <input type="text" name="products[1].Name" />
</fieldset>

The name ‘products’ is VERY important, since this specifies that it your input should be bound to the ‘products’ parameter in your controller action.

Then the index between brackets: IT MUST START FROM 0 AND BE CONTINUES!

Then the .Name, which specifies that your input should be placed in the Name property (not just a public variable, but a property with a get/set) (see code above).

You can repeat this for multiple properties, and group them by product.

That’s it for simple model binding.

Hope it helps.

Cast vs ‘as’

What’s the difference?

object dinner = new Dinner();
Dinner myDinner2 = (Dinner) dinner;
Dinner myDinner = dinner as Dinner;

Well, the first cast (which is really a cast) throws an error if dinner is null.

The second one doesn’t, so you have to check that by yourself.

Also see the MSDN reference on the ‘as’ keyword.

WinForms: Labels and ampersands

Today I bumped into this problem at work. I had a label on a form and I had to display an employee’s department.

Quite easy, but the department sometimes contains an ampersand. And that ampersand was not displayed. I went looking for this problem and I bumped into this property (in System.Windows.Forms.Label): Label.UseMnemonic Property

Setting this property true means: an ampersand that precedents a character underlines that character, so that it can be used in conjunction with the alt key.

The problem arises when you for example pull a department from the database with an ampersand (for example: shipping & hauling). Putting this into the label causes the & not to be displayed since the label assumes that the ampersand means ‘underline the character after the ampersand’.

To display the ampersand you’ve got two choices:

  1. set UseMnemonic to false so that it doesn’t parse the ampersand.
  2. if you need the mnemonic: replace the & with &&, that displays 1 ampersand in the label.

LINQ to Entities: EntityReference

When creating one to many relationships one might bump into the following problem:

Consider the following database design:

Tables:

Customers
-Id
-FirstName
-LastName
-…snip…
-City

Cities
-Id
-Name
-Zip

With a many to one relation from Customers.City to Cities.Id

While this is easy to do in SQL, the LINQ to Entities syntax might seem a bit different.

Consider the following piece of code:

City c = (from city in ctx.CitySet
where city.Name == cityName && city.Zip == cityZip
select city).FirstOrDefault();

This selects the city (if it exists) or null.

Now the problem is: IF the city exists, how do I point the current customer’s city to that particular city.

I tried this:

//customer is a customer object
customer.City = c;

But that resulted in duplicate cities in the database.

The solution was actually quite easy, I browsed through all the properties (Intellisense!) and found this:

customer.CityReference.EntityKey = c.EntityKey;

This resulted in the one to many relationship I had in mind. No duplicate cities in my database.

I love database normalization!

WPF: FileDialogs on Vista 64-bit, use the Manifest!

Rick Brewster made this comment on my previous post about the Inconsistent FileDialogs.

So I decided to fire up his solution:

I’ve created an empty WPF project, with a Window called ‘Main’ with the following code:

using System.Windows;
using Microsoft.Win32;

namespace OpenFileDialogNewStyle
{
	///

	/// Interaction logic for Main.xaml
	/// 

	public partial class Main : Window
	{
		///

		/// Constructor
		/// 

		public Main()
		{
			this.InitializeComponent();

			OpenFileDialog myOpenFileDialog = new OpenFileDialog();

			myOpenFileDialog.ShowDialog();
		}
	}
}

This opens the ‘old’ style FileDialog, with the outdated icons.

old-filedialog

To resolve this you can add a manifest in your project:

add-manifest

The manifest should be named NameOfYourStartUpProject.exe.manifest (as pointed out above), it should be a text file containing the following code:



	
	Description
	
		
			
		
	

Change the name on the 5th line to the name of your project!

Now go to properties and point to the manifest.

select-manifest

Now compile, and test if you see the new type icons :)

new-filedialog

Entity Framework: SDF: Server-generated keys and server-generated values are not supported by SQL Server Compact.

(My friend Peter pointed me to this so I am writing this on his behalf)

Basic setup:

A simple application, an SDF (Microsoft SQL Server Compact file) and the Entity Framework.

So I created the project, added the files, created the tables, made a model, and wrote this class:

namespace LinqToEntities
{
	class Program
	{
		static void Main(string[] args)
		{
			using (Database1Entities ctx = new Database1Entities())
			{
				Test myTest = new Test() { Value1 = "Blah", Value2 = "Blah2" };

				ctx.AddToTestSet(myTest);

				ctx.SaveChanges();
			}
		}
	}
}

And this gives me a nice error on ctx.SaveChanges();sqlserver-ce

(Big image!!!)

The problem is not the database, like the error says. But the problem is that the EF just doesn’t understand it.

Here are some ‘workaround’, I quote it because I don’t really consider them a workaround.:

  • Disable autoincrement, and manually fetch the highest id, and then insert. This could lead to corruption if you are in a multi threaded  environment.
  • Use a SqlCeCommand

But it’s a breaking issue I think, and I hope they fix it in the next version.

WPF: Inconsistent FileDialogs on Vista 64-bit.

You might run into this problem:

When you try to make an Open/SaveFileDialog on in a WPF program, you might see that the dialog is displayed with the old graphics:

savefiledialog

*yuk*

This seems to be caused by a detection inconsistency somewhere inside the Microsoft.Win32.

To solve the problem you could manually add a Reference to System.Windows.Forms, and use the System.Windows.Forms.OpenFileDialog or the System.Windows.Forms.SaveFileDialog.

This will display the beautiful Open/SaveFileDialog on Vista 64-bit.

Good luck :)

C#: Structs and parameters

struct MyStruct
{
	public int X { get; set; }
	public int Y { get; set; }

	public MyStruct(int x, int y)
	{
		this.X = x;
		this.Y = y;
	}
}

Will trigger an error on line 8:

The ‘this’ object cannot be used before all of its fields are assigned to

So I thought I might fix it by assigning a value to the fields. Since we have automatic properties, let’s convert them to normal properties:

struct MyStruct
{
	private int _x = 0;
	public int X
	{
		get
		{
			return _x;
		}
		set
		{
			_x = value;
		}
	}
	private int _y = 0;
	public int Y
	{
		get
		{
			return _y;
		}
		set
		{
			_y = value;
		}
	}

	public MyStruct(int x, int y)
	{
		this.X = x;
		this.Y = y;
	}
}

Let’s press F5. Oeh noes, another error:

‘MyStruct._x’ cannot have its instance field initializers in structs

So you can’t do field initialization in a struct (apart from in a function / constructor / getter / setter).

Let’s go back to the first piece of code and make it work by adding 7 characters:

struct MyStruct
{
	public int X { get; set; }
	public int Y { get; set; }

	public MyStruct(int x, int y) : this()
	{
		this.X = x;
		this.Y = y;
	}
}

The this() initializes the struct, and in the constructor itself the struct’s vars & properties are set to their default values. It’s weird though that an int needs initialization…

C#: Extending Outlook.(_)Application.

Does not work.

Outlook.Application and Outlook._Application are both interfaces. And I want to use them as a class in my program (I don’t know how they made that work).

I wanted to extend Outlook.Application and add a simple method to create a new email. But that does not work since you have to implement a bunch of methods which I hardly understand.

Thank Microsoft for creating extension methods, so here is my solution:

using System;
using Outlook = Microsoft.Office.Interop.Outlook;

namespace SendToExtended
{
	static class OutlookExtensions
	{
		///

		/// Creates and returns an Microsoft Outlook MailItem
		/// 

		///
an instantiated Outlook application
		/// A new MailItem object
		public static Outlook.MailItem CreateMailItem(this Outlook.Application outlook)
		{
			if (outlook == null)
				throw new ArgumentException("outlook parameter cannot be null");

			return (Outlook.MailItem)outlook.CreateItem(Outlook.OlItemType.olMailItem);
		}
	}
}

A fluent approach to C# parameter validation

Normally I don’t do this, but since this is such a great article:

http://blog.getpaint.net/2008/12/06/a-fluent-approach-to-c-parameter-validation/

From the creator of Paint.NET.

It’s really worth reading, if you do a lot of parameter validation. It might come in handy for your forms, or maybe even for a website.

I think I’ll write something based on that really soon :)