My form isn't always submitted when I hit the submit button.
On my form I have one submit button. When I first hit the button, the form will submit. But when there's a validation error, the error is shown. But when I fix that error and press the submit button again, the form is not submitted. This will happen if you work with 'normal' speed; if you do everything very slow, then the form will submit.
In the 'normal speed' mode I see in FireBug that there's a request to the server, but my breakpoint in the code is never hit! So I keep on the same page and nothing happens. When I click multiple times (5-10) or I wait a few seconds and then click the submit button, the submit will reach my code.
I am using MVC4 with the .NET 4.5 framework.
I hope someone can help me with this..
EDIT:
This is the code I am talking about.
My html (with razor) code:
<div id="content" class="boxBorder">
<form method="post" action="/Import/ProcessStep" #(Model.UploadFiles ? "enctype=multipart/form-data" : "") id="wizardForm">
<table id="detailsTable" width="550" cellspacing="0" border="0">
<thead>
<tr>
<th class="first">Importwizard
</th>
</tr>
<tr>
<th></th>
</tr>
</thead>
<tfoot>
<tr>
<td></td>
</tr>
</tfoot>
<tbody>
<tr>
<td> </td>
</tr>
<tr>
<td>
<div id="ImportProgressBar">
<ul>
#foreach (var step in Model.StepNames)
{
<li>
<div class="WizardProgressStep">
<img src="#step.Value" class="ProgressStepImage" />
<br />
<span>#step.Key</span>
</div>
</li>
}
</ul>
</div>
<div id="StepTitle">
#Model.StepTitle
<hr />
</div>
<div id="StepContent">
#RenderBody()
</div>
</td>
</tr>
<tr>
<td> </td>
</tr>
<tr>
<td>
<div id="WizardNavigationBox">
#if (Model.HasPreviousButton)
{
<input type="submit" name="PreviousStep" id="PreviousStep" value="Vorige" class="button icon add" />
}
#if (Model.HasNextButton)
{
<input type="submit" name="NextStep" id="NextStep" value="Volgende" class="button icon add saveButton" />
}
</div>
</td>
</tr>
</tbody>
</table>
</form>
</div>
My controller:
[HttpPost]
public ActionResult ProcessStep(FormCollection formCollection)
{
WebMediator mediator = new WebMediator();
ViewResult newStep;
GenericWizardViewModel viewModel;
if (formCollection["NextStep"] != null)
{
ValidateStep(formCollection);
if (ModelState.IsValid)
{
mediator.ProcessStep(formCollection);
newStep = mediator.GetNextStep();
}
else
{
IWizardStep currentStep = mediator.GetCurrentStep();
viewModel = mediator.CreateViewModel(currentStep);
return this.RazorView(currentStep.StepName, viewModel);
}
}
else
{
newStep = mediator.GetPreviousStep();
}
viewModel = newStep.Model as GenericWizardViewModel;
return this.RazorView(newStep.ViewName, viewModel);
}
We finally figured it out.
All our controllers inherit from a custom BaseController class. This BaseController had an trribute with OutputCache on it with a duration set to 10 seconds. Removing this attribute fixed my problem.
Related
I have a table with pagination in ASP.Net Core. I have a input where user can search the result by name and a Search button which works as expected. However after the search name input is searched and result is displayed, clicking on the new page number, the model parameter(search name) is not being transferred to the controller action method. The page parameter is however being transferred correctly. How do I go about fixing it?
#model FruitViewModel
#using PagedList.Core.Mvc
<form id="formPostFruit" asp-action="PostFruit" asp-controller="Fruit" asp-route-model="#Model" method="get">
<input name="SearchName" type="text" title="Search Name" class="form-control" placeholder="Search name" asp-for="SearchName" aria-describedby="basic-addon1">
<button id="btnSearch" class="btn btn-secondary btn-sm" type="button" title="Search"><i class="fas fa-search" aria-hidden='true'></i> Search</button>
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Quantity</th>
<th>Price</th>
</tr>
</thead>
<tbody>
#if (Model.ResultList != null && Model.ResultList.Count() > 0)
{
#foreach (var item in Model.ResultList)
{
<tr>
<td>
#item.Name
</td>
<td>
#item.Quantity
</td>
<td>
#item.Price
</td>
</tr>
}
}
</tbody>
</table>
#if (Model != null && Model.ResultList != null && Model.ResultList.Count() > 0 && Model.ResultList.PageCount > 1)
{
<pager class="pager" list="#Model.ResultList" asp-action="PostFruit" asp-
controller="Fruit" asp-route-model="#Model" param-page-number="page"
options="#PagedListRenderOptions.Bootstrap4PageNumbersPlusFirstAndLast" />
}
The Controller action
public ActionResult PostFruit(FruitViewModel model, int? page)
{
}
I have the following table:
<form method="post" asp-action="Index" asp-controller="Record">
<table class="table table-hover">
<thead>
<tr>
<th scope="col"><input type="checkbox" id="chkAll"></th>
<th scope="col">Created</th>
<th scope="col">User Reference</th>
<th scope="col">Type</th>
<th scope="col">Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
#foreach (var rec in Model.Data)
{
<tr>
<td style="display: none">
#Html.TextBoxFor(m => rec.Id)
</td>
<td>
#Html.CheckBoxFor(m => rec.IsChecked)
</td>
<td>#rec.Created</td>
<td>#rec.UserReference</td>
<td>#rec.Type</td>
<td>#rec.Status</td>
<td>
<input name="submit" type="submit" id="process" value="submit" />
</td>
</tr>
}
</tbody>
</table>
</form>
The issue I have is when I press submit I'm expecting to pass the content of the table into my controller, however when I submit the form the model on my controller is null:
[HttpPost]
public async Task<IActionResult> Index(List<UserData> data)
When I submit the form I expect to have a list of id's and checkbox values either true / false, can someone shed some light into why I'm not able to see this within the post method of the controller?
Found the solution of the following thread, seems switching foreach to for resolved the issue.
When I click the button to submit my form, the viewModel is not being bound. I'm not sure whether this is to do with the model property being an array.
Controller
[HttpPost]
public async Task<IActionResult> CommodityAdditionalCodes(CommodityAdditionalCodesViewModel viewModel)
{
//todo code in here which calls webservice
return View(viewModel);
}
ViewModel
public class CommodityAdditionalCodesViewModel
{
public CommodityAdditionalCodeType[] Types { get; set; }
}
View
#model Asm.Helios.ToolboxMvc.ViewModels.CommodityAdditionalCodesViewModel
#{
ViewData["Title"] = "CommodityAdditionalCodes";
}
<Section>
<button type="button" id="btnCommit">Commit Changes</button><span id="isDirtyMessage" class="warning" style="display:none">There are unsaved changes, press the commit changes button to save them</span>
</Section>
<form id="frmAdditionalCodes" name="frmAdditionalCodes" method="post" >
<table class="table header-fixed">
<thead>
<tr >
<th>Origin</th>
<th>Description</th>
<th>Valid From</th>
<th>Valid To</th>
<th>Type</th>
<th>Customs Identifier</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Types)
{
<tr>
<td>
<span>#item.Origin</span>
<input type="text" value="#item.Origin" style="display:none"/>
</td>
<td>
<span>#item.Description</span>
<input type="text" value="#item.Description" style="display:none" />
</td>
<td>
<span>#item.ValidFrom</span>
<input type="text" value="#item.ValidFrom" style="display:none" />
</td>
<td>
<span>#item.ValidTo</span>
<input type="text" value="#item.ValidTo" style="display:none" />
</td>
<td>
<span>#item.Type</span>
<input type="text" value="#item.Type" style="display:none" />
</td>
<td>
<span>#item.CustomsIdentifier</span>
<!--<input type="text" value="#item.CustomsIdentifier" style="display:none" />-->
#Html.TextBoxFor(m=>item.CustomsIdentifier, new {#style="display:none"})</td>
<td>
<button type="button" id="deleteItem">Delete</button>
<button type="button" id="editItem">Edit</button>
<button type="button" id="updateItem" style="display:none">Update</button>
<button type="button" id="cancelItem" style="display:none">Cancel</button>
</td>
</tr>
}
</tbody>
</table>
</form>
Don't use a foreach loop, instead use a classic for and index the model, for example Model.Types[index].
Also you should consider using tag helpers, it makes your Razor code much easier to read as it more closely resembles real HTML.
#for (var index = 0; index < Model.Types.Count; index++)
{
<input type="text" asp-for="Model.Types[index].Origin" />
<!-- etc... -->
}
C#, MVC4
I have a PartialView created for a popup data entry on a form. This is a snippet from the main form.
<input type="button" id="btnAddGroup" value="Add Group" />
<p>
<input type="submit" value="Save" />
</p>
</div>
</fieldset> }
I discovered quickly that I needed to have the line:
#Html.Partial("_Groups")
Outside the primary view so the form submit button in the partial view would accept and process.
My controller processes and sends back the data using:
return PartialView(NewModel);
I can run the debugger and see that the data is getting passed back to the PartialView but since the view sits outside the original form, it's not displaying.
My PartialView is as follows:
#model OMD.ViewModels.SearchedUser
#if (Model.AddGroups != null)
{
<h2>Groups to be Added</h2>
<table id="AddGroupList">
<thead>
<tr>
<th>
Name
</th>
<th>
Until
</th>
<th>
Action
</th>
</tr>
</thead>
<tbody>
#foreach (var Group in Model.AddGroups)
{
<tr>
<td>
#Html.DisplayFor(model=> Group.GroupName)
</td>
<td>
#Html.DisplayFor(model=> Group.dtAddedTo)
</td>
<td>
#Html.DisplayFor(model=> Group.bAddOrRemove)
</td>
<td>
#if (AuthCheck.CheckUser(new HttpContextWrapper(HttpContext.Current), oRoles.StaffChangeRequest) ||
AuthCheck.CheckUser(new HttpContextWrapper(HttpContext.Current), oRoles.StudentChangeRequest))
{
<span>#Html.ActionLink("Remove", "RemoveGroup", new { id = Group.ID })</span>
}
</td>
</tr>
}
</tbody>
</table>
}
<div id="dlgAddGroup" title="Add Group" style="display: none">
#using (Ajax.BeginForm("_Groups",new AjaxOptions { UpdateTargetId ="ID",OnSuccess="onSuccess"}))
{
#Html.DropDownListFor(model => model.AllGroups,new SelectList(Model.AllGroups, "ID","GroupName"), "Select Group to Add")
#Html.ValidationMessageFor(model => model.AllGroups)
<div class="editor-label">
#Html.CheckBox("cbxMakeGroupPermanent", true) Permanent
</div>
<div class="editor-label" id ="dlgUntil1">
Group Add Until:
</div>
<div class="editor-field" id="dlgUntil2">
#Html.TextBox("tbAddUntil",null,new { maxlength = 30, style = "width: 100px" })
<span style='padding:5px'><img id='calImageGroup' alt="img" src='~/Images/calendar.gif'></span>
</div>
<button class="btn btn-inverse" type="submit">add</button>
}
I can see the table at the top display the information posted back to it but it doesn't show on the screen...
How can I get this data/table to display?
I have a MasterPage, in my Views\Shared folder. I have an index.aspx in my Views\Home folder. And I have a login.ascx (user control) in my Views\User folder. The ascx file is added to my MasterPage:
<% Html.RenderPartial(#"~\Views\User\login.ascx");%>
The code in the ascx is pointing the submit form to a UserController.cs in my Controllers folder.
Here's the ascx:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<BudgieMoneySite.Models.SiteUserLoginModel>" %>
<% using (Html.BeginForm("UserLogin", "User"))
{%>
<table width="300">
<tr>
<td colspan="3" align="center">
User Login
</td>
</tr>
<tr>
<td align="right">
<%=Html.LabelFor(m => m.Username)%>
</td>
<td>
<%=Html.TextBoxFor(m => m.Username)%>
</td>
<td>
</td>
</tr>
<tr>
<td align="right">
<%=Html.LabelFor(m => m.Password)%>
</td>
<td>
<%=Html.PasswordFor(m => m.Password)%>
</td>
<td>
</td>
</tr>
<tr>
<td>
</td>
<td>
<%=Html.CheckBoxFor(m => m.RemeberMe)%><%=Html.LabelFor(m => m.RemeberMe)%>
</td>
</tr>
<tr>
<td colspan="2">
</td>
<td colspan="3" align="right">
<input id="Submit1" type="submit" runat="server" value="Login" />
</td>
</tr>
</table>
<%
} // End Using.%>
If I ctrl+click the Controller name and the method, in the Html.BeginForm area, it takes me to my method that should be called when I click Sybmit.
The method that this should call, in my UserController, has this code defined:
[HttpPost]
public ActionResult UserLogin(SiteUserLoginModel model)
{
try
{
if (MembershipService.ValidateUser(model.Username, model.Password))
{
FormService.SignIn(model.Username, model.RemeberMe);
PersonDto user = SiteUserLoginModel.LoadLoggedInUserDetails(model.Username);
Session.Add("current_firstname", user.Firstname);
Session.Add("current_userid", user.PersonId);
}
return RedirectToAction("Index", "Home");
}
catch (ArgumentException e)
{
ViewData["ErrorMessage"] = e.Message;
return RedirectToAction("Index", "Home");
}
}
However, when I click the submit button at runtime, this method is never called. The screen just refreshed. The HomeController does fire though, as the index screen is refreshed, I think. But the breakpoint in my method above never fires.
What am I doing wrong?
I would start removing the runat="server" attribute from your submit button...
<input id="Submit1" type="submit" value="Login" />
Your form in BeginForm isn't set to POST.
Try this: Html.BeginForm("UserLogin", "User", FormMethod.Post).
Guys, I found the issue, and it's an issue I had 2 weeks back, but totoally forgot. The master page had a Form tag! And the user control's Form tage was being hidden by the master page's one. I remove the Form tags from the master page, and it's resolved.