Let MVC Concatenate For You

We have all encountered the situation where we want to show user information on a form. Most people have a FirstName and a LastName (unless you're Prince or Bono) so we would usually show that data in two separate fields or columns. Here is a way to quickly and easily concatenate MVC ViewModel fields without having to use String.Format. Let MVC concatenate information you.

Firstly, let me set the scene with a simple "ViewModelUser" ViewModel.

namespace MyApp.Web.Models
{
    public partial class ViewModelUser
    {
		public int Id { get; set; }

		[Required("This is a required field")]
		[StringLength(50, ErrorMessageResourceName="ValidatedMaxLength", ErrorMessageResourceType=typeof(Generic))]
		[Display("UserName")]
		public string UserName { get; set; }

		[Required("This is a required field")]
		[StringLength(50, ErrorMessageResourceName="ValidatedMaxLength", ErrorMessageResourceType=typeof(Generic))]
		[Display("First Name")]
		public string FirstName { get; set; }

		[Required("This is a required field")]
		[StringLength(50, ErrorMessageResourceName="ValidatedMaxLength", ErrorMessageResourceType=typeof(Generic))]
		[Display("Surname")]
		public string LastName { get; set; }

		[Required("Email is a required field")]
		[StringLength(100, ErrorMessageResourceName="ValidatedMaxLength", ErrorMessageResourceType=typeof(Generic))]
		[Display("Email")]
		[RegularExpressEmailAttribute]
		[DataType(DataType.EmailAddress)]
		public string Email { get; set; }
	}
}

So now we have a number of fields that "describe" the ViewModelUser class.

A common use case for this is when we want to implement a simple CRUD mechanism. We want to make all users in the system available to an administrator and the most common way to do that is show a list screen, which displays all the users in a tabular format. The administrator can click one of the users in the table and will be directed to an Edit screen. Alternatively, the administrator could click a button to delete the intended user.

List Table

Let's take this table as an example.

UserName First Name Surname Email
Daffy Daffy Duck daffy@disney.com
Donald Donald Duck donald@disney.com
Mickey Mickey Mouse mickey@disney.com
Daisy Daisy Duck daisy@disney.com

You can see from this table that we have separated the first and last names. This is because we have separate fields in the database, which have flowed through to the ViewModel.

Here is the MVC razor code that renders the table. Take note of the fields in the razor code and how they relate to the fields of the ViewModelUser ViewModel.

@model IEnumerable<ViewModelUser>

<table class="table table-bordered">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.UserName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.FirstName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.LastName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Email)
            </th>
            <th></th>
        </tr>
    </thead>

    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.UserName)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.FirstName)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.LastName)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Email)
                </td>
                <td>
                    <input type="button" value="Edit" />
                    <input type="button" value="Delete" />
		</td>
            </tr>
        }
    </tbody>
</table>

Wouldn't it be better use of screen real estate if we combined the first and last name columns into one? That is quite to do.

Firstly, let's make a change to the ViewModel.

public int Id { get; set; }

[Required("This is a required field")]
[StringLength(50, ErrorMessageResourceName="ValidatedMaxLength", ErrorMessageResourceType=typeof(Generic))]
[Display("UserName")]
public string UserName { get; set; }

[Required("This is a required field")]
[StringLength(50, ErrorMessageResourceName="ValidatedMaxLength", ErrorMessageResourceType=typeof(Generic))]
[Display("First Name")]
public string FirstName { get; set; }

[Required("This is a required field")]
[StringLength(50, ErrorMessageResourceName="ValidatedMaxLength", ErrorMessageResourceType=typeof(Generic))]
[Display("Surname")]
public string LastName { get; set; }

[Required("Email is a required field")]
[StringLength(100, ErrorMessageResourceName="ValidatedMaxLength", ErrorMessageResourceType=typeof(Generic))]
[Display("Email")]
[RegularExpressEmailAttribute]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }

[Display("Full Name")]
public string FullName
{
	get
	{
		return FirstName + " " + LastName;
	}
}

Notice the property FullName. This is a simple concatenation of the FirstName and LastName fields. Now all we need to do it call that in our razor code. Here is the altered table code.

@model IEnumerable<ViewModelUser>

<table class="table table-bordered">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.UserName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.FullName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Email)
            </th>
            <th></th>
        </tr>
    </thead>

    <tbody>
        @foreach (var item in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.UserName)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.FullName)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Email)
                </td>
                <td>
                    <input type="button" value="Edit" />
                    <input type="button" value="Delete" />
                </td>
            </tr>
        }
    </tbody>
</table>

And that's all you have to do. You can use this approach with most ViewModel fields to make your razor code much more succinct and easier to write.

Til next time ...