Jeff Coon
Jeff Coon

Reputation: 1

Passing simple XML data from a controller to a view?

I am writing my first MVC application, and struggling with how best to pass data from my controllers to my views. I have a very simple XML document structured like this. (Yes, this is Magic: The Gathering data)

<setlist>
  <set>
    <name>Alara Reborn</name>
    <block>Shards of Alara</block>
    <cards>145</cards>
    <code>ARB</code>
  </set>
  <set>
    <name>Archenemy</name>
    <code>ARC</code>
  </set>
</setlist>

(note that some of the nodes like "Block" and "Cards" are optional.)

On my first attempt, I was trying this:

        ' Load the set info
        Dim doc As New System.Xml.XmlDocument
        doc = LoadXML("setinfo.xml")
        Dim listSet = doc.GetElementsByTagName("set")
        ViewData("sets") = listSet

Then in my view, I was attempting to access the XmlNodeList like this:

    <%
        If ViewData("sets").count > 0 Then
            For i = 1 To (ViewData("sets").count - 1)
    %>
            <tr>
                <td><%= ViewData("sets")(i).SelectSingleNode("code").InnerText%></td>
                <td><%= ViewData("sets")(i).SelectSingleNode("name").InnerText%></td>
                <td><%= ViewData("sets")(i).SelectSingleNode("block").InnerText%></td>
            </tr>
    <%
            Next
        End If
    %>

But I get an Object Block or With Block error when trying to access SelectSingleNode("block") on the second "set" node, since that node doesn't have a "block" node.

I also have a feeling that the way I'm approaching the view is all wrong. Is there a better way to get this simple XML data into the view so I can work with it?

Upvotes: 0

Views: 2472

Answers (2)

Aaron Carlson
Aaron Carlson

Reputation: 5762

A better way to pass your XML document to the view would be to create a class that represents your xml document, serialize your document into the type and then pass the instance of the class to the view.

One easy way to serialize your document into a class is to use the XmlSerializer.

Domain Class:

<System.Xml.Serialization.XmlRoot("setlist")> _
Public Class SetList
  Inherits List(Of SetItem)

End Class

<System.Xml.Serialization.XmlType("set")> _
Public Class SetItem

  <System.Xml.Serialization.XmlElement("name")> _
  Public Name As String
  <System.Xml.Serialization.XmlElement("block")> _
  Public Block As String
  <System.Xml.Serialization.XmlElement("cards")> _
  Public Cards As String
  <System.Xml.Serialization.XmlElement("code")> _
  Public Code As String

End Class 

Controller:

Public Class SetController
  Inherits System.Web.Mvc.Controller

  Function Index() As ActionResult

    Using reader As System.IO.FileStream = System.IO.File.OpenRead("SetInfo.xml")
      Dim xmlSerializer As New System.Xml.Serialization.XmlSerializer(GetType(SetList))
      Dim setList As SetList = xmlSerializer.Deserialize(reader)
      Return View(setList)
    End Using

  End Function

End Class

View (note this is a strongly typed view):

<%@ Page Language="VB" Inherits="System.Web.Mvc.ViewPage(Of VB.SetList)" %>

<html>
<head>
  <title>Test</title>
</head>
<body>
  <div>
    <table>
      <tr>
        <th>Code</th>
        <th>Name</th>
        <th>Block</th>
      </tr>
      <%For Each setItem In Model%>
      <tr>
        <td><%=setItem.Code%></td>
        <td><%=setItem.Name%></td>
        <td><%=setItem.Block%></td>
      </tr>
      <%Next%>
    </table>
  </div>
</body>
</html> 

Upvotes: 1

James Webster
James Webster

Reputation: 4114

You should consider creating a Set class (this will be the Model class in MVC) that the Controller loads the XML into. Then this Set class can then handle the absence of a 'block' element.

Binding your view directly to the serialised representation of your data is generally a bad idea. Even though this is just a first application it would be good to follow the 'rules' of the MVC pattern from the start, and you'll learn/understand more along the way!

Upvotes: 1

Related Questions