Wednesday, 6 April 2011

Using XLinq & MVVM to Populate DDL for ASP.NET MVC

Making some adjustments to a website recently. It's not a heavily used beast, but my client required some dynamic functionality - pulling data from a semi-static data-source that he would be able to edit. Hooking up a SQL Server back-end would have been overkill, so I looked into XLinq as an alternative. I have tinkered with XLinq in the past but haven't ever found any particularly useful application for it. This time however it worked out beautifully.

Setup an MVVM for the page that I was working with and used a technique for loading the data that admittedly I need to credit to Sascha Barber. The technique is fantastic and works perfectly.


Here's my data, stored in a file name things.xml at http://things.com/things.xml:


<?xml version="1.0" encoding="UTF-8" ?>
<things>
<thing>
<name>-- STUFF --</name>
</thing>
<thing>
<name>THING ONE</name>
</thing>
<thing>
<name>THING TWO</name>
</thing>
...
</things>


Here's the MVVM:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Collections;
using System.Xml.Linq;

namespace ThingSite.Controllers.ViewModels
{
public class ThingsViewModel
{
...
public SelectList Things { get; private set; }
public Thing CurrentThing { get; private set; }

// constructor
public ThingsViewModel()
{
Things = new SelectList(GetThings(), "Text", "Value");
...
}

private IEnumerable GetThings()
{
string fullXmlPath = "http://things.com/things.xml";

var xmlThingResults =
from thing in Common.StreamElements(fullXmlPath, "thing")
select new SelectListItem
{
Text = thing.Element("name").Value,
Value = thing.Element("name").Value,
Selected = false
};

var list = xmlThingResults.ToList();
return list;
}
...


Here's the Common.StreamElements() static method (thanks Sascha!):


public static IEnumerable StreamElements(string uri, string name)
{
using (XmlReader reader = XmlReader.Create(uri))
{
reader.MoveToContent();
while (reader.Read())
{
if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == name))
{
XElement element = (XElement)XElement.ReadFrom(reader);
yield return element;
}
}
}
}


Here's the code that returns the MVVM from the Controller:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ThingSite.Controllers.ViewModels;

namespace ThingSite.Controllers
{
public class ThingBookingController : Controller
{
...
//
// GET: /ThingBooking/Create

public ActionResult Create()
{
return View(new ThingsViewModel());
}
...


And here's how it's used in the View to populate a DDL:


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

...
<% Html.EnableClientValidation(); %>
...

<td colspan="3">
<%:
Html.DropDownListFor(m => m.CurrentThing, Model.Things)
%>
<span class="validation"><%= Html.ValidationMessageFor(m => m.CurrentThing) %></span>
</td>
...


So providing he more-or-less knows how to edit an XML file (he does!) my client is able to go into the XML file and adjust the list of things available for the DDL to be populated by. I reckon that's a pretty nifty technique, for lightweight use.

No comments:

Post a Comment