如何在Layout.cshtml中设计MVC5全局搜索功能 [英] How to design an MVC5 Global Search feature in Layout.cshtml

查看:93
本文介绍了如何在Layout.cshtml中设计MVC5全局搜索功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在应用程序内的所有视图中实现全局搜索"功能,该功能可在主菜单上方使用.看起来像这样:

I am trying to implement a "global search" feature, that is available above our main menu, in all Views within our application. It looks like this:

全局搜索"是jQuery自动完成输入字段.它位于我们的_Layout.cshtml中,它是一个共享视图,并被其他视图多次加载.本质上,它将显示搜索关键字的自动建议列表.我们的关键字建议列表大约有6000条.

The "global search" is a jQuery autocomplete input field. It resides in our _Layout.cshtml, which is a shared View and gets loaded many times by other views. Essentially it will display an auto-suggestion list for search keywords. Our list of keyword suggestions is roughly 6000 items.

我们的HomeController看起来像这样:

Our HomeController looks like this:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult Home()
    {
        ViewBag.Message = " Home Page.";

        GlobalSearchController controller = new GlobalSearchController();
        //_Layout.cshtml uses this for the auto-complete jQuery list
        var suggestions = controller.GetGlobalSearchSuggestions(); 
        return View(suggestions);
    }

    public ActionResult SearchResults()
    {
        ViewBag.Message = "Search Results page.";

        GlobalSearchController controller = new GlobalSearchController();
        var searchKeyword = "technology";
        //SearchResults.html uses this for the search results data
        var results = controller.GetGlobalSearchResults(searchKeyword); 
        ViewBag.SearchKeyword = searchKeyword;
        return View(results);
    }
}

_Layout.cshtml使用以下模型:

_Layout.cshtml uses this model:

@model MyApplication.Models.GlobalSearchSuggestions

SearchResults.cshtml使用以下模型:

SearchResults.cshtml uses this model:

@model IQueryable<MyApplication.Models.GlobalSearchResult>  

当我在_Layout.cshtml中使用@model声明式时,我的问题开始了.

My problem begins when I use the @model declarative in _Layout.cshtml.

我收到这样的错误:

Message =传递到字典中的模型项是类型 'System.Web.Mvc.HandleErrorInfo',但此字典需要一个模型 "MyApplication.Models.GlobalSearchSuggestions"类型的项目."

Message = "The model item passed into the dictionary is of type 'System.Web.Mvc.HandleErrorInfo', but this dictionary requires a model item of type 'MyApplication.Models.GlobalSearchSuggestions'."

如果我删除_Layout.cshtml的模型声明,并通过其他方式(例如AJAX)检索建议",它将使SearchResults.cshtml正常工作.没有错误产生.但是我宁愿使用模型而不是AJAX.因此,如果我将模型声明式的代码保留在_Layout.cshtml中,则会出现异常.

If I remove the model declarative for _Layout.cshtml, and retrieve the "suggestions" through another means (like AJAX), it will allow the SearchResults.cshtml to work. No error is produced. But I would much rather use the model instead of AJAX. So, if I leave the model declarative in the _Layout.cshtml, I get the exception.

我也无法从Home以外的任何视图加载建议".这是为什么?如果我转到应用程序中的另一个视图,并且尝试从_Layout.cshtml小部件执行全局搜索",则jQuery自动完成功能中没有任何建议"或数据.为什么它仅适用于主视图和主控制器?

I also cannot load the "suggestions" from any View other than Home. Why is that? If I go to another view within our application, and I try to perform a "global search" from our _Layout.cshtml widget, I do not get any "suggestions" or data in the jQuery autocomplete. Why does it only work for the Home view and Home controller??

如何避免出现此异常,并同时使用@model声明语?以及如何获得_Layout.cshtml来在自动完成字段中持续显示建议(而不仅仅是在首页上?)?

感谢您的帮助.谢谢!

推荐答案

这听起来像是这是AJAX的基本示例,因此用户无需重新加载页面即可查看结果.

This is a basic example with AJAX so the user will see results without a page reload.

_Layout.cshtml

<div class="header">
    @Html.Action("SearchWidget", "GlobalSearch")
</div>

@RenderBody()

<script src="jquery.js" />
<script>
    $(".global-search-form").on("click", "button", function(e)
    {
        $.ajax({
            url: "/GlobalSearch/Search",
            method: "GET",
            data: { item: $("input[name='item']").val() }
        })
        .then(function(result)
        {
            $(".global-search-result").html(result);
        });
    });
</script>

_Search.cshtml

<div class="global-search-widget">
    <div class="globa-search-form">
        <label for="item">Search For:</label>
        <input type="text" name="item" value="" />
        <button type="button">Search</button>
    </div>
    <div class="global-search-results"></div>
</div>

_SearchResults.cshtml

@model MyNamespace.SearchResults

<div>Results</div>
<ul>
@foreach(var item in Model.Suggestions)
{
    <li>@item</li>
}
</ul>

搜索结果

public class SearchResults
{
    public List<string> Suggestions { get; set; }
}

GlobalSearchController

[HttpGet]
[ChildActionOnly]
public ActionResult SearchWidget()
{
    return PartialView("_Search");
}

[HttpGet]
public ActionResult Search(string item)
{
    SearchResults results = searchService.Find(item);
    return PartialView("_SearchResults", results);
}

我们将@model声明保留在布局"页面之外,并将其移至子动作的局部视图.此示例将搜索窗口小部件加载到Layout中,但是您可以在所需的任何视图上使用它.

We keep the @model declaration out of the Layout page and move it to the Child Action's partial view. This example loaded the search widget into Layout but you can use it on any view you want.

为使操作简单,AJAX由按钮触发,但您可以对其进行修改以在延迟的文本更改时触发.结果也可能是JSON而不是局部视图-一些客户端的Type-Ahead插件可能会将结果作为JSON处理.

To keep things simple here, the AJAX is triggered by a button but you can modify it to trigger on a delayed text change. The result could also be JSON instead of a parital view -- some client-side Type-Ahead plug-ins may handle the results as JSON.

您可以删除所有脚本并将小部件转换为适当的格式.

You can drop all the script and convert your widget to a proper form.

@model MyNamespace.SearchForm

@using(Html.BeginForm("Search", "GlobalSearch", FormMethod.Get, new { item = ViewBag.GlobalSearchKey })
{
    @Html.TextBoxFor(m => m.Item)
    <button type="submit">Search</button>
}

搜索模型

public class SearchForm
{
    public string Item { get; set; }
}

调整布局以将参数传递回搜索小部件.这将在结果页面中保留搜索键.

Adjust your layout to pass a parameter back to the search widget. This will maintain the search key in the results page.

@Html.Action("SearchWidget", "GlobalSearch", new { item = ViewBag.GlobalSearchKey })

SearchWidget操作现在传递一个参数来填充表单(如果提供).

The SearchWidget action now passes a parameter to populate the form (if provided).

[HttpGet]
[ChildActionOnly]
public ActionResult SearchWidget(string item)
{
    var model = new SearchForm
    {
        Item = item ?? ""
    };
    return PartialView("_Search", model);
}

[HttpGet]
public ActionResult Search(SearchForm model)
{
    var results = searchService.Find(model.Item);
    ViewBag.GlobalSearchKey = model.Item;  // keep the same value for the form

    return View("SearchResults", results);  // full view with layout
}

我们使用ViewBag作为搜索关键字,因此使用布局的任何操作都不必定义通用模型.

We use the ViewBag for the search key so any action using the layout will not have to define a common model.

这篇关于如何在Layout.cshtml中设计MVC5全局搜索功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆