-1

My application can search for one type of tag in the XML which is: 'title', but nothing else. I want the user to be able to search for anything in the file with multiple fields and with part strings... What have I done wrong here?

Model:

using System;

namespace Andre_Kordasti___Programmeringsuppgift.Models
{
    public class BookModel
    {
        public string Author { get; set; }
        public string Title { get; set; }
        public string Genre { get; set; }
        public decimal Price { get; set; }
        public DateTime PublishDate { get; set; }
        public string Description { get; set; }
    }
}

View:

   @model IEnumerable<Andre_Kordasti___Programmeringsuppgift.Models.BookModel>

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Sök</h2>


@using (Html.BeginForm("Index", "Home", FormMethod.Get))
{
    <p>
        Författare: @Html.TextBox("author") <br /><br />
        Titel: @Html.TextBox("title") <br /><br />
        Genre: @Html.TextBox("genre") <br /><br />
        Pris: @Html.TextBox("price") <br /><br />
        Publicerad: @Html.TextBox("publishDate") <br /><br />
        Beskrivning: @Html.TextBox("description") <br /><br />

        <input class="btn btn-primary" type="submit" value="Sök" />
    </p>
}

<div id="bok">
    @foreach (var book in Model)
    {
        <p>Author: @Html.DisplayFor(m => book.Author)</p>
        <p>Title: @Html.DisplayFor(m => book.Title)</p>
        <p>Genre: @Html.DisplayFor(m => book.Genre)</p>
        <p>Price: @Html.DisplayFor(m => book.Price)</p>
        <p>Publish Date: @Html.DisplayFor(m => book.PublishDate)</p>
        <p>Description: @Html.DisplayFor(m => book.Description)</p>
        <hr />
    }
</div>

Controller:

using System;
using System.Linq;
using System.Web.Mvc;
using System.Xml.Linq;
using Andre_Kordasti___Programmeringsuppgift.Models;

namespace Andre_Kordasti___Programmeringsuppgift.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index(string author, string title, string genre, decimal? price, string description)
        {
            const string FILENAME = @"c:\users\andre\documents\visual studio 2015\Projects\Andre Kordasti - Programmeringsuppgift\Andre Kordasti - Programmeringsuppgift\DataSource\books.xml";

            XDocument doc = XDocument.Load(FILENAME);

            var books = doc.Descendants("book").Select(x => new BookModel()
            {
                Author = (string)x.Element("author"),
                Title = (string)x.Element("title"),
                Genre = (string)x.Element("genre"),
                Price = (decimal)x.Element("price"),
                PublishDate = (DateTime)x.Element("publish_date"),
                Description = (string)x.Element("description")
            });

            //if (!String.IsNullOrEmpty(searchString))
            //{
            //    books = books.Where(s => s.Author.Contains(searchString) || (s.Title.Contains(searchString)) || (s.Genre.Contains(searchString)) || (s.Description.Contains(searchString)));
            //}

            if (author != null)
            {
                books = books.Where(b => b.Author.Contains(author));
            }

            if (title != null)
            {
                books = books.Where(b => b.Title.Contains(title));
            }

            if (genre != null)
            {
                books = books.Where(b => b.Genre.Contains(genre));
            }

            if (price.HasValue)
            {
                books = books.Where(b => b.Price <= price.Value);
            }

            if (description != null)
            {
                books = books.Where(b => b.Description.Contains(description));
            }

            return View(books);
        }

        public ActionResult Fibonacci()
        {
            return View();
        }
    }
}

XML File:

<?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>
  <book id="bk103">
    <author>Corets, Eva</author>
    <title>Maeve Ascendant</title>
    <genre>Fantasy</genre>
    <price>5.95</price>
    <publish_date>2000-11-17</publish_date>
    <description>
      After the collapse of a nanotechnology
      society in England, the young survivors lay the
      foundation for a new society.
    </description>
  </book>
  <book id="bk104">
    <author>Corets, Eva</author>
    <title>Oberon's Legacy</title>
    <genre>Fantasy</genre>
    <price>5.95</price>
    <publish_date>2001-03-10</publish_date>
    <description>
      In post-apocalypse England, the mysterious
      agent known only as Oberon helps to create a new life
      for the inhabitants of London. Sequel to Maeve
      Ascendant.
    </description>
  </book>
  <book id="bk105">
    <author>Corets, Eva</author>
    <title>The Sundered Grail</title>
    <genre>Fantasy</genre>
    <price>5.95</price>
    <publish_date>2001-09-10</publish_date>
    <description>
      The two daughters of Maeve, half-sisters,
      battle one another for control of England. Sequel to
      Oberon's Legacy.
    </description>
  </book>
  <book id="bk106">
    <author>Randall, Cynthia</author>
    <title>Lover Birds</title>
    <genre>Romance</genre>
    <price>4.95</price>
    <publish_date>2000-09-02</publish_date>
    <description>
      When Carla meets Paul at an ornithology
      conference, tempers fly as feathers get ruffled.
    </description>
  </book>
  <book id="bk107">
    <author>Thurman, Paula</author>
    <title>Splish Splash</title>
    <genre>Romance</genre>
    <price>4.95</price>
    <publish_date>2000-11-02</publish_date>
    <description>
      A deep sea diver finds true love twenty
      thousand leagues beneath the sea.
    </description>
  </book>
  <book id="bk108">
    <author>Knorr, Stefan</author>
    <title>Creepy Crawlies</title>
    <genre>Horror</genre>
    <price>4.95</price>
    <publish_date>2000-12-06</publish_date>
    <description>
      An anthology of horror stories about roaches,
      centipedes, scorpions  and other insects.
    </description>
  </book>
  <book id="bk109">
    <author>Kress, Peter</author>
    <title>Paradox Lost</title>
    <genre>Science Fiction</genre>
    <price>6.95</price>
    <publish_date>2000-11-02</publish_date>
    <description>
      After an inadvertant trip through a Heisenberg
      Uncertainty Device, James Salway discovers the problems
      of being quantum.
    </description>
  </book>
  <book id="bk110">
    <author>O'Brien, Tim</author>
    <title>Microsoft .NET: The Programming Bible</title>
    <genre>Computer</genre>
    <price>36.95</price>
    <publish_date>2000-12-09</publish_date>
    <description>
      Microsoft's .NET initiative is explored in
      detail in this deep programmer's reference.
    </description>
  </book>
  <book id="bk111">
    <author>O'Brien, Tim</author>
    <title>MSXML3: A Comprehensive Guide</title>
    <genre>Computer</genre>
    <price>36.95</price>
    <publish_date>2000-12-01</publish_date>
    <description>
      The Microsoft MSXML3 parser is covered in
      detail, with attention to XML DOM interfaces, XSLT processing,
      SAX and more.
    </description>
  </book>
  <book id="bk112">
    <author>Galos, Mike</author>
    <title>Visual Studio 7: A Comprehensive Guide</title>
    <genre>Computer</genre>
    <price>49.95</price>
    <publish_date>2001-04-16</publish_date>
    <description>
      Microsoft Visual Studio 7 is explored in depth,
      looking at how Visual Basic, Visual C++, C#, and ASP+ are
      integrated into a comprehensive development
      environment.
    </description>
  </book>
</catalog>

Is there anything I have to adjust in my LINQ statement?

Cleon
  • 157
  • 1
  • 2
  • 13
  • 1
    [Adding a Search Method and Search View](http://www.asp.net/mvc/overview/getting-started/introduction/adding-search) and [Sorting, Filtering, and Paging with the Entity Framework in an ASP.NET MVC Application](http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/sorting-filtering-and-paging-with-the-entity-framework-in-an-asp-net-mvc-application) –  Mar 12 '16 at 11:39
  • I dont have a DataBase so I dont know how Entity Framework will do here? – Cleon Mar 12 '16 at 11:42
  • What does that have to do with it. Whether you query a database or an XML file is irrelevant. –  Mar 12 '16 at 11:43
  • By best advice is to read the links I gave you. You also need to read the [help] files to understand what are appropriate questions on this site (and avoid the inevitable temporary question ban you will be given if you keep this up). SO is not a code writing service. Make an attempt. Show the code you tried and explain what you expect to happen and what is actually happening and we will be more than willing to help. –  Mar 13 '16 at 10:09
  • I have read the article and done what is said, I took your advice. I partly made it work but still not complete! Do you think you can help me this time? My question is now updated. – Cleon Mar 13 '16 at 10:41
  • First thing you will need to do is change the view to `@using (Html.BeginForm("Index", "Home", FormMethod.Get))` - by default `BeginForm` will be a POST, but you need to redirect to a GET. –  Mar 13 '16 at 10:46
  • Ok, that is done. And next? – Cleon Mar 13 '16 at 10:52
  • So what problems are you having? What is not working as expected? –  Mar 13 '16 at 10:53
  • I can only search for the title, I want to be able to search for everything! Genre, Author, Description, PublishDate, Price etc... – Cleon Mar 13 '16 at 10:56
  • That's an issue with you query. If you enter (say) "Computer" in the text box, the the first line `( books = books.Where(s => s.Title.Contains(searchString));` returns and empty collection. Then the 2nd line is trying to query the (now) empty collection. –  Mar 13 '16 at 11:01
  • Yes that is right. So do you have any solution for it...? – Cleon Mar 13 '16 at 11:01
  • I'm not sure exactly what you want to do (a better approach might be to have (say) a dropdownlist in addition to the textbox) but for the moment you can use an `OR` - `books = books.Where(s => s.Title.Contains(searchString) || s.Author.Contains(searchString) || s.Genre.Contains(.....etc...));` –  Mar 13 '16 at 11:04
  • I tried that. Look: 'books = books.Where(s => s.Title.Contains(searchString)) || (s => s.Author.Contains(searchString));' I get the error: "Operator || cannot be applied to operands of type 'IEnumerable' and 'lambda expression' – Cleon Mar 13 '16 at 11:06
  • Look again please. – Cleon Mar 13 '16 at 11:09
  • That is not the same as my comment - its `|| s.Author()` not `|| s => s.Author()` –  Mar 13 '16 at 11:09
  • Ah yes it worked. Thank you! Just one more question. Since my publishdate and price datatype is not string, it does not work to put them in there as and '||' statement. It says: 'decimal' does not contain a definition for 'Contains' and the best extension method overload 'QueryAble.Contains(IQueryable, string) requires a resceiver of type 'IQueryable'... Do you know how to solve this? – Cleon Mar 13 '16 at 11:15
  • Well you could do a conversion in the query, but that does not really make sense. Would you really expect a user to enter `27.45` and return only books that are exactly `$27.45`? You really should be having multiple form controls to search different properties, for example 2 text boxes where you might enter a price range (or maybe just one to for search books to a maximum price of x). Ditto for date - you might just enter the year and search all books published that year. –  Mar 13 '16 at 11:21
  • Yeah I mean your right, I would rather have 1 textbox for each category, but I dont know how to, it would be great! You think I can copy the query and make another if statement and make another Html.BeginForm and make it work? – Cleon Mar 13 '16 at 11:26
  • You just need one form, but multiple textboxes (and/or dropdownlists) - say `@Html.TextBox("title")` and `@Html.TextBox("maxprice")` (with associated labels) and then change the method to accept multiple parameters - `public ActionResult Index(string title, decimal? maxPrice, etc)` and then you can adjust the query - `if (title != null) { books = books.Where(b => b.Title.Contains(title)); } if (maxPrice.HasValue) { books = books.Where(b => b.Price <= maxPrice.Value); }` etc. –  Mar 13 '16 at 11:35
  • Ok I did that and I edited the post with the new code. The problem is still there, I can only search for the first field which is 'Author', when I try to search in the other textboxes, it gives me nothing, and when I try to combine multiple textboxes, it gives me nothing. I also tried to use DateTime in my parameter for publishDate, and I got an error for that also. Do you know why this is? – Cleon Mar 13 '16 at 11:48
  • The code you have shown will work fine if you were to enter say "Tim" (for `Author`) and "Computer" (for `Genre`) - it would return books `bk110` and `bk111`. But I need some sleep. And you need to understand how to use this site. Its one question at a time, and you cannot keep editing your question based on comments and then ask new questions in comments. The question already has 3 close votes and will probably be closed soon. –  Mar 13 '16 at 12:00
  • I suggest you consider deleting this and asking a new question focusing on one issue at a time, and clearly explaining what your trying to achieve, showing the relevant code, and explain what is not working, for example what error message you get, or that you expect to get X, but you actually getting Y. –  Mar 13 '16 at 12:02

1 Answers1

0

You have to add Where clause before Select and call function for filter:

var results = doc.Descendants("book").Where(d => IsMatched(d, searchCriteria).Select(x => new BookModel()
        {
            Author = (string)x.Element("author"),
            Title = (string)x.Element("title"),
            Genre = (string)x.Element("genre"),
            Price = (decimal)x.Element("price"),
            PublishDate = (DateTime)x.Element("publish_date"),
            Description = (string)x.Element("description")
        }).ToList();

public bool IsMatched(XElement node, Dictionary<string, string> searchCriteria)
    {
        foreach (var key in criteras)
        {
            if (!node.Element(key.Key).Value.Contains(key.Value))
            {
                return false;
            }
        }
        return true;
    }

You can pass searchCriteria from with jquery ajax: JS:

var dict = {};
dict['author'] = 'authorName';

$.post('/Home/Index/', { searchCriteria: dict });

Controller:

public ActionResult Index(Dictionary<string, string> searchCriteria)

Then, you pass it as a BookModel list to View.

Django
  • 222
  • 1
  • 5
  • Sure, but how do I connect that to my View? – Cleon Mar 12 '16 at 12:11
  • I edited about how to pass criterias from view. – Django Mar 12 '16 at 12:42
  • I dont think you know what you are doing my friend. – Cleon Mar 12 '16 at 12:59
  • i think you couldn't understand what i wrote and you cannot explain your problem properly. – Django Mar 12 '16 at 13:11
  • The changed to my code (previous posting) for results is the correct approach is you want to add a class. The dictionary code that is posted is very confusing. Ignore the IsMatched() method unless more details are included. – jdweng Mar 12 '16 at 17:05