The problem I will be describing is very similar to ones I already found (e.g. this post with nearly identical name) but I hope that I can make it into something that is not a duplicate.
I have created a new ASP.NET MVC 5 application in Visual Studio. Then, I defined two model classes:
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; }
}
Then I created the SearchController
as follows:
public class SearchController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult DisplaySearchResults()
{
var model = new List<SearchResultModel>
{
new SearchResultModel { Id=1, FirstName="Peter", Surname="Pan" },
new SearchResultModel { Id=2, FirstName="Jane", Surname="Doe" }
};
return PartialView("SearchResults", model);
}
}
as well as views Index.cshtml
(strongly typed with SearchCriterionModel
as model and template Edit) and SearchResults.cshtml
as a partial view with model of type IEnumerable<SearchResultModel>
(template List).
This is the Index view:
@model WebApplication1.Models.SearchCriterionModel
@{
ViewBag.Title = "Index";
}
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>SearchCriterionModel</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Keyword, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Keyword, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Keyword, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="button" id="btnDisplaySearchResults" value="Search" onclick="location.href='@Url.Action("DisplaySearchResults", "SearchController")'" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
<div id="searchResults">
</div>
As you can see, I added a div
with id="searchResults"
below the standard template and edited the button. What I want is to display the partial view SearchResults.cshtml
in the div
on the bottom, but only after the button is clicked. I have succeeded in showing a partial view there by using @Html.Partial("SearchResults", ViewBag.MyData)
, but it is rendered when the parent view is loaded for the first time and I set ViewBag.MyData
in the Index()
method already, which is not what I want.
Summary: On clicking the button, I will obtain some List
of SearchResultModel
instances (via database access) and then the partial view should be rendered, using this newly obtained data as model. How can I accomplish this? I already seem fail at the first step, that is reacting to the button click with the above code. Right now, I navigate to the URL ~/Search/DisplaySearchResults
, but of course there's nothing there and no code-behind method is called.
In traditional ASP.NET I'd just have added a server-side OnClick
handler, set the DataSource
for a grid and show the grid. But in MVC I already fail with this simple task...
Update: Changing the button to @Html.ActionLink
I can finally enter the controller method. But naturally since it returns the partial view, it's displayed as the whole page content. So the question is: How do I tell the partial view to be rendered inside a specific div
on the client side?
Change the button to
and add the following script
and modify the controller method to accept the search text
The jQuery
.load
method calls your controller method, passing the value of the search text and updates the contents of the<div>
with the partial view.Side note: The use of a
<form>
tag and@Html.ValidationSummary()
and@Html.ValidationMessageFor()
are probably not necessary here. Your never returning theIndex
view soValidationSummary
makes no sense and I assume you want anull
search text to return all results, and in any case you do not have any validation attributes for propertyKeyword
so there is nothing to validate.Edit
Based on OP's comments that
SearchCriterionModel
will contain multiple properties with validation attributes, then the approach would be to include a submit button and handle the forms.submit()
eventand the controller method would be