asp.net mvc - كيفية تصميم ميزة البحث العالمي MVC5 في layout.cshtml



asp.net-mvc razor (1)

هذا يبدو وكأنه حالة استخدام جيدة لأفعال الطفل .

هذا مثال أساسي مع أجاكس بحيث سيشاهد المستخدم النتائج دون إعادة تحميل الصفحة.

_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 من صفحة "التخطيط" @model إلى العرض الجزئي ل "إجراء الطفل". حمل هذا المثال أداة البحث في التخطيط ولكن يمكنك استخدامه على أي طريقة عرض تريدها.

لإبقاء الأمور بسيطة هنا، يتم تشغيل أجاكس بواسطة زر ولكن يمكنك تعديله لتشغيل تغيير النص المتأخر. ويمكن أيضا أن تكون النتيجة جسون بدلا من وجهة نظر باريتال - بعض العملاء من جانب تايب-أهيد المكونات الإضافية قد التعامل مع النتائج كما جسون.

إذا كنت تريد الانتقال إلى صفحة نتائج

يمكنك إسقاط كل البرنامج النصي وتحويل القطعة الخاصة بك إلى شكل مناسب.

@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; }
}

اضبط التنسيق لتمرير معلمة إلى أداة البحث. سيؤدي هذا إلى الحفاظ على مفتاح البحث في صفحة النتائج.

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

يمرر إجراء سيرتشويدجيت الآن معلمة لتعبئة النموذج (في حالة تقديمه).

[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 لمفتاح البحث حتى أي إجراء باستخدام تخطيط لن تضطر إلى تحديد نموذج مشترك.

أنا أحاول تنفيذ ميزة "البحث العالمي"، وهذا هو متاح فوق القائمة الرئيسية لدينا، في جميع وجهات النظر ضمن طلبنا. تبدو هكذا:

"البحث العالمي" هو حقل إدخال الإكمال التلقائي للمسج. أنه يقيم في منطقتنا _Layout.cshtml، وهو عرض مشترك ويحصل على تحميل عدة مرات من قبل وجهات النظر الأخرى. أساسا فإنه سيتم عرض قائمة لصناعة السيارات في اقتراح الكلمات الرئيسية للبحث. تحتوي قائمة اقتراحات الكلمات الرئيسية على 6000 عنصر تقريبا.

لدينا هومكونترولر يشبه هذا:

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 يستخدم هذا النموذج:

@model MyApplication.Models.GlobalSearchSuggestions

يستخدم SearchResults.cshtml هذا النموذج:

@model IQueryable<MyApplication.Models.GlobalSearchResult>  

مشكلتي تبدأ عند استخدام @ موديل إعلاني في _Layout.cshtml.

أحصل على خطأ من هذا القبيل:

مساج = "عنصر النموذج الذي تم تمريره في القاموس هو من نوع 'System.Web.Mvc.HandleErrorInfo'، ولكن هذا القاموس يتطلب عنصر نموذج من نوع 'MyApplication.Models.GlobalSearchSuggestions'."

إذا قمت بإزالة نموذج إعلاني _Layout.cshtml، واسترداد "اقتراحات" من خلال وسيلة أخرى (مثل أجاكس)، فإنه سيسمح SearchResults.cshtml للعمل. لا يتم إنتاج أي خطأ. ولكني سأستخدم بدلا من ذلك النموذج بدلا من أجاكس. لذا، إذا تركت نموذجا إعلانيا في _Layout.cshtml، أحصل على الاستثناء.

أنا أيضا لا يمكن تحميل "اقتراحات" من أي عرض غير المنزل. لماذا هذا؟ إذا ذهبت إلى وجهة نظر أخرى ضمن طلبنا، وأنا أحاول إجراء "البحث العالمي" من لدينا _Layout.cshtml القطعة، وأنا لا تحصل على أي "اقتراحات" أو البيانات في الإكمال التلقائي مسج. لماذا يعمل فقط للعرض الرئيسية و تحكم المنزل ؟؟

كيف يمكنني تجنب هذا الاستثناء واستخدام كل من إعلانات موديل؟ وكيف يمكنني الحصول على _Layout.cshtml لعرض الاقتراحات باستمرار في حقل الإكمال التلقائي (وليس فقط من الصفحة الرئيسية؟)؟

أي مساعدة هو موضع تقدير. شكرا لكم!