Posts Tagged ‘ASP.NET MVC’

Presenting at the Microsoft Web Partner event Oct. 7th

No Comments »

I will be giving a high-level presentation on the ASP.NET MVC framework at Microsoft’s Web Partner event on October 7th.

Participation is free for web partners. Register here.

Update: The slides for the presentation are now available here.


MVC Model Binding to an interface

No Comments »

Have you ever tried using ASP.NET MVC’s data binding capabilities against an interface? If so, you may have experienced some unexpected behaviour.

Let’s say we’ve got a form with two fields that we want to post to a Create action. In the Create action we’ll usually databind the fields to properties of a business object and persist the object to the database. For this example, we’ll just perform the data binding and display the bound values.

Our Order class is very simple:

public class Order : IOrder
{
    public int Id { get; set; }
    public string Text { get; set; }
}

Our form for submitting an order is equally simple:

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

<asp:Content ID="indexTitle" ContentPlaceHolderID="TitleContent" runat="server">
    Home Page
</asp:Content>

<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
    <h2><%= Html.Encode(ViewData["Message"]) %></h2>

     <% using (Html.BeginForm("Create", "Home")){ %>
        <fieldset>
        <legend>Order:</legend>
            Id:<br />
            <%= Html.TextBox("order.Id") %> <br />
            Text:<br />
            <%= Html.TextBox("order.Text") %><br />
        </fieldset>
    <%} %>
</asp:Content>

We’ve got a Create action like this

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(FormCollection form)
{
    Order order = new Order();
    UpdateModel(order, "order", form.ToValueProvider());

    ViewData["Id"] = order.Id;
    ViewData["Text"] = order.Text;

    return View();
}

and a corresponding view which displays the values:

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

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Create
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Create</h2>
    <p>Data used for create:</p>
    <p>
        Id: <%= ViewData["Id"] %> <br />
        Text: <%= ViewData["Text"] %>
    </p>


</asp:Content>

When we enter a pair of values like so

forminput

we will see this upon submitting

result1

However, what happens if we try to databind to a reference of type IOrder? The IOrder interface looks like this

public interface IEntity
{
    int Id { get; set; }
}

public interface IOrder : IEntity
{
    string Text { get; set; }
}

If we change the Create action to use an IOrder reference like so

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(FormCollection form)
{
    IOrder order = new Order(); //This line has been changed
    UpdateModel(order, "order", form.ToValueProvider());

    ViewData["Id"] = order.Id;
    ViewData["Text"] = order.Text;

    return View();
}

we will se a somewhat surprising result:

result2 

What happens is that the posted value is not bound to the Id property of IOrder! The reason for this turns out to be that the Id property is declared in the IEntity interface. If you move the Id property from IEntity to IOrder, things will again be working as expected.

Tihs is something to keep in mind when you’re considering what to use for databinding in your application. If all your business objects are encapsulated in interfaces once they get to the web tier, you may have to provide special types for use in databinding, even though this to some extent defeats the purpose of databinding..

I have previously written a blog post about why this behaviour occurs: Hey, where are my interface’s properties?