-1

I'm currently reviewing some tutorials using LINQ and XML with ASP.NET C#. I want to create a search page that reads an xml file and return the results in the Grid View after a button is clicked.

This is the XML File I'm attempting to search:

<?xml version="1.0"?>
<catalog>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications 
      with XML.</description>
   </book>
   <book id="bk102">
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-12-16</publish_date>
      <description>A former architect battles corporate zombies, 
      an evil sorceress, and her own childhood to become queen 
      of the world.</description>
   </book>
</catalog>

I have a Text box and search button:

 <asp:TextBox ID="searchtxt" runat="server" /> &nbsp; <asp:Button ID="search_btn" Text="Search" runat="server" OnClick="search_btn_Click" />

...the Grid View:

<div>
            <asp:GridView ID="gvSearch" runat="server" EmptyDataText="No Results found" Width="618px" AutoGenerateColumns="false" CssClass="gridviewsearch" GridLines="None">
            <Columns>
                 <asp:TemplateField HeaderText="Keyword">
                             <ItemTemplate>
                                <%# Eval("author")%>
                            </ItemTemplate>
                    </asp:TemplateField>
                    <asp:TemplateField HeaderText="Results">
                             <ItemTemplate>
                                <%# Eval("title")%>
                            </ItemTemplate>
                    </asp:TemplateField>
                     <asp:TemplateField HeaderText="URL">
                             <ItemTemplate>
                                <%# Eval("genre")%>
                            </ItemTemplate>
                    </asp:TemplateField>
            </Columns>
            </asp:GridView>
        </div>

...The code behind the button:

  protected void search_btn_Click(object sender, EventArgs e)
    {
        //1 .create a reference of XDocument 
        XDocument xdoc = XDocument.Load("database\\books.xml");

        xdoc.Descendants("book").Select(p => new
        {
            author = p.Attribute("author").Value,
            title = p.Element("title").Value,
            genre = p.Attribute("genre").Value

        }) .OrderBy(p => p.author).ToList().ForEach(p =>
        {
            gvSearch.DataSource = xdoc;
            gvSearch.DataBind();
        });
    }

...My question is, how do I implement the id: searchtxt into the back-end of the the code? In addition, am I on the right path, set-up and syntax-wise in accomplishing the task?

user1724708
  • 1,409
  • 7
  • 31
  • 53
  • You don't need the `ToList` between the `Select` and the `OrderBy` and honestly I'd recommend not getting into the habit of using `ToList` just so you can use `ForEach`. Instead just assign the result to a variable and use a regular `foreach` instead (It saves creating an intermediate list that you don't need) – juharr Feb 10 '18 at 18:20
  • try your code with `xdoc.Descendants("book")` not *catalog* – Eser Feb 10 '18 at 18:31
  • Thanks for the advise .. when I click the button I get an Object Reference not set to an instance of the object error at the following line: xdoc.Descendants("book").Select(p => new ...Am not sure how to tie searchtxt (the ID for the Text box into the back end. Do you have any suggestions? – user1724708 Feb 10 '18 at 18:59

1 Answers1

0

identify catalog descendants and iterate over book elements

var term = "rain";

var query = from element in document
                .Descendants("catalog")
                .Elements("book")
            let book = new
            {
                id = element.Attribute("id").Value,
                author = element.Element("author").Value,
                title = element.Element("title").Value,
                genre = element.Element("genre").Value
            }
            where book.author.ToLower().Contains(term)
                || book.title.ToLower().Contains(term)
                || book.genre.ToLower().Contains(term)
            select book;

that would give you

id|author|title|genre 
bk102|Ralls, Kim|Midnight Rain|Fantasy
Dan Dohotaru
  • 2,809
  • 19
  • 15
  • ...still, the ID value for the text box: searchtxt, how do I tie it into the back-end code? I believe that is what's generating the Object Reference error – user1724708 Feb 10 '18 at 20:04
  • in your code you treat `author` and `genre` as an attribute while it should be element most likely – Dan Dohotaru Feb 10 '18 at 20:10
  • for passing the search value to the underlying click handler, well that is very specific to asp.net, it's been too long since i haven't touched any of that stuff, but i guess the command argument should do the trick https://stackoverflow.com/questions/30461086/pass-parameter-into-a-function-with-aspbutton – Dan Dohotaru Feb 10 '18 at 20:13