как правильно использовать ViewModels

Я создал простое приложение, в котором есть список продуктов и боковая панель с поисковым фильтром.(http://i.imgur.com/4tAHgiK.png) У меня возникла проблема с нумерацией страниц (с использованием PagedList), потому что после фильтрации результатов и перехода на следующую страницу (http://i.imgur.com/xh3SSN7.png) Я получал пустую страницу. Причина была ясна. Я получал данные в параметрах действия контроллера, поэтому после нажатия кнопки «Следующая страница» данные фильтра были потеряны. Поэтому я решил где-то хранить эти данные.

Мне сказали, что мне нужна ViewModel, поэтому я создал еще одну модель FilterModel с полями боковой панели:

public class FilterModel {
    public string Manufacturer { get; set; }
    public string Name { get; set; }
    public int? MinPrice { get; set; }
    public int? MaxPrice { get; set; }
}

а это Products модель

public partial class Products {
    [Key]
    public int ProductID { get; set; }
    public string Manufacturer { get; set; }
    public string Name { get; set; }
    ......
    public int Price { get; set; }
}

И поместите их в ViewModel:

public class HomeViewModel {
    public IPagedList<Products> Repository { get; set; }
    public FilterModel FilterView { get; set; }
}

это мои контроллеры — HomeController, который отображает каждый продукт, и SearchFilterController, который должен отображать отфильтрованные продукты:

public class HomeController : Controller {
    IProductRepository _repository;
    public HomeController(IProductRepository rep) {
        _repository = rep;
    }

    public ActionResult Index(int page=1) {
        ViewBag.Manufacturers = Manufacturers.ManufacturersList(_repository);
        var model =
            (from p in _repository.Product
             orderby p.Price descending
             select p).ToPagedList(page, 2);
        ViewBag.Title = "Home";
        return View(model);
    }
}

.

public class SearchFilterController : Controller {
        IProductRepository _repository;
        public SearchFilterController(IProductRepository rep) {
            _repository = rep;
        }

        [HttpPost]
        public ActionResult Filter(FilterModel filterModel, int page = 1) {
            ViewBag.Manufacturers = Manufacturers.ManufacturersList(_repository);
            var model =
                (from p in _repository.Product
                 where (p.Manufacturer == filterModel.Manufacturer || p.Name.Contains(filterModel.Name) || 
                    p.Price >= filterModel.MinPrice || p.Price <= filterModel.MaxPrice)
                 orderby p.Price descending
                 select p).ToPagedList(page, 1);
            ViewBag.Title = "Results";
            return View(model);
        }
    }

В обоих контроллерах я передаю модель views PagedList<Products>, но они должны получить HomeViewModel, я думаю.

вот мои взгляды: Index(HomeController)

@model SmartPhoneCatalog.Models.HomeViewModel
@using System.Linq
@using PagedList
@using PagedList.Mvc
@using SmartPhoneCatalog.Domain.Abstract

...

<div id="root">
     @Html.Partial("_Sidebar", Model)

     @Html.Partial("_ProductsList", Model)
</div>

<br>
<div class="pagedList" data-sc-target="#products">
    @Html.PagedListPager(Model.Repository, page => Url.Action("Index", "Home", new { page }),
                PagedListRenderOptions.ClassicPlusFirstAndLast);
</div>

Filter(SearchFilterController)

@model SmartPhoneCatalog.Models.HomeViewModel
@using System.Linq
@using PagedList
@using PagedList.Mvc
@using SmartPhoneCatalog.Domain.Abstract

...

<div id="root">
    @Html.Partial("_Sidebar", Model)

    @Html.Partial("_ProductsList", Model)
</div>

<br>
<div class="pagedList" data-sc-target="#products">
    @Html.PagedListPager(Model.FilterModel, page => Url.Action("Filter", "SearchFilter", new { page }),
                PagedListRenderOptions.ClassicPlusFirstAndLast);
</div>

Частичный вид: _Sidebar

@model SmartPhoneCatalog.Models.HomeViewModel
@using System.Linq
@using PagedList
@using PagedList.Mvc

    <div id="filter" class="left">
        @using (Html.BeginForm("Filter", "SearchFilter")) {
            <div>
                <b>Manufacturer:</b> <br>
                <select name="manufacturer" class="form-control">
                    <option>@null</option>
                    @foreach (var item in ViewBag.Manufacturers) {
                        <option>@item</option>
                    }
                </select><br>

                <b>Name:</b> <br>@Html.EditorFor(model=>model.FilterModel.Name)<br>
                <b>Price From:</b> <br>@Html.EditorFor(model => model.FilterModel.Name)<br>
                <b>To:</b> <br>@Html.EditorFor(model => model.FilterModel.Name)<br>
                <button type="submit" value="search"><b>Search</b></button>
            </div>
        }
    </div>

Я думаю, что у меня все правильно сделано в представлениях. но я не знаю, как правильно передать им модели, а привязка объектов выполняется правильно или нет.

Какие-либо предложения?

Редактировать: Хорошо, я сделал это в контроллерах: создал объект HomeViewModel и изменил это

var model =
            (from p in _repository.Product
             orderby p.Price descending
             select p).ToPagedList(page, 2);
return View(model);

в это:

_homeView.Repository =
            (from p in _repository.Product
             orderby p.Price descending
             select p).ToPagedList(page, 2);
return View(_homeView);

теперь все работает, кроме нумерации страниц после фильтрации результатов (почему я все это сделал :D). Поэтому я должен исправить привязку модели


person arsena    schedule 16.09.2014    source источник


Ответы (1)


привет, я выполнил ваш код .. ниже приведены изменения

Объявите такую ​​модель

public class FilterModel
{
    public string Manufacturer { get; set; }
    public string Name { get; set; }
    public int? MinPrice { get; set; }
    public int? MaxPrice { get; set; }
}

public partial class Products
{
    public int ProductID { get; set; }
    public string Manufacturer { get; set; }
    public string Name { get; set; }
    public int Price { get; set; }
}

public class HomeViewModel
{
    public IPagedList<Products> Repository { get; set; }
    public FilterModel FilterView { get; set; }
}

Методы действия контроллера (ов)

 public class PagingController : Controller
{
    int pagesize = 2;

    public ActionResult Index(int page = 1)
    {
        HomeViewModel _HomeViewModel = new HomeViewModel();

        //call service and get products list
        AgentServiceReference.AgentServiceClient ServiceClient = new AgentServiceClient();
        var productlist = ServiceClient.GetProducts().ToPagedList(page, pagesize);

        //set IPagedList<Products> to our HomeViewModel Repository property
        _HomeViewModel.Repository = productlist;

        // set view bag  this we use for Drop Down list
        SetViewBags();
        ViewBag.Title = "Home";
        return View(_HomeViewModel);
    }


    [HttpGet]
    public ActionResult Filter(int page = 1)
    {
        //call service and get products list
        AgentServiceReference.AgentServiceClient ServiceClient = new AgentServiceClient();
        var productlist = ServiceClient.GetProducts().ToPagedList(page, pagesize);

        //set IPagedList<Products> to our HomeViewModel Repository property
        HomeViewModel _homeViewModel = new HomeViewModel();
        _homeViewModel.Repository = productlist;
        SetViewBags();
        return View("Index", _homeViewModel);
    }

    [HttpPost]
    public ActionResult Search(HomeViewModel HomeViewModel)
    {
        HomeViewModel _homeviewModel = new HomeViewModel();
        AgentServiceReference.AgentServiceClient ServiceClient = new AgentServiceClient();

        var productlist = ServiceClient.GetProducts();
        // do filter stuff here........
        var resultpagedList = productlist.ToPagedList(3, pagesize);

        _homeviewModel.Repository = resultpagedList;

        SetViewBags();
        return View("Index", _homeviewModel);
    }

    private void SetViewBags()
    {
        List<SelectListItem> manufactures = new List<SelectListItem>();
        for (int i = 0; i < 10; i++)
        {
            manufactures.Add(new SelectListItem { Text = "Text" + i, Value = "Value" + i, Selected = false });

        }
        ViewBag.Manufacturers = manufactures;
    }
}

Страница index.cshtml

@using System.Linq
@using PagedList
@using PagedList.Mvc
@model EntityLayer.HomeViewModel
@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
@using (Html.BeginForm("Search", "Paging", FormMethod.Post))
{
<div id="root">
    @Html.Partial("_Sidebar", Model)
    @Html.Partial("_ProductsList", Model)
</div>
}

_Боковая панель.cshtml

@model EntityLayer.HomeViewModel
@using System.Linq
@using PagedList
@using PagedList.Mvc
<div id="filter" class="left">
<div>
    <b>Manufacturer:</b>
    <br>        
    @Html.DropDownListFor(model => model.FilterView.Manufacturer, ViewBag.Manufacturers as IEnumerable<SelectListItem>)
    <b>Name:</b>
    <br>@Html.TextBoxFor(model => model.FilterView.Name)<br>
    <b>Price From:</b>
    <br>@Html.TextBoxFor(model => model.FilterView.MaxPrice)<br>
    <b>To:</b>
    <br>@Html.TextBoxFor(model => model.FilterView.MinPrice)<br>
    <button type="submit" value="search"><b>Search</b></button>
</div>

and finally _ProductsList.cshtml

@model EntityLayer.HomeViewModel
@using System.Linq
@using PagedList
@using PagedList.Mvc
<table>
<tr>
    <th>Name</th>
    <th>Price</th>
</tr>

@foreach (var item in Model.Repository)
{
    <tr>
        <td>@item.Name</td>
        <td>@item.Price</td>
    </tr>
}

<div class="pagedList" data-sc-target="#products">
@Html.PagedListPager(Model.Repository, page => Url.Action("Filter", "Paging", new { page }),
            PagedListRenderOptions.ClassicPlusFirstAndLast);

  • Соответственно измените пространства имен EntityLayer.HomeViewModel.
  • Подход, которому вы следовали, может быть неправильным, поскольку мы передаем всю HomeViewModel каждый раз, когда частичному представлению действительно нужна конкретная модель.
  • было бы лучше, если бы вы выполнили то же самое, используя запрос ajax. Обратите внимание, что я не применил макет, поскольку вы предоставили изображения. Изображения результатов: On LoadПервая подкачка Заданные значения моделиПривязка модели при публикации

Надеюсь, это поможет вам

person Gowtham.K.Reddy    schedule 16.09.2014
comment
Ух ты. спасибо за Ваш ответ. Я проверю и отвечу, если что-то пойдет не так. - person arsena; 16.09.2014
comment
@misho дайте мне знать, если у вас возникнут какие-либо проблемы. Отметьте это как ответ, если это вам поможет :) - person Gowtham.K.Reddy; 16.09.2014