Renderização de vista parcial no botão de clique no asp.net MVC

O problema que eu vou descrever é muito parecido com o que eu já encontrei (por exemplo, este post com um nome quase idêntico ), mas espero poder transformá-lo em algo que não seja duplicado.

Eu criei um novo aplicativo ASP.NET MVC 5 no Visual Studio. Então, eu defini duas classs de modelo:

public class SearchCriterionModel { public string Keyword { get; set; } } public class SearchResultModel { public int Id { get; set; } public string FirstName { get; set; } public string Surname { get; set; } } 

Então eu criei o SearchController seguinte forma:

 public class SearchController : Controller { public ActionResult Index() { return View(); } public ActionResult DisplaySearchResults() { var model = new List { new SearchResultModel { Id=1, FirstName="Peter", Surname="Pan" }, new SearchResultModel { Id=2, FirstName="Jane", Surname="Doe" } }; return PartialView("SearchResults", model); } } 

bem como visualizações Index.cshtml (fortemente tipado com SearchCriterionModel como modelo e modelo Edit ) e SearchResults.cshtml como uma visão parcial com modelo do tipo IEnumerable (template List ).

Esta é a visão do índice:

 @model WebApplication1.Models.SearchCriterionModel @{ ViewBag.Title = "Index"; } @using (Html.BeginForm()) { @Html.AntiForgeryToken() 

SearchCriterionModel


@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.Keyword, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.Keyword, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Keyword, "", new { @class = "text-danger" })
}
@Html.ActionLink("Back to List", "Index")

Como você pode ver, adicionei uma div com id="searchResults" abaixo do modelo padrão e editei o botão. O que eu quero é exibir a visualização parcial SearchResults.cshtml na div na parte inferior, mas somente depois que o botão for clicado. Eu consegui mostrar uma visão parcial lá usando @Html.Partial("SearchResults", ViewBag.MyData) , mas é processado quando a exibição pai é carregada pela primeira vez e eu defino ViewBag.MyData no Index() método já, o que não é o que eu quero.

Resumo: Ao clicar no botão, eu obterei algumas instâncias de SearchResultModel (via access ao database) e, em seguida, a visualização parcial deverá ser renderizada, usando esses dados recém-obtidos como modelo. Como posso fazer isso? Eu já pareço falhar no primeiro passo, que está reagindo ao clique do botão com o código acima. No momento, eu navego até o URL ~/Search/DisplaySearchResults , mas é claro que não há nada lá e nenhum método code-behind é chamado. No ASP.NET tradicional, eu acabei de adicionar um manipulador OnClick lado do servidor, definir o DataSource para uma grade e mostrar a grade. Mas no MVC eu já falho com essa tarefa simples …

Atualização: Alterando o botão para @Html.ActionLink finalmente posso entrar no método do controlador. Mas, naturalmente, uma vez que retorna a visão parcial, é exibido como todo o conteúdo da página. Então a pergunta é: como eu digo a visão parcial para ser renderizada dentro de um div específico no lado do cliente?

Altere o botão para

  

e adicione o seguinte script

 var url = '@Url.Action("DisplaySearchResults", "Search")'; $('#search').click(function() { var keyWord = $('#Keyword').val(); $('#searchResults').load(url, { searchText: keyWord }); }) 

e modificar o método do controlador para aceitar o texto da pesquisa

 public ActionResult DisplaySearchResults(string searchText) { var model = // build list based on parameter searchText return PartialView("SearchResults", model); } 

O método jQuery .load chama seu método do controlador, passando o valor do texto da pesquisa e atualizando o conteúdo do

com a visualização parcial.

Nota: O uso de uma tag

e @Html.ValidationSummary() e @Html.ValidationMessageFor() provavelmente não são necessários aqui. Você nunca retornando a visualização do Index para que ValidationSummary não faça sentido e suponho que você deseja que um texto de pesquisa null retorne todos os resultados e, em qualquer caso, você não possui atributos de validação para a propriedade Keyword portanto, não há nada para validar.

Editar

Com base nos comentários do OP que o SearchCriterionModel conterá várias propriedades com atributos de validação, a abordagem seria include um botão de envio e manipular o evento .submit() formulários .submit()

  var url = '@Url.Action("DisplaySearchResults", "Search")'; $('form').submit(function() { if (!$(this).valid()) { return false; // prevent the ajax call if validation errors } var form = $(this).serialize(); $('#searchResults').load(url, form); return false; // prevent the default submit action }) 

e o método do controlador seria

 public ActionResult DisplaySearchResults(SearchCriterionModel criteria) { var model = // build list based on the properties of criteria return PartialView("SearchResults", model); }