Reputation: 473
I have a form with a searchbox on it. When someone types something into the search box and hits the search button I am trying ot do a post to capture the search filter and then fire off a view.
Here is the controller code
public class SpotsController : Controller
{
[HttpPost]
[AllowAnonymous]
public ActionResult SearchSpots(string searchfilter)
{
//your code here....
return Index(searchfilter);
}
Here is the code from my view up until the part that is tryign to do the submit
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - Haunt Spotter</title>
</head>
<form id="__AjaxAntiForgeryForm" action="#" method="post"><@Html.AntiForgeryToken()></form>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="navbar-collapse collapse">
@using (Html.BeginForm("SearchSpots", "Spots"))
{
<input id="searchfilter" type="text" class="form-control" autocomplete="off" placeholder="Search" name="searchfilter">
<button class="btn btn-default" type="submit"><i class="glyphicon glyphicon-search"></i></button>
}
</div>
</div>
</div>
If I take the parameter off of the controller function it works fine. If not it seems to crash and try to re display a get which fails because I only have a post function for this. I am guessing I have something screwed up with the parameter but I can't figure out what it is. Any help woudl be greatly appreciated.
UPDATE
Based on feedback I have changed my post to a get
[HttpGet]
[AllowAnonymous]
public ActionResult SearchSpots(string searchfilter)
{
//your code here....
return Index(searchfilter);
}
and my view code to this
@using (Html.BeginForm("SearchSpots", "Spots", FormMethod.Get, null))
{
<input id="searchfilter" type="text" class="form-control" autocomplete="off" placeholder="Search" name="searchfilter">
<button class="btn btn-default" type="submit"><i class="glyphicon glyphicon-search"></i></button>
}
Unfortunately I still have the original issue. If I remove the searchfileter parameter from my controller call then it goes into the call with no problems but when I am expecting the modelbinder to give me a searchfilter it crashes out.
Here is the call I am redirecting to in my search function
private ApplicationDbContext db = new ApplicationDbContext();
// GET: Spots
public ActionResult Index(string filter = "")
{
ViewBag.initialFilter = filter;
if (User.IsInRole("SiteAdmin"))
{
return View(db.Spots.ToList());
}
else
{
return View(db.Spots.Where(x => x.Approved).ToList());
}
}
and the view that is displayed
@model IEnumerable<HauntSpots.Models.Spot>
@{
ViewBag.Title = "Index";
}
<h2 class="align-right">Haunt Spots</h2>
@if (Context.User.IsInRole("SiteAdmin"))
{
<p style="padding-top:20px">
<a href="@Url.Action("Create")" title="Add New Spot" class="btn btn-primary"><i class="icon-plus-sign"></i> Add New</a>
</p>
}
<table id="dt-spots" class="table table-striped">
<thead>
<tr>
<th></th>
<th></th>
<th></th>
@if (Context.User.IsInRole("SiteAdmin"))
{
<th></th>
}
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@if (Context.User.IsInRole("SiteAdmin"))
{
@Html.Hidden(Url.Action("Edit", "Spots", new { id = item.Id }))
<a style="color: Red; vertical-align: middle; font-size: 2em" href="@Url.Action("Delete", "Spots", new { id = item.Id })" title="Delete Spot" class="btn"><i class="icon-remove-sign"></i></a>
}
else
{
@Html.Hidden(Url.Action("Details", "Spots", new { id = item.Id }))
}
</td>
<td>
@if (item.Image == null)
{
<img width="100" height="100"
src="~/Content/Images/NoPhoto.jpg" class="img-rounded" />
}
else
{
<img width="100" height="100"
src="@item.Image" class="img-rounded"/>
}
</td>
<td >
<div class="form-group pull-left col-md-2">
<h4>@item.Title </h4>
<h5 style="clear: left">
@if (item.Address != null)
{
<span>@item.Address</span>
<br/>
}
@if (item.State == null)
{
<span>@item.City</span><br/>
<span>@item.Country</span>
}
else
{
if (item.State == "")
{
<span>@item.City</span>
<br/>
<span>@item.Country</span>
}
else
{
<span>@item.City, @item.State</span>
<br/>
<span>@item.Country</span>
}
}
</h5>
</div>
<div class="form-group pull-left col-md-8">
<h6>@item.Summary</h6>
</div>
</td>
@if (Context.User.IsInRole("SiteAdmin"))
{
<td>
@if (@item.Approved)
{
<span style="color: green">Approved</span>
}
else
{
<span style="color: red">Not Approved</span>
}
</td>
}
</tr>
}
</tbody>
</table>
<script type="text/javascript">
$(document).ready(function () {
//Initalize and configure DataTables
$('#dt-spots').dataTable({
"oSearch": { "sSearch": "@ViewBag.initialFilter" }
});
$("tbody").on("click", "tr", function () {
window.location = $(this).find('input').attr('name');
});
});
</script>
Upvotes: 0
Views: 2902
Reputation: 5953
In agreement with most of the other answers stating that this needs to be an HttpGet
request rather than an HttpPost
request I believe that this can be solved by changing your HTML.
HTML:
@using (Html.BeginForm("SearchSpots", "Spots", FormMethod.Get, null))
{
<input id="searchfilter" type="text" class="form-control" autocomplete="off" placeholder="Search" name="searchfilter">
<input class="btn btn-default" type="submit" <i class="glyphicon glyphicon-search"</i>/> // part that needs changing
}
Controller:
[HttpGet]
public ActionResult SearchSpots(string searchfilter)
{
// logic
}
I believe your issue can be related to this. <button>
is exactly what it is.. a button.. it basically does nothing, and is mainly used for JS purposes. However, the <input type="submit" />
actually submits the surrounding form.
I hope this helps!
UPDATE
I did need the input to pass the parameter. I still had the same error even after it was being passed and I had to make this final tweak to get it running
[HttpGet]
[AllowAnonymous]
public ActionResult SearchSpots(string searchfilter)
{
return RedirectToAction("Index", new { filter = searchfilter});
}
I needed to redirect instead of trying to return a view
Upvotes: 0
Reputation: 6565
Do a GET
instead of a POST
—you're not doing any inserts or updates, just fetching results based on a parameter (searchfilter
). With a GET
, the values of the input elements in your form will be appended as parameters to the query string of the target URL, which would produce something like mywebsite.com/spots/spotsearch?searchfilter=whateverValueInTheInputBox
(depending on how you have your routing configured).
Razor:
@using (Html.BeginForm("SearchSpots", "Spots", FormMethod.Get, null))
{
<input id="searchfilter" type="text" class="form-control" autocomplete="off" placeholder="Search" name="searchfilter">
<button class="btn btn-default" type="submit"><i class="glyphicon glyphicon-search"></i></button>
}
Controller:
public class SpotsController : Controller
{
[HttpGet]
[AllowAnonymous]
public ActionResult SearchSpots(string searchfilter)
{
// ...
}
}
Edit: As per @BviLLe_Kid, you can try replacing <button>
with <input>
.
Edit 2: Can't help but wonder why you are proxying the call to Index
via SearchSpots
, causing an unnecessary redirect. If all that SearchSpots
does is redirect to Index
, why not submit the form directly to Index
?
Razor:
@using (Html.BeginForm("Index", "Spots", FormMethod.Get, null))
{
<!-- remember to rename to name="filter" below -->
<input id="filter" type="text" class="form-control" autocomplete="off" placeholder="Search" name="filter">
<input class="btn btn-default" type="submit" <i class="glyphicon glyphicon-search"</i>/>
}
Controller:
// GET: Spots
public ActionResult Index(string filter = "")
{
ViewBag.initialFilter = filter;
if (User.IsInRole("SiteAdmin"))
{
return View(db.Spots.ToList());
}
else
{
return View(db.Spots.Where(x => x.Approved).ToList());
}
}
Upvotes: 1
Reputation: 1483
This is a routing issue. You don't have a route that will hit SearchSpots with a parameter. So either change your route, or change the BeginForm to include the parameter.
ASP.NET MVC - passing parameters to the controller
Pass multiple parameters in Html.BeginForm MVC
Upvotes: 0
Reputation: 1590
you don't need two forms in your HTML and this code is working and post search text
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - Haunt Spotter</title>
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="navbar-collapse collapse">
@using (Html.BeginForm("SearchSpots", "Spots", FormMethod.Post))
{
@Html.AntiForgeryToken()
<input id="searchfilter" type="text" class="form-control" autocomplete="off" placeholder="Search" name="searchfilter">
<button class="btn btn-default" type="submit"><i class="glyphicon glyphicon-search"></i></button>
}
</div>
</div>
</div>
And you can add [ValidateAntiForgeryToken]
in your action
Upvotes: 0
Reputation: 1725
I believe you're missing FormMethod.Post
in
@using (Html.BeginForm("SearchSpots", "Spots", FormMethod.Post))
{...
Upvotes: 0