Как обновить только часть страницы индекса в MVC 5?

страница индекса содержит два частичных представления. Один для пользователя, чтобы ввести критерии поиска, другой, чтобы показать результаты. Как обновить данные только в представлении результатов ?

Я использую MVC 5 и Razor. Я видел несколько примеров этого, в основном используя ajax и jquery. Я спрашиваю, что было бы лучшим (предпочтительнее проще) решением для этого

/ / INDEX VIEW:

<div id="div_Search"> 
@{Html.RenderPartial("~/Views/Shared/Search.cshtml", ViewBag.Model_Search );}
</div>

<div id="div_Results">
@{Html.RenderPartial("~/Views/Shared/Results.cshtml", ViewBag.Model_Results );}
</div>


// HOME CONTROLLER

общественный класс HomeController: контроллер { MainContextDB db = новый MainContextDB ();

public ActionResult Index()
{
    // Code to initialize ViewBag.Model_Search, etc...
    .... 

    // Code to initialize  ViewBag.Model_Results, etc... (Values empty at startup) 
    ....

    return View();
}


[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult GetResults([Bind(Include = "DropOffLoc,DropOffDate,PickUpDate")] Search search)
{

   // Retrieve results using the search parameters, etc...
   ....

   // THIS RETURNS THE VIEW WITH THE DATA, BUT IN A SEPARATE PAGE (AS EXPECTED) 
   return View("~/Views/Shared/Results.cshtml", results);            

   // THIS RETURNS THE VIEW IN THE MAIN PAGE BUT WITH EMPTY DATA (AS EXPECTED) 
   return  RedirectToAction("Index");

   // HOW TO RETURN THE VIEW WITH THE DATA IN THE MAIN PAGE ?
   ??????? 

}

}

/ / ЭТО ЧАСТИЧНЫЙ ВИД ПОИСКА

@model Models.Results

@using (Html.BeginForm("GetResults", "Home", FormMethod.Post, new { @class = "my-form" }))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <div class="form-group input-group-sm">
        @Html.LabelFor(model => model.DropOffLoc)
        @Html.DropDownListFor(model => model.DropOffLoc, ViewBag.LocationList as SelectList, new { @class = "form-control"  })
        @Html.ValidationMessageFor(model => model.DropOffLoc)
    </div>

    <div class="form-group input-group-sm">
        @Html.LabelFor(model => model.DropOffDate)
        @Html.TextBoxFor(model => model.DropOffDate, new { @class = "form-control datepicker", placeholder = "Enter Drop-off date here..." })
        @Html.ValidationMessageFor(model => model.DropOffDate)
    </div>

        <div class="form-group input-group-sm">
        @Html.LabelFor(model => model.PickUpDate)
        @Html.TextBoxFor(model => model.PickUpDate, new { @class = "form-control datepicker", placeholder = "Enter Pick-up date here..." })
        @Html.ValidationMessageFor(model => model.PickUpDate)
    </div>

    <div style="text-align: center; margin-top: 10px; margin-bottom: 10px;">
        <input type="submit" id="getResults" value="GET RESULTS" class="btn btn-default btn-success" />
    </div>
}

3 ответов


Я бы поставил форму в частичный поиск. Затем у вас есть сообщение о действии, которое, через JQuery, к вашему действию GetResults, которое должно вернуться:

return PartialView("~/Views/Shared/Results.cshtml", results); 

затем, в обратном вызове успеха Вашего сообщения JQuery, выплюните возвращенные результаты в свой $("#div_Results") так:

$.ajax({
    url: '/Home/GetResults',
    type: "POST",
    dataType: "html",
    data: $("#FormId").serialize(),
    success: function (data) {
        //Fill div with results
        $("#div_Results").html(data);
    },
    error: function () { alert('error'); }
});

Если у меня нет опечатки или чего-то еще, это должно сработать. Вам нужно будет заменить селектор форм идентификатором тега формы.


хотя на этот вопрос уже есть ответ, я думал, что опубликую альтернативный подход, который также будет работать. Этот подход использует тот же метод действий и проверяет только, является ли запрос вызовом Ajax, который затем заменяет только часть тела. Вот только соответствующий код.

//форме поиска

 @using (Ajax.BeginForm("Index", "Home", new AjaxOptions() 
                                                                { HttpMethod = "GET", UpdateTargetId = "my-posts", 
                                                                    InsertionMode = InsertionMode.Replace 
                                                                }))
                        {
                            <input type="text" name="term" placeholder="Search B.I & G" />
                            <input type="submit" value="" />
                        }

//части представления

<section>
<div id="my-posts">
    @Html.Partial("_Posts", Model.Posts)
</div>

Теперь вот метод действия индекса, если запрос является AjaxRequest, он возвращает частичное представление, которое заменяет содержимое div на id my-posts. Если запрос не является запросом Ajax, он загружает все представление.

        public async Task<ActionResult> Index(string term)
    {

        var viewModel = new HomeFeedsViewModel();

        viewModel.Posts = await Task.Run(() =>
                                    db.Posts.Include("Comments")
                                    .Include("By").OrderByDescending(o => o.PostedOn)
                                    .ToList());
        //Return a Partial View which replaces content on the View
        //only if the Request is an Ajax Request
        if (Request.IsAjaxRequest())
        {
            viewModel.Posts = viewModel.Posts
                .Where(a => a.Title.IndexOf(term, StringComparison.OrdinalIgnoreCase) >= 0
                || a.Message.IndexOf(term, StringComparison.OrdinalIgnoreCase) >= 0
                );

            return PartialView("_Posts", viewModel.Posts);
        }

        return View(viewModel);
    }

надеюсь, это кому-то поможет.


вам, на самом деле, нужно будет использовать AJAX.

лучший подход, как я вижу, состоит в том, чтобы иметь частичное представление и выдавать нагрузку AJAX (jQuery.загрузки в jQuery) к нему.