Search code examples
c#asp.netxmlrepeaternested-repeater

ASP.NET Nested Repeater Issues


I am currently working on a ASP.NET Web Forms project where I need to display some deserialized XML data using nested repeaters for a Job Postings page.

The issues I am having is that the nested repeater is only showing the first item which is an XMLElement, and not showing the data from XMLAttribute that is a part of the element.

For instance the XML data looks as follows:

Jobs.xml

<Jobs>
  <Job Category="Administration" Title="Senior Human Resource Coordinator">
    <Description>
      <![CDATA[ Long description of the job goes here. ]]>
    </Description>
    <ShortDescription>
      <![CDATA[ Short description of the job goes here.  ]]>
    </ShortDescription>
    <JobLocations>
      <Location Salary="$50000">Toronto</Location>
      <Location Salary="£40000">London</Location>
    </JobLocations>
    <Benefits>Drug, Dental, Optical and Extended Healthcare Benefits</Benefits>
    <Jobtype>Full-Time</Jobtype>
  </Job>
  <Job Category="Administration" Title="Junior Human Resource Coordinator">
    <Description>
      <![CDATA[ Long description of the job goes here. ]]>
    </Description>
    <ShortDescription>
      <![CDATA[ Short description of the job goes here.  ]]>
    </ShortDescription>
    <JobLocations>
      <Location Salary="$50000">Toronto</Location>
      <Location Salary="£40000">London</Location>
    </JobLocations>
    <Benefits>Drug, Dental, Optical and Extended Healthcare Benefits</Benefits>
    <Jobtype>Full-Time</Jobtype>
  </Job>
</Jobs>

What I am looking to accomplish is get the first repeater to cycle through the "Job" and display the Category, Title, Description, etc. And in the nested repeater display the Job Location and its Salary.

So for example from the XML data displayed above the outcome would be as follows:

  • Category: Administration
  • Title: Senior Human Resource Coordinator
  • Description: ...
  • Short Description: ...
  • Location: Toronto
  • Salary: $50000
  • ...

then for the same job, display the data again but show the other location and salary...

  • Category: Administration
  • Title: Senior Human Resource Coordinator
  • Description: ...
  • Short Description: ...
  • Location: London
  • Salary: Category: Administration
  • Title: Senior Human Resource Coordinator
  • Description: ...
  • Short Description: ...
  • Location: London
  • Salary: £40000

Currently, the nested repeaters are only showing the first Job Location, then nothing for Salary, then move onto the next job without showing the other location and salary for the same job. I am not sure if this is because of a mistake I made with the structure of the repeater in my .aspx file, or because or a mistake in the .cs file I used for deserialization of the XML data. Please review the code provided below.

Jobs.cs

[Serializable]
public class Job
{
    [XmlAttribute]
    public string Category { get; set; }
    [XmlAttribute]
    public string Title { get; set; }
    [XmlElement]
    public string Description { get; set; }
    [XmlElement]
    public string ShortDescription { get; set; }

    public string Benefits { get; set; }
    [XmlElement]
    public string Jobtype { get; set; }

    [XmlElement("JobLocations")]
    public List<JobLocation> JobLocations { get; set; }

    public class JobLocation
    {
        [XmlElement("Location")]
        public string Location { get; set; }
        [XmlAttribute("Salary")]
        public string Salary { get; set; }
    }

    public static List<Job> Load(string path)
    {
        return SerializerSupport.DeserializeList<Job>(System.IO.Path.Combine(path, "jobs.xml"));
    }
}

JobCategories.aspx

<div class="flex-container">
  <div class="flex-row">
    <!-- Category Repeater -->
    <asp:Repeater ID="Job" runat="server" ItemType="COMPANY.Ecommerce.API.Models.Job" SelectMethod="JobGrid_GetData">
        <ItemTemplate>
          <div class="flex-item">
            <div>Title: <%#Item.Title%></div>
            <div>S.Desc: <%#Item.ShortDescription%></div>                
              <asp:Repeater runat="server" ItemType="COMPANY.Ecommerce.API.Models.Job+JobLocation" DataSource="<%#Item.JobLocations%>">
                <ItemTemplate>
                  <div>Location: <%#Item.Location%></div>  
                  <div>Salary: <%#Item.Salary%></div>

                </ItemTemplate>                                        
              </asp:Repeater>                  
            <div>
            </div>
            <div>Category: <%#Item.Category%></div>
            <div>Jobtype: <%#Item.Jobtype%></div>
            <div>Benefits: <%#Item.Benefits%></div>  
            <div>Desc: <%#Item.Description%></div>
          </div>  
        </ItemTemplate>        
    </asp:Repeater>
  </div>

Solution

  • As mentioned in the comment, I am not sure how your custom deserializer is parsing the XML data into objects. IMHO using Linq-to-XML is pretty simple here and its straight forward without any complexities:-

     public class Job
        {
            public string Category { get; set; }
            public string Title { get; set; }
            public string Description { get; set; }
            public string ShortDescription { get; set; }
            public string Benefits { get; set; }
            public string Jobtype { get; set; }
            public List<JobLocation> JobLocations { get; set; }
    
            public class JobLocation
            {
                public string Location { get; set; }
                public string Salary { get; set; }
            }
    
            public static List<Job> Load(string path)
            {
                static XDocument xdoc = XDocument.Load(path);
                return xdoc.Descendants("Job")
                           .Select(x => new Job
                           {
                               Category = (string)x.Attribute("Category"),
                               Title = (string)x.Attribute("Title"),
                               Description = (string)x.Element("Description"),
                               ShortDescription = (string)x.Element("ShortDescription"),
                               Benefits = (string)x.Element("Benefits"),
                               Jobtype = (string)x.Element("Jobtype"),
                               JobLocations = x.Element("JobLocations").Elements("Location")
                                               .Select(jl => new JobLocation
                                               {
                                                   Location = (string)jl,
                                                   Salary = (string)jl.Attribute("Salary")
                                               }).ToList()
                           }).ToList();
            }
        }