I am new to mvc, so am still struggling with some concepts.
I have a very simple form and controller.
Controller:
public class InquiryController : BaseController {
public ActionResult Index() {
return View();
}
public ActionResult Search(int Id) {
int newid = Id;
return View();
}
}
and the form:
#using (Html.BeginForm("Index", "Results", FormMethod.Post))
{
#Html.TextBox("id", null, new { type = "Search", autofocus = "true", style = "width: 200px" })
<input type="submit" value="Search" />
}
What is happening is that when I enter a number in the form, I want that number to be passed to the "Search" function in the controller. I do not understand how to get the form to call the controller and do its processing inside that controller. Instead, it goes to an error looking for the "results" page, which i understand comes from the BeginForm method.
So in essence, how can i get my form to pass the number entered into the search box to my controller function?
Specify what action and what controller you want to go to in the first two arguments of Html.BeginForm.
#using (Html.BeginForm("Search", "Inquiry", FormMethod.Post))
{
#Html.TextBox("id", null, new { type = "Search", autofocus = "true", placeholder = "Harvest Tag, 6 Digit Tag No.", style = "width: 200px" })
<input type="submit" value="Search" />
}
Inside the action you can access the Id like you're doing but you could also get it from FormCollection["id"] or Request["id"] as the original string and validate it to avoid getting parsing errors in case the user submits an invalid int.
The first parameter to BeginForm is the action to take, and the second is the controller to execute, so your usage should be:
#using (Html.BeginForm("Search", "Inquiry", FormMethod.Post))
The value that gets passes in is found (in this case) by the HTML ID of the input control (id)
Related
I have some problems with deletion item from database (SQLServer) using parameters for that. I want to press "Delete" reference in Index() then put name parameter in Delete() and redirect action to Index() again and show content of db. When I press "Delete" reference I show nothing but start page of Index() :(
public async Task<IActionResult> Delete(string nm)
{
IQueryable<Phone> users = db.Phones;
if (!String.IsNullOrEmpty(nm))
{
users = users.Where(p => p.Name.Contains(nm));
foreach (var item in users)
{
db.Phones.Remove(item);
}
await db.SaveChangesAsync();
}
return RedirectToAction("Index");
}
#model DataApp2.Models.Phone
#{
ViewBag.Title = "Delete";
}
<form method="get">
<div class="form-inline form-group">
<label class="control-label">Name: </label>
#Html.TextBox("nm", Model.Name, htmlAttributes: new { #class = "form-control" })
<input type="submit" value="Delete" class="btn btn-default" />
</div>
</form>
Building the input yourself and using a form is a bit overkill/overcomplicated. Instead, you can leverage the .NET MVC framework to send the request to your action
by replacing the form you posted and everything inside of it with:
#Html.ActionLink("Delete", "Delete", new { nm = Model.Name })
This will generate a link (<a> tag) with the text "Delete" (first param of the ActionLink) and send the Model.Name in a data field called nm to the Delete action in your controller (second param of the ActionLink).
I've put together a proof of concept showing that this works:
View:
#Html.ActionLink("Delete", "Delete", new { nm = "hi" })
Controller Action:
public ActionResult Delete(string nm)
{
if (!String.IsNullOrEmpty(nm))
{
ViewBag.Name = nm;
}
return RedirectToAction("Index");
}
the controller is successfully setting ViewBag.Name in this example. Note as far as the issue you're having, it makes no difference that I'm returning a ActionResult here instead of async Task<IActionResult> as you are.
I'm guessing that you're not populating Model.Name in the action that initially loads the page. Please post the code for your get action that loads the view if you'd like more information. You can test this theory by sticking:
#if (string.IsNullOrEmpty(Model.Name))
{
<h1>Name is empty!</h1>
}
else
{
<h1>Name is #Model.Name</h1>
}
in your view if you dont want to step through the code via the debugger
Working on mvc5 app. In my ajax form I have alot of fields, including one hidden input...
<input id="currentView" name="currentView"
value="calendar" type="hidden" />
Whenever I post to my action, currentView is null, unless I change type to "text". Then I get the value fine.
The beginning of the action is defined as...
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult GetEvents(string userName, string currentView,
string theStatus)
{
The other params are in the Model and come across fine. Is this the issue? Does currentView have to be in the Model for the hidden field to work? I guess I'm just confused as to why when I change the type to text it works. My understanding was that as long as I have a name defined it's accessible in the request vars.
Thanks!
**** UPDATE: Here's the top portion of my Ajax form *****
#using (Ajax.BeginForm(
new AjaxOptions
{
HttpMethod = "POST",
Url = "/Scheduler/GetEvents",
UpdateTargetId = "mainTable"
}))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<input id="currentView" name="currentView"
value="calendar" type="text"
style="display: none;" />
As you can see I hacked it by using display: none. When I change type to "hidden" it doesn't work.
instead of sending value with hidden field you can try sending it in route values like this
#using (Ajax.BeginForm("GetEvents", "Scheduler", new { currentView ="calander"},
new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "mainTable"
}))
{
In my RequestController I have 2 methods with the same name, Create(), 1 for GET and 1 for POST.
I want to call the GET method in a button.
It works as text like this:
#Html.ActionLink("Create New", "Create")
But in a button it calls the POST Create method:
#using (Html.BeginForm("Create", "Request"))
{
<button type="submit">New Request</button>
}
RequestController methods:
//
// GET: /Request/Create
public ActionResult Create()
{
ViewBag.ID = new SelectList(db.Expenses, "ID", "Department");
var destinations = from t in db.Typevalues
where t.Typeschema.SchemaCode == "CTY"
select t;
ViewBag.Destinations = destinations;
return View();
}
//
// POST: /Request/Create
[HttpPost]
public ActionResult Create(Request request)
{
if (ModelState.IsValid)
{
db.Requests.Add(request);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.ID = new SelectList(db.Expenses, "ID", "Department", request.ID);
return View(request);
}
How do I call the GET method in the button?
In your template specify the form method:
#using (Html.BeginForm("Create", "Request", FormMethod.Get)) {
<button type="submit">New Request</button>
}
What others have said should indeed work, however, I'd encourage you to think about what you're really trying to do. Based upon your code, it seems to me using a regular link (which can easily be styled as a button) would make more sense semantically.
If it's not really a form with data that needs to be submitted, in my opinion, it doesn't belong in a form.
You should replace your submit button with a plain HTML link:
<a class="button" href="#Url.Action("Create", "Request")">New Request</a>
and add a "button" class to you styles to simulate a button.
Or if you want to keep the button:
<button type="submit" onclick="top.location.href='#Url.Action("Create", "Request")'; return false;">New Request</button>
In every HTML form you should specify form method, otherwise it defaults. In your case one form (POST) goes:
#using (Html.BeginForm("Create", "Request", FormMethod.Post))
{
<button type="submit">New Request</button>
}
And the other one (GET):
#using (Html.BeginForm("Create", "Request", FormMethod.Get))
{
<button type="submit">New Request</button>
}
Or the same what you had, which default to GET:
#using (Html.BeginForm("Create", "Request"))
{
<button type="submit">New Request</button>
}
Controller
[HttpGet]
[Route("~/search/{clause}/{skip?}")]
public async Task<ActionResult> Search(string clause, int skip = 0)
{
...
}
View
#using (Html.BeginForm("Index", "search", FormMethod.Get))
{
#Html.TextBox("clause", null, new { #class = "form-control col-md-4" })
...
}
Rendered Html
<form action="/search" method="get">
<input id="clause" name="clause" type="text" value="test">
</form>
I am using [HttpGet] partly because i want the search to be accessing via http://myapp.com/search/<search values>
When i navigate to http://myapp.com/search/test, everything seems fine, but when i try to enter my new search term in the textbox and hit enter or submit, it navigates to http://myapp.com/search?clause=newsearch
What should I do so that my textbox will navigate to http://myapp.com/search/newsearch instead?
Your form generates http://myapp.com/search?clause=newsearch because a browser has no knowledge of your routes (c# code running on your server).
In order to generate your preferred url (http://myapp.com/search/newsearch), you need javascript to intercept and cancel the default submit, and build a url to navigate to. Using jQuery:
$('form').submit(function() {
var baseUrl = $(this).attr('action'); // or var baseUrl = '#Url.Action("Index", "search")';
var url = baseUrl + '/' + $('clause').val(); // add value for skip if required
location.href = url; // redirect
return false; // cancel the default submit
});
I want to pass the Html.Textbox value to a controller from anchor tag, so that I can search the value passed to a controller. Please tell me how can I achieve this.
#p
public ActionResult Index(string String)
{
}
#Html.TextBox("String")
use jquery
#Html.TextBox("String", null, new { #class="txtString" })
#p
then in your script
$('.txtString').on('blur', function(){
$('.linkAction').attr('src', '#Url.Action("Index", "Home", new { text = "----" })'.replace("----", $('.txtString').val()));
});
You don't have to use jQuery. If you're doing a HttpPost, you just need the "name" of the textbox.
On your page:
#using (Html.BeginForm("Index", FormMethod.Post)) {
#Html.TextBox(string.Empty, new { name = "textbox" })
<input type="submit">Submit</input>
}
Then in your controller:
[HttpPost]
public ActionResult Index(string textbox) {
// The name of the string parameter must match the name given to the TextBox element on the page.
}
#using (Html.BeginForm("Index", "Home", null, FormMethod.Post, new {#id = "my-form"}))
{
#Html.TextBox("String")
}
<a href="javascript:document.getElementById('my-form').submit();>#p</a>
You can use FormMethod.Post or FormMethod.Get. The latter will append ?String= to the url.