Thare is two forms in a page first one for searching and another for deleting....
<table><tr><td>
<% using(Html.BeginForm("ViewList","ControllerName",
[values],FormMethod.Post,new{id="viewListForm"}))
{ %>
Name: <%=Html.TextBox("Name", "[value]", new { maxlength = "250" })%>
Location: <%=Html.TextBox("Location", "[Value]", new { maxlength = "250" })%>
<input type="submit" id="Search" name="Search" value="Search" />
<% } %>
</td></tr>
<tr><td>
<% using(Html.BeginForm("DeleteList","ControllerName",
new { name=?,location=? },[values],FormMethod.Post,
new{id="deleteListForm"}))
{ %>
[here the code for all items displayed in a table.]
<input type="submit" id="Delete" name="Delete" value="Delete" />
When delete buttom pressed i need to pass two parameters ie name
and location. The values of name and location are in the above viewListForm.
How i take this value from the viewListForm at run time ?
<% } %>
</td></tr><table>
Use javascript to populate hidden inputs.
Or use javascript to dynamically change the action of the search form.
Or dynamically create a form in jQuery for example and submit it.
You will need to have a controller action that takes a FormCollection as parameter
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ActionName(FormCollection collection)
{
// you can pull key value pair from the posted collection
string formValue = collection["InputId"]
}
Related
There are a few questions on SO about multiple submit buttons, such as How do you handle multiple submit buttons in ASP.NET MVC Framework? but what I am having trouble with is having multiple search buttons, each with it's own associated textbox for the value being searched for, and which searches it's own set of data. For example..
<div class="leftContentColumnRow">
#Html.TextBox("SearchString", null, new { placeholder = "Search Roles..." })
<input type="submit" value="" class="searchbtn" name="SearchRoles" />
</div>
<div class="rightContentColumnRow">
#Html.TextBox("SearchString", null, new { placeholder = "Search Permissions..." })
<input type="submit" value="" class="searchbtn" name="SearchPermissions" />
</div>
I can determine which button has been clicked, but I am struggling to get hold of the data in both textboxes.
Use a separate form for each input button pair with a different action for the form.
Like Oded said, 2 forms, each has it'w own action paramter value.
#using(Html.Beginform("SearchRole","User")
{
<div class="leftContentColumnRow">
#Html.TextBox("SearchString", null, new { placeholder = "Search Roles..." })
<input type="submit" value="" class="searchbtn" name="SearchRoles" />
</div>
}
#using(Html.Beginform("SearchPermissions","User")
{
<div class="rightContentColumnRow">
#Html.TextBox("SearchString", null, new { placeholder = "Search Permissions..." })
<input type="submit" value="" class="searchbtn" name="SearchPermissions" />
</div>
}
and the Action methods
public ActionResult SearchRole(string SearchString)
{
//get data and return something
}
public ActionResult SearchPermissions(string SearchString)
{
//get data and return something
}
I'm fairly new to ASP.NET MVC and still getting used to some of the concepts.
I understand that to pass the value of a text box in the View back to the Controller, I can use Html.BeginForm and give the text box the same name as the corresponding parameter in the Controller Action.
Here's my situation: I have 2 buttons. I want them to call the same Action in the Controller. I want them to both pass the value for the text box (i.e. the "searchText").
However, I want one of the buttons to pass "false" for the parameter isQuickJump and I want the other button to pass "true" for the parameter isQuickJump.
Here is my View:
#using (Html.BeginForm("SearchResults", "Search", FormMethod.Get)) {
<div id="logo" class="centered">
<a href="SearchResults">
<img alt="Search" src="../../Content/themes/base/images/Search.jpg" />
</a>
</div>
<div id="searchBox" class="centered">
#Html.TextBox("searchText", null, new { #class = "searchTextBox" })
</div>
<div id="buttons" class="centered">
<input type="submit" id="searchButton" value="Search" class="inputBtn" />
#Html.ActionLink("Quick Jump", "SearchResults", "Search", new { isQuickJump = true }, new { #class = "btn" })
</div>
}
Controller:
public ActionResult SearchResults(string searchText, int? page, int? size, bool? isQuickJump, GridSortOptions sort)
{
var items = GetSearchGrid(searchText, page, size, sort);
if (Request.IsAjaxRequest())
return PartialView("_SearchResultsGrid", items);
return View(items);
}
Any suggestions on how to do this?
I appreciate your help!
Just use 2 submit buttons with the same name and different value:
<div id="buttons" class="centered">
<button type="submit" name="isQuickJump" value="false">Search</button>
<button type="submit" name="isQuickJump" value="true">Quick Jump</button>
</div>
Depending on which button is clicked the corresponding value will be sent to the server for the isQuickJump parameter. And since both are submit buttons, they will also submit all other input fields data to the server (which was not the case with the anchor that you used as the second button).
I need to build voting web site so, I have couple candidates and below them a vote button,
how I can find which of the buttons was submitted
thanks
Give each of your buttons a name, like so (notice they are both "submit" buttons)::
<input type="submit" name="buttonYes" value="Yes" />
<input type="submit" name="buttonNo" value="No" />
Then, in your controller, capture a parameter for each of the two button names like this:
public ActionResult Index(string buttonYes, string buttonNo) { ... }
You can then tell which button was pressed by checking to see which of these two parameters is not null; the one which is pressed with a have a value equal to the "value" attribute of the button, the other one will be null:
if (buttonYes != null)
{
// Then the yes button was preseed
}
else if (buttonNo != null)
{
// Then the no button was pressed
}
else
{
// Neither button was used to submit the form
// and we got here some other way
}
The reason this works is because the web browser sends the information for the submit button that was pressed as part of the HTTP post to the web server. The button that was not pressed will not be sent with the post, and therefore the parameter will be null.
There are lots of ways to rewrite and optimzie this, but this is the essence of it and shows the fundamentals that are at work--you can play with it from there.
I wouldn't use the button value, I would set it up so that the url used to do the post encodes the vote itself. You could do this a couple of ways.
Use links
<div class="left">
<img src="/images/candidate/#Model.Candidates[0].ID" alt="#Model.Candidates[0].Name" />
#Html.ActionLink( "Vote for " + Model.Candidates[0].Name, "count", "vote" )
</div>
<div class="right">
<img src="/images/candidate/#Model.Candidates[1].ID" alt="#Model.Candidates[1].Name" />
#Html.ActionLink( "Vote for " + Model.Candidates[1].Name, "count", "vote" )
</div>
Use separate forms
<div class="left">
#using (Html.BeginForm( "count", "vote", new { id = Model.Candidates[0].ID } ))
{
<img src="/images/candidate/#Model.Candidates[0].ID" alt="#Model.Candidates[0].Name" />
<input type="submit" value="Vote" />
}
</div>
<div class="right">
#using (Html.BeginForm( "count", "vote", new { id = Model.Candidates[1].ID } ))
{
<img src="/images/candidate/#Model.Candidates[1].ID" alt="#Model.Candidates[1].Name" />
<input type="submit" value="Vote" />
}
</div>
Either of the above can be adapted to work with AJAX as well. Note, if you care, you'll need to build in some mechanism to detect vote fraud, e.g., add a one-time nonce to the url to verify that it isn't used more than once; track the number of times a user has voted if they are authenticated, etc.
I have a really strange ‘bug’. I use this in my view:
<% foreach (var QualitativeGlobalFeatureValue in Model.PossibleValues)
{ %>
<% using (Html.BeginForm("DeleteQualitativeGlobalFeatureValue", "Features", FormMethod.Post, new { #class = "deleteForm" }))
{ %>
<%= QualitativeGlobalFeatureValue.Value %>
<%= Html.ActionLink("Edit", "QualitativeGlobalFeatureValueForm", new { FeatureId = Model.Id, Id = QualitativeGlobalFeatureValue.Id })%>
<%= Html.Hidden("QualitativeGlobalFeatureValueId", QualitativeGlobalFeatureValue.Id)%>
<%= QualitativeGlobalFeatureValue.Id %>
<%= Html.Hidden("FeatureId", Model.Id)%>
<input type="submit" value="Delete" class="link_button" />
<% } %>
<% } %>
This produces a bunch of forms which post to an action which then redirect to an action which in turn produces this view.
Here is some HTML:
<form action="/Features/DeleteQualitativeGlobalFeatureValue" class="deleteForm" method="post">b
Edit
<input id="QualitativeGlobalFeatureValueId" name="QualitativeGlobalFeatureValueId" value="3004" type="hidden">
3004
<input id="FeatureId" name="FeatureId" value="2103" type="hidden">
<input value="Delete" class="link_button" type="submit">
</form><form action="/Features/DeleteQualitativeGlobalFeatureValue" class="deleteForm" method="post">aa
Edit
<input id="QualitativeGlobalFeatureValueId" name="QualitativeGlobalFeatureValueId" value="9010" type="hidden">
9010
<input id="FeatureId" name="FeatureId" value="2103" type="hidden">
<input value="Delete" class="link_button" type="submit">
</form>
Now if I delete the value with the Id 9010 the resulting HTML is as follows:
<form action="/Features/DeleteQualitativeGlobalFeatureValue" class="deleteForm" method="post">b
Edit
<input id="QualitativeGlobalFeatureValueId" name="QualitativeGlobalFeatureValueId" value="9010" type="hidden">
3004
<input id="FeatureId" name="FeatureId" value="2103" type="hidden">
<input value="Delete" class="link_button" type="submit">
</form>
For some unexplainable reason it contains value="9010" rather than value="3004" although it uses the code QualitativeGlobalFeatureValue.Id
It just does not make sense. Is this some browser/caching issue? – I am using Firefox. Thanks!
Best wishes,
Christian
PS:
Actions:
[MembersOnlyAttribute]
[AcceptVerbs(HttpVerbs.Get)]
public ViewResult GlobalQualitativeFeature(string Id)
{
QualitativeGlobalFeature QualitativeGlobalFeature = null;
if (TempData["ViewData"] != null)
{
ViewData = TempData["ViewData"] as ViewDataDictionary;
}
try
{
QualitativeGlobalFeature = FeatureService.GetQualitativeGlobalFeature(Id);
}
catch (Exception e)
{
ModelState.AddModelError("Exception", e.Message);
}
return View("GlobalQualitativeFeature", QualitativeGlobalFeature);
}
[MembersOnlyAttribute]
[AcceptVerbs(HttpVerbs.Post)]
public RedirectToRouteResult DeleteQualitativeGlobalFeatureValue(string QualitativeGlobalFeatureValueId, string FeatureId)
{
try
{
FeatureService.GetQualitativeGlobalFeatureValueRepository().DbContext.BeginTransaction();
FeatureService.DeleteQualitativeGlobalFeatureValue(QualitativeGlobalFeatureValueId);
FeatureService.GetQualitativeGlobalFeatureValueRepository().DbContext.CommitTransaction();
}
catch (Exception e)
{
ModelState.AddModelError("Exception", e.Message);
FeatureService.GetQualitativeGlobalFeatureValueRepository().DbContext.RollbackTransaction();
}
TempData["ViewData"] = ViewData;
return RedirectToAction("GlobalQualitativeFeature", new { Id = FeatureId });
}
I suspect the following. You click on the delete button for the 9010. The form is posted and the POST request contains QualitativeGlobalFeatureValueId=9010. In the controller action the same view is rendered. Here's the gotcha. When you write this:
<%= Html.Hidden(
"QualitativeGlobalFeatureValueId",
QualitativeGlobalFeatureValue.Id)
%>
The HTML helper (and not only this one) will first look if there's a request parameter with the same name as the name of the field (QualitativeGlobalFeatureValueId) and will use this value instead of the one you specified as the second argument (that's the way it is, don't ask my why, it's by design). So to fix this the only way is to manually render the hidden field:
<input
id="QualitativeGlobalFeatureValueId"
name="QualitativeGlobalFeatureValueId"
value="<%= QualitativeGlobalFeatureValue.Id %>"
type="hidden"
/>
You can put breakpoints in the markup and debug as it renders through, though it doesn't allow putting breakpoints on client markup or <% lines, so you need to find a line continuation.
Are you sure that it isn't a sort reordering or something like that, maybe the results aren't sorted, and that result is later on?
HTH.
I have a form in my MVC application that in theory should submit data back to my database using a Repository class.
However, when I submit the form (http://localhost:1028/Admin/NewUser/), the URL changes to where the form should be submitting to, which is fine (http://localhost:1028/Admin/NewUser/Submit), but once it has been submitted, it should send the user to a confirmation page.
From what I can tell, I'm moving through all my pages correctly until it comes to the submit, where it displays the form again but under /Admin/NewUser/Submit and the data is not inserted into the database.
This is the ActionResult I'm using:
Public Function Submit() As ActionResult
Try
Dim user = New hdUser() With { _
.userLogon = Request.Form("UserLogin"), _
.userPass = Request.Form("UserPassword"), _
.userEmail = Request.Form("UserEmail"), _
.RealName = Request.Form("UserFullName"), _
.isLive = 1, _
.avatar = "noavatar.gif" _
}
userRepository.Add(user)
userRepository.Save()
Return Redirect("/Admin/NewUser/Confirm")
Catch ex As Exception
ModelState.AddModelError("Error", ex)
End Try
Return View()
End Function
I'm fairly new to MVC so I'm not entirely sure if the above is correct or not.
And in my data repository class UserRepository.vb, the two functions I'm using are:
Public Sub Add(ByVal user As hdUser) Implements IUserRepository.Add
db.hdUsers.InsertOnSubmit(user)
End Sub
and
Public Sub Save() Implements IUserRepository.Save
db.SubmitChanges()
End Sub
And the form I have created is:
<form action="/Admin/NewUser/Submit" method="post">
<table border="0" cellpadding="0" cellspacing="2">
<tr>
<td><strong>User's Full Name</strong> <br />
<%=Html.TextBox("UserFullName")%>
</td>
</tr>
<tr>
<td><strong>User Login</strong> <br />
<%=Html.TextBox("UserLogin")%>
</td>
</tr>
<tr>
<td><strong>Password</strong> <br />
<%=Html.Password("UserPassword")%>
</td>
</tr>
<tr>
<td><strong>Email Address</strong> <br />
<%=Html.TextBox("UserEmail")%>
</td>
</tr>
<tr>
<td align="right"><input type="submit" value="Create" /></td>
</tr>
</table>
</form>
The code doesn't produce any errors but also doesn't seem to be submitting to the database. So I'm not entirely sure where I've gone wrong.
It could be obvious to someone more experienced, but I really haven't a clue on this one.
Is this my code that's causing the issue or some other fault?
Thanks in advance for any help.
EDIT: Based on Zhaph - Ben Duguid comment, I have made the following edits:
AdminController.vb
<AcceptVerbs(HttpVerbs.Post)> _
Public Function NewUser(ByVal formValues As FormCollection) As ActionResult
Try
Dim user = New hdUser()
user.userLogon = Request.Form("UserLogin")
user.userPass = Request.Form("UserPassword")
user.userEmail = Request.Form("UserEmail")
user.RealName = Request.Form("UserFullName")
user.isLive = 1
user.avatar = "noavatar.gif"
UpdateModel(user)
userRepository.Add(user)
userRepository.Save()
Catch ex As Exception
ModelState.AddModelError("Error", ex)
End Try
Return View()
End Function
NewUser.aspx
<%Html.BeginForm()%>
<%=Html.ValidationMessage("Error")%>
<table border="0" cellpadding="0" cellspacing="2">
<tr>
<td><strong>User's Full Name</strong> <br />
<%=Html.TextBox("UserFullName")%>
<%=Html.ValidationMessage("Name", "*")%></td>
</tr>
<tr>
<td><strong>User Login</strong> <br />
<%=Html.TextBox("UserLogin")%>
<%=Html.ValidationMessage("Username", "*")%></td>
</tr>
<tr>
<td><strong>Password</strong> <br />
<%=Html.Password("UserPassword")%>
<%=Html.ValidationMessage("Password", "*")%></td>
</tr>
<tr>
<td><strong>Email Address</strong> <br />
<%=Html.TextBox("UserEmail")%>
<%=Html.ValidationMessage("Email", "*")%></td>
</tr>
<tr>
<td align="right"><input type="submit" value="Create" /></td>
</tr>
</table>
<% Html.EndForm() %>
Which now produces an error of The value '' is invalid. for me.
Does this mean that form values aren't being passed correctly to the controller?
EDIT: I've made those edits in response Zhaph - Ben Duguid's edit and I've changed the Form elements to the DB field names (for testing at least). And now, when the page is submitted Name, Login and Email are all filled, password is blank (which I'm assuming is expected behaviour as per password boxes) but I still receive the "The value '' is invalid" error.
Response.Write in your controller isn't going to do anything to the view.
You should be returning your model back to the edit page, with any errors in
ModelState.AddModelError();
There's a very good example of how you can implement a Repository pattern, and take advantage of the ASP.NET MVC model binding features, etc in the NerdDinner Chapter from the Professional ASP.NET MVC book.
An example controller I have (in c# I'm afraid) based on the Nerd Dinner samples:
//
// POST: /AdminAlbums/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(FormCollection collection)
{
var album = new Album();
// Method on System.Web.Mvc.Controller, that takes a form collection, and
// using reflection on the Model, assigns values to it from the form.
UpdateModel(album);
if (album.IsValid)
{
// These methods are the same as yours
m_PhotoRepository.Add(album);
m_PhotoRepository.Save();
// In this instance, I'm returning the user to a list view of Albums
// for editing, probably ought to send them to the page to start
// uploading photos.
return RedirectToAction("Index");
}
// Still here, so I'm going to set up some ViewData I need.
ViewData["Title"] = "Create a new album";
ViewData["Message"] = "Create Album";
// I'm picking up errors from the model here.
// RuleViolation is my own class, implemented in a partial on Album.
foreach (RuleViolation violation in album.GetRuleViolations())
{
ModelState.AddModelError(violation.PropertyName, violation.ErrorMessage);
}
return View(album);
}
So you can see I return the model back to the main view if there's an error, to populate the Validation summary.
The relevant part of the view is:
<%= Html.ValidationSummary("Edit was unsuccessful. Please correct the errors and try again.") %>
<% using (Html.BeginForm()) {%>
<fieldset>
<legend>Album details</legend>
<div class="form_row">
<label for="Caption" class="left_label">Album caption:</label>
<%= Html.TextBox("Caption", Model.Caption, new { #class = "textbox" })%>
<%= Html.ValidationMessage("Caption", "*") %>
<div class="cleaner"> </div>
</div>
<div class="form_row">
<label for="IsPublic" class="left_label">Is this album public:</label>
<%= Html.CheckBox("IsPublic", Model.IsPublic) %>
</div>
<div class="form_row">
<input type="submit" value="Save" />
</div>
</fieldset>
<% } %>
Edit in response to question edit
Sorry, I should have clarified:
A lot of this is based on using the Helper methods provided by the ASP.NET MVC framework - you'll notice that I'm using methods like Html.TextBox to generate my fields, with their name/id pulled from the model itself. This way, if I load the view with ModelErrors in the ModelState, the helper will add the relevant details to rendered HTML to include the following mark-up
<label for="Caption" class="left_label">Caption:</label>
<input class="input-validation-error textbox"
id="Caption" name="Caption" type="text" value="" />
<span class="field-validation-error">*</span>
The other option you could have would be to add a message to the ViewData collection, and if it has a value, display that on your view.
Edit in response to question edit
A couple of things to bear in mind:
1) The identifiers of the Form elements and the Validation controls should be the same:
<%= Html.TextBox("Caption", Model.Caption, new { #class = "textbox" })%>
<%= Html.ValidationMessage("Caption", "*") %>
(you have things like "UserEmail" and "Email")
2) You should be returning the hdUser to the view on error - so try something like this:
<AcceptVerbs(HttpVerbs.Post)> _
Public Function NewUser(ByVal formValues As FormCollection) As ActionResult
Dim user = New hdUser()
Try
UpdateModel(user)
user.isLive = 1
user.avatar = "noavatar.gif"
userRepository.Add(user)
userRepository.Save()
Catch ex As Exception
ModelState.AddModelError("Error", ex)
End Try
Return View(user)
End Function