Форма поиска с несколькими выпадающими списками ASP MVC

Я пытаюсь выполнить поиск с помощью формы с несколькими раскрывающимися списками, чтобы ограничить значения поиска, раскрывающийся список заполняется через модель представления.

модель просмотра: PesquisaHomeViewModel.cs

using System; 
using System.Collections.Generic; 
using System.Linq;
using System.Web; 
using MinisPT.Models;

namespace MinisPT.ViewModels {
     public class PesquisaHomeViewModel
     {
        public List<Marca> Marcas { get; set; }       
         public List<Modelo> Modelos { get; set; }
         public List<EstadoProduto> EstadosProdutos { get; set; }
     } 
}

это часть представления с формой: Home/Index.cshtml

@using (Html.BeginForm("Index", "ResultadosPesquisa", FormMethod.Get))
            {
                @Html.ValidationSummary(true)                 
                <div id="coluna1">
                <div class="coluna1_titulo">Marca</div>
                <div class="coluna1_DropDownList">
                    @Html.DropDownListFor(m => m.Marcas, new SelectList(Model.Marcas, "MarcaNome", "MarcaNome"), String.Empty)
                </div>
                <div class="coluna1_titulo">Modelo</div>
                <div class="coluna1_DropDownList">
                    @Html.DropDownListFor(md => md.Modelos, new SelectList(Model.Modelos, "ModeloNome", "ModeloNome"), String.Empty)
                </div>
                <div class="coluna1_titulo">Estado</div>
                <div class="coluna1_DropDownList">
                    @Html.DropDownListFor(e => e.EstadosProdutos, new SelectList(Model.EstadosProdutos, "EstadoProdutoTipo", "EstadoProdutoTipo"), String.Empty)
                </div>
                <span>
                    <input type="submit" value="Pesquisar" class="botaoPesquisa" />
                </span>                
           }

Как вы можете видеть из этой отправки, я вызываю индексное действие контроллера «ResultadosPesquisa», в этом контроллере я использую параметры формы и пытаюсь выполнить поиск по модели с именем «Anuncios» (это означает «Реклама» в мой язык)

ResultadosPesquisaController.cs :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Data;
using System.Data.Entity;
using MinisPT.Models;
using MinisPT.ViewModels;

namespace MinisPT.Controllers
{
    public class ResultadosPesquisaController : Controller
    {
        MinisPTEntities db = new MinisPTEntities();

        //
        // GET: /ResultadosPesquisa/
        public ActionResult Index(string Marcas, string Modelos, string EstadosProdutos)
        {
            var query = from m in db.Anuncios.Include(a => a.Marca).Include(a => a.Modelo)
                        where m.Marca.MarcaNome == Marcas
                        where m.Modelo.ModeloNome == Modelos
                        where m.EstadoProduto.EstadoProdutoTipo == EstadosProdutos
                        select m;

            return View(query.ToList());
        }
    }
}

который вызывает представление ResultadosPesquisa/Index.cshtml, где я должен отображать результаты позже:

@model IEnumerable<MinisPT.Models.Anuncio>

... (html stuff in here) 

<table>
    <tr>
        <th>
            Marca
        </th>
        <th>
            Modelo
        </th>
        <th>
            Estado
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(a => item.Marca.MarcaNome)
        </td>
        <td>
            @Html.DisplayFor(a => item.Modelo.ModeloNome)
        </td>
        <td>
            @Html.DisplayFor(a => item.EstadoProduto.EstadoProdutoTipo)
        </td>
    </tr>
}

</table>

*МОЯ проблема * запрос в ResultadosPesquisaController дает мне результаты только в том случае, если я помещаю значения во ВСЕ 3 раскрывающихся списка, если я выбираю значение только в одном из раскрывающихся списков, ничего не возвращается, но я хочу сделать все выпадающие списки необязательны, как я могу этого добиться?

Я подумал об одном возможном способе, используя библиотеку динамических запросов LINQ,

с использованием библиотеки динамических запросов LINQ, Скотт Гу

Таким образом, я мог бы построить запрос для первого действия с индексом с помощью набора операторов if (не очень элегантно) и перенаправить на второе действие, где я бы использовал предварительно созданный запрос с динамическим LINQ и выполнил его.

Если есть более элегантный способ сделать это, пожалуйста, сообщите мне.

Спасибо.


person Ricardo_Rodrigues    schedule 20.06.2012    source источник


Ответы (1)


То, как вы структурировали свой Linq, складывается как операция &&. Вам нужно изменить его на это:

var query = from m in db.Anuncios.Include(a => a.Marca).Include(a => a.Modelo)
            where m.Marca.MarcaNome == Marcas ||
                m.Modelo.ModeloNome == Modelos ||
                m.EstadoProduto.EstadoProdutoTipo == EstadosProdutos
            select m

Это должно возвращать результаты любого выбора.

Редактировать:
Основываясь на ваших комментариях ниже, возможно, вам лучше сложить их, используя вместо этого методы расширения. Поскольку это происходит в контексте данных (мое предположение, основанное на db.Anuncios), эти вызовы будут отложены до тех пор, пока они не будут фактически использованы.

var query = from m in db.Anuncios.Include(a => a.Marca).Include(a => a.Modelo)
            select m;

if (!string.IsNullOrWhitespace(Marcas))
    query = query.Where(m => m.Marca.MarcaNome == Marcas);

if (!string.IsNullOrWhitespace(Modelos))
    query = query.Where(m => m.Modelo.ModeloNome == Modelos);

if (!string.IsNullOrWhitespace(EstadoProdutoTipo))
    query = query.Where(m => m.EstadoProduto.EstadoProdutoTipo == EstadosProdutos);

Конечный результат все равно будет IQueryable<T> для любого значения m, но поскольку предложения where не будут добавлены до тех пор, пока они не будут фактически вызваны. Это можно сделать с помощью синтаксиса запроса, который вы использовали, но он становится очень уродливым и сложным. Это выглядит немного чище и проще в обслуживании IMO.

person Joel Etherton    schedule 20.06.2012
comment
Спасибо за быстрый ответ, Джоэл, он возвращает любой из вариантов, но проблема в том, что он возвращает результаты для них по отдельности, я хочу, чтобы они складывались вместе следующим образом: первая dll имеет значение Marcas = A, а вторая dll имеет значение Modelos=B, поэтому результат должен иметь Marca A и Modelo B (между прочим, Marca означает Maker, а modelo означает модель), поэтому OR не собирается решать это так, как мне нравится. - person Ricardo_Rodrigues; 20.06.2012
comment
@Ricardo_Rodrigues: Итак, если я вас правильно понял, если вы выберете только 1 раскрывающийся список, вы хотите, чтобы он возвращал этот раскрывающийся список, но если вы выбираете 2 раскрывающихся списка, вы хотите, чтобы он возвращался, только если это оба. И вы хотите иметь возможность выбирать любой набор из 3 в любом порядке. - person Joel Etherton; 20.06.2012
comment
спасибо @Joel, решение, которое вы предоставили, решило мою проблему. - person Ricardo_Rodrigues; 21.06.2012