如何将ViewBag中的某些对象传递给Action? - 保留搜索,排序和分页选项

时间:2016-08-29 17:45:30

标签: c# asp.net .net asp.net-mvc routevalues

我有一个视图,我在分页列表中显示搜索结果和排序。我将列标题添加为链接,以使用户能够以这种方式基于列进行排序:

<tr>
    <th>           
        @Html.ActionLink("Reference No", "Index", 
          new { sortOrder = ViewBag.RefNoSortParm, currentFilter = ViewBag.CurrentFilter })
    </th>
    <th>
        @Html.ActionLink("Category", "Index", 
          new { sortOrder = ViewBag.CatSortParm, currentFilter = ViewBag.CurrentFilter })
    </th>
    ... Some other columns
</tr>

我也这样添加了一个寻呼机:

Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount

@Html.PagedListPager(Model, page => Url.Action("Index",
    new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))

我使用的动作如下:

private Registry_fssEntities db = new Registry_fssEntities();
public ActionResult Index(string sortOrder, SearchTransacModel searchModel, SearchTransacModel currentFilter, int? page)
{            
    var model = from c in db.TRANSACs
                select c;
    ViewBag.CurrentSort = sortOrder;
    ViewBag.DispDateSortParm = String.IsNullOrEmpty(sortOrder) ? "DispDate" : "";
    ViewBag.RefNoSortParm = sortOrder == "RefNo" ? "RefNo_desc" : "RefNo";
    ViewBag.CatSortParm = sortOrder == "Cat" ? "Cat_desc" : "Cat";   
    if (searchModel.DATEDISPFROM != null || searchModel.DATEDISPTO != null || searchModel.DATEDISPFROM != null || searchModel.OFFICERNAME != null || searchModel.APPNAME != null || searchModel.REFNO != null || searchModel.PROCNAME != null)
    {
        page = 1;
    }
    else
    {
        searchModel = currentFilter;
    }
    if (searchModel != null)
    {
        if (!String.IsNullOrEmpty(searchModel.DATEDISPFROM))
        {                    
            ViewBag.DispFrom = searchModel.DATEDISPFROM.ToString();
        }
        else
        {
            searchModel.DATEDISPFROM = "01/01/" + DateTime.Today.Year.ToString();
            ViewBag.DispFrom = "01/01/" + DateTime.Today.Year.ToString();
        }
        if (!String.IsNullOrEmpty(searchModel.DATEDISPTO))
        {                   
            ViewBag.DispTo = searchModel.DATEDISPTO.ToString();
        }
        else
        {
            searchModel.DATEDISPTO = "31/12/" + DateTime.Today.Year.ToString();
            ViewBag.DispTo = "31/12/" + DateTime.Today.Year.ToString();
        }
    }
    if (searchModel != null)
    {
        var tRANSACs = new TransacBusinessLogic();
        model = tRANSACs.GetTransacs(searchModel);

        ViewBag.currentFilter = searchModel;
    }
    List<TransacViewModel> TransactionList = new List<TransacViewModel>();
    foreach (var item in model)
    {
        TransactionList.Add(new TransacViewModel {
                TRANSID = item.TRANSID,
                REFNO = item?.REFNO,
                PROCESS = item?.PROCESS,
                //CATEGORY = item.PROCESS.CATEGORY,
                DOCTYPE = item?.DOCTYPE,
                DATEDEL = returnasdate(item.DATEDEL),
                DATEDISP = returnasdate(item.DATEDISP),
                APPNAME = item?.APPNAME,
                OFFICER = item?.OFFICER,
                DATEREG = item.DATEREG
            });
    }
    switch (sortOrder)
    {
        case "DispDate":
            TransactionList = TransactionList.OrderBy(x => x.DATEDISP).ToList();
            break;
        case "RefNo":
            TransactionList = TransactionList.OrderBy(t => t.REFNO).ToList();
            break;
        case "RefNo_desc":
            TransactionList = TransactionList.OrderByDescending(t => t.PROCESS.CATEGORY.DETAIL).ToList();
            break;
        case "Cat":
            TransactionList = TransactionList.OrderBy(t => t.PROCESS.CATEGORY.DETAIL).ToList();
            break;
        case "Cat_desc":
            TransactionList = TransactionList.OrderByDescending(t => t.REFNO).ToList();
            break;
        default:
            TransactionList = TransactionList.OrderByDescending(t => t.DATEDISP).ToList();
            break;
    }
    int pageSize = 6;
    int pageNumber = (page ?? 1);            
    return View(TransactionList.ToPagedList(pageNumber, pageSize));
}

SearchTransacModel是用于包含搜索参数的模型,因为我将它们传递给控制器​​。 当我通过提交按钮提交搜索表单时,它工作正常,我使用ViewBag将此搜索条件发送回视图:ViewBag.currentFilter = searchModel;

但是当我点击任何排序操作链接时,我会丢失搜索参数。当我到达控制器时,currentFilter为空。

我将currentFilter作为查询字符串传递,并将搜索模型分配给它,就像在这种情况下一样:

 @Html.ActionLink("Reference No", "Index", new { sortOrder = ViewBag.RefNoSortParm, currentFilter = ViewBag.CurrentFilter })

有人可以帮忙吗?我是MVC btw的新人。

4 个答案:

答案 0 :(得分:3)

您无法将视图中的值传递回控制器。

相反,您应该在视图中使用模型绑定将信息传递给post方法。

答案 1 :(得分:3)

您可以使用此类操作:

public ActionResult Index(SearchModel searchModel, string sortColumn, string sortOrder)
{
    ViewBag.SearchModel = searchModel;
    ViewBag.SortColumn= sortColumn;
    ViewBag.SortOrder = sortOrder;
    var business = new BusinessLogic();
    var model = business.Search(searchModel, sortColumn, sortOrder);
    return View(model);
}

您可以通过这种方式简单地混合一些路线值。这样,搜索选项和排序选项都将保留在请求之间:

@{
    var routeValues = new RouteValueDictionary(ViewBag.SearchModel ?? new { });
    routeValues["sortColumn"] = ViewBag.SortColumn;
    routeValues["sortOrder"] = ViewBag.SortOrder;
}
@Html.ActionLink("Link Text", "Action", routeValues);

注意:

  • 根据这个答案中的想法,你可以简单地创建一个方法,它甚至可以混合2个对象来为你创建路线值。

  • 您还可以将排序选项封装在SortOption类中,并将其放在ViewBag中并在模型绑定中使用它。

  • System.Linq.Dynamic将帮助您获得更加动态,干净的排序代码。

  • 要详细了解此类SearchModelBusinessLogic技术的优势,请查看Filter/Search using Multiple Fields - ASP.NET MVC

  • 此要求的常见方案是,例如,网页的页面链接或网格的列链接,显示搜索和排序的结果。如果您在网格上使用此技术,则分页链接应保留搜索选项并在请求之间排序选项。但是为了生成列标题链接,对于每个列,您应该使用不同的合适排序顺序和排序列;对于其名称等于当前排序列的列,排序顺序应与当前排序顺序相反。列标题也应该保留页面索引。

答案 2 :(得分:0)

从viewbag读取后,您可以在查询字符串中传递过滤器值。假设您的SearchTransacModel课程具有DATEDISPFROMOFFICERNAME属性,

public class SearchTransacModel
{
     public string DATEDISPFROM { set; get; }
     public string OFFICERNAME { set; get; }
}  

您可以将值作为路由值发送,其中键将是属性名称(SearchTransacModel类),值将是您拥有的值。

@{
    var filter = ViewBag.CurrentFilter as SearchTransacModel;
}
@Html.ActionLink("Reference No", "Index", new { sortOrder = ViewBag.RefNoSortParm, 
        DATEDISPFROM = filter!=null? filter.DATEDISPFROM:"", 
        OFFICERNAME = filter != null ? filter.OFFICERNAME : "" })

模型绑定器将能够将查询字符串值映射到您的currentFilter对象。

我建议您不要使用相同类型的2个参数(currentFilter&amp; searchModel)。

答案 3 :(得分:0)

虽然可以使用 ViewBag 来实现您的目标,但它仍然不是为此而设计的。

相反,您应该创建一个模型并使用它与您的控制器和视图进行通信。

将您的退货模式更改并对齐得更大。

public TransactionsViewModel
{
    public SearchTransacModel SearchModel { get; set; }
    public List<TransacViewModel> TransactionList { get; set; }
}

现在您可以放弃使用 ViewBag.currentFilter 并仅使用此模型。