ASP MVC Submit button not doing anything. At all - c#

I have a (simple) ASP MVC view:
<div class="row">
<div id="dashboard-left" class="col-md-8">
#using (Html.BeginForm("ConfigureOffers", "Offers", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div style="padding-bottom: 10px;">
<p style="font-size: large;"><strong>Available</strong></p>
</div>
<div class="accordion" id="accordion2">
<div class="widget" style="background:#fff !important">
#{
int i = 0;
}
#foreach (var prod in Model.allProducts)
{
<div class="accordion-group">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse" data-parent="accordion2" href="#collapse#(i)">
<h4 class="widgettitle" id="QuickTitle">> #prod.Description_VC</h4>
</a>
</div>
<div id="collapse#(i)" class="accordion-body collapse" style="height: 0px;">
<div class="accordion-inner" style="margin-left: 10px;">
<div style="padding-bottom: 10px;"><strong>Total product:</strong> #{
for (int k = 0; k < Model.OfferHeaders.Count(); k++)
{
if (Model.OfferHeaders[k].Product_ID == prod.Product_ID)
{
#Html.TextBoxFor(o => o.OfferHeaders[k].Amount_DEC);
break;
}
}
}
</div> #*prod div*#
</div> #*accordion-inner*#
#{i++;}
</div>
<div style="clear:both;"></div>
</div>
}
<input type="submit" class="btn btn-default" value="Save Changes" />
</div> #*widget*#
</div> #*accordion*#
}
</div>
<!-- col-md-4 -->
</div>
<!--row-->
The basis of this view was taken from another (working page), but for some reason, clicking the submit button doesn't trigger the server action detailed in the BeginForm element. I get no errors from Visual Studio, nor any JavaScript errors from the browser console, and nothing seems to happen server-side.

One possible reason for Action not happening is mainly when you put
the action in the View and also created the page. but i think you
have forgot mentioning the ActionResult in the controller.
Another possible option is you have to use [HttpPost] above your
method in controller where you specified the ActionResult
[HttpPost]
public ActionResult ConfigureOffers(ModelClass instance)
{
...
}

Other possible reasons
The routes are not correct
The Form Action property is not correct
You are using nested FORM tags

Related

Update the partia view based on Main view custom filters

Code searchView and PartialResultView
SearchView
#model Shared.Model.Search.GLSearch
#{
ViewData["Title"] = "Search GL";
}
<!-- start page title -->
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<ol class="breadcrumb m-0">
<li class="breadcrumb-item">UBold</li>
<li class="breadcrumb-item">Forms</li>
<li class="breadcrumb-item active">Elements</li>
</ol>
</div>
<h4 class="page-title">Search Customer</h4>
</div>
</div>
</div>
<!-- end page title -->
<form asp-action="" asp-controller="" method="post">
<div class="row">
<div class="col-lg-12">
<div class="card-box">
<div class="form-row">
<div class="form-group col-md-2">
<label asp-for="Name" class="col-form-label"></label>
<input asp-for="Name" type="text" class="form-control" />
</div>
<div class="form-group col-md-2">
<label asp-for="Code" class="col-form-label"></label>
<input asp-for="Code" type="text" class="form-control" />
</div>
<div class="form-group col-md-3">
<label asp-for="GLSectionId" class="col-form-label">Section </label>
<select asp-for="GLSectionId" asp-items="#(new SelectList(Model.glSections,"Id","Name"))" class="form-control">
<option value="">Choose</option>
</select>
</div>
<div class="form-group col-md-3">
<label asp-for="GLGroupId" class="col-form-label">Group</label>
<select asp-for="GLGroupId" asp-items="#(new SelectList(Model.glGroups,"Id","Name"))" class="form-control">
<option value="">Choose</option>
</select>
</div>
<button type="button" id="search" class="btn btn-primary waves-effect waves-light">Search</button>
</div>
</div> <!-- end card-box -->
</div> <!-- end col -->
</div> <!-- end row -->
</form>
<div id="view-all"></div>
Search_PartiaView
#model PagedResult<Shared.Model.Masters.GLMaster.GLViewModel>
#{
}
#if (Model == null || Model.RowCount == 0)
{
<p>No results found</p>
}
else
{
<div class="col-lg-12">
<div class="card-box">
<h4 class="header-title">Customers</h4>
<p class="sub-header">
</p>
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead>
<tr>
<th data-priority="1">#</th>
<th data-priority="3">Name</th>
<th data-priority="6">Code</th>
<th data-priority="6">Section</th>
<th data-priority="6">Group</th>
<th data-priority="6">
<a onclick="showInPopup('#Url.Action("AddOrEditGL","GLMaster",new {area = "Masters"},Context.Request.Scheme)','New GL')" class="btn btn-success text-white"><i class="fas fa-random"></i> New GL</a>
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model.Results)
{
<tr>
<th scope="row">#item.Id</th>
<td>#item.Name</td>
<td>#item.Code</td>
<td>#item.GLSection</td>
<td>#item.GLGroup</td>
<td>
<div>
<a onclick="showInPopup('#Url.Action("AddOrEditGL","GLMaster",new { area= "Masters",id = item.Id},Context.Request.Scheme)','Update GL')" class="btn btn-info text-white"><i class="fas fa-pencil-alt"></i> Edit</a>
<form asp-area="Masters" asp-action="DeleteGL" asp-route-id="#item.Id" onsubmit="return jQueryAjaxDelete(this)" class="d-inline">
<input type="submit" value="Delete" class="btn btn-danger" />
</form>
</div>
</td>
</tr>
}
</tbody>
</table>
</div> <!-- end table-responsive-->
</div> <!-- end card-box -->
</div> <!-- end col -->
<!-- Responsive Table js -->
}
Partial View (AddEditGL)
#model Shared.Model.Masters.GLMaster.GLModel
#{
Layout = null;
ViewData["Title"] = "Add Customer";
}
<div class="row">
<div class="col-lg-12">
<div class="card-box">
<form asp-action="AddOrEditGL" asp-controller="GLMaster" asp-area="Masters" asp-route-id="#Model.Id" onsubmit="return jQueryAjaxPost(this);">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="#Model.Id" />
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" type="text" class="form-control">
<span asp-validation-for="Name" class="text-danger"></span>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label asp-for="NameLang" class="control-label"></label>
<input asp-for="NameLang" type="text" class="form-control">
<span asp-validation-for="NameLang" class="text-danger"></span>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-6 offset-md-3">
<input type="submit" value="Submit" class="btn btn-primary btn-block" />
</div>
</div>
</form>
</div> <!-- end card-box -->
</div> <!-- end col -->
</div> <!-- end row -->
I have View with Partial view (is for results in table) . When i click Edit button in Search_PartiaView
i need to open popup (Partial View (AddEditGL))
and data should be loaded ajax and submit the button after update.. I need to use jquery unobtrusive validation in popup and also without refresh the page ..Please let me know hw to do..Thanks
EDIT
I Have implemented similar to this Ajax crud popup
I Have Main view and Partial view. Also AddOrEdit View for Add/edit Master.
My Current solution works.. But inmy main view i have filter based on 2 filds.
After add/edit grid load all the result but if filter applied i also need to filter the grid ..
My Javascript code Here:
jQueryAjaxPost = form => {
try {
$.ajax({
type: 'POST',
url: form.action,
data: new FormData(form),
contentType: false,
processData: false,
success: function (res) {
if (res.isValid) {
$('#view-all').html(res.html) --- here actually data coming all without filter
$('#form-modal .modal-body.p-4').html('');
$('#form-modal .modal-title').html('');
$('#form-modal').modal('hide');
showAll(4, 1); --- it is the javascript fuction call to call the
api again
}
else
$('#form-modal .modal-body.p-4').html(res.html);
},
error: function (err) {
console.log(err)
}
})
//to prevent default form submit event
return false;
} catch (ex) {
console.log(ex)
}
}
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddOrEditGL(int id,GLModel glModel)
{
if (ModelState.IsValid)
{
var mappedGL = _mapper.Map<GLDTO>(glModel);
//Insert
if (id == 0)
{
await _glService.CreateGL(mappedGL);
}
//Update
else
{
await _glService.UpdateGL(mappedGL);
//Call Update
}
// How do i filter the based on Main view form controls
return Json(new { isValid = true, html = Helper.RenderRazorViewToString(this, "_GLViewAll", null) });
}
return Json(new { isValid = false, html = Helper.RenderRazorViewToString(this, "AddOrEditGL", glModel) });
}
my Current solution call the api again ( 2 server calls) one for update and another for call update table .. i need to do the same in single call ..Please help to do?
Note: I dont need complete solution , I only need to how to get the AddOrEditGL Controller post method Main view form control text fieds text to filter in DB
If you want to update/add and show the searched data in one request,The quick way is to copy the SearchGLPartial code to the AddOrEditGL function and pass the pageSize,pageIndex,name,code,GLSectionId and GlGroupId by ajax:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddOrEditGL(int id,GLModel glModel,string name,string code,string GLSectionId,string GlGroupId...)
{
if (ModelState.IsValid)
{
var mappedGL = _mapper.Map<GLDTO>(glModel);
//Insert or
//Update
//copy the SearchGLPartial code here and return view with data
}
return Json(new { isValid = false, html = Helper.RenderRazorViewToString(this, "AddOrEditGL", glModel) });
}
If you just do not want to remove showViewAll() jquery,I think you could set session for the filter condition when you first search the data in SearchGLPartial action.Then in your AddOrEdit action,get the session and set the correct url.Finally,you could get the url in ajax success response:
public IActionResult SearchGLPartial(string name,string code,string GLSectionId,string GLGroupId)
{
HttpContext.Session.SetString("name", name);
HttpContext.Session.SetString("code", code);
HttpContext.Session.SetString("GLSectionId", GLSectionId);
HttpContext.Session.SetString("GLGroupId", GLGroupId);
var data = Gllist.Where(a => a.Name.Contains(name) & a.Code.Contains(code)).FirstOrDefault();//filter by yourself
return PartialView("_Search", data);
}
AddOrEdit:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> AddOrEditGL(int id,GLModel glModel)
{
if (ModelState.IsValid)
{
//Insert
//Update
var name = HttpContext.Session.GetString("name");
//other session data...
return Json(new { isValid = true, url="Home/Index?name="+name+"&code="+xxx+"&...."});
}
return Json(new { isValid = false, html = Helper.RenderRazorViewToString(this, "AddOrEditGL", glModel) });
}
Then your ajax:
success: function (res) {
if (res.isValid) {
window.location.href = response.url;
}
else
$('#form-modal .modal-body.p-4').html(res.html);
},
I recommend using the jQuery Unobtrusive AJAX library. Its very easy to use:
It can fetch partial views and place them in a container of your choice using the
data-ajax-update="#panel"
Click here
<div id="panel"></div>
This is an example of a controller action that would return the modal:
public IActionResult GetEditModal() => Partial("ViewName");
Then when the modal is placed in your container, using the data-ajax-success attribute a callback method is called, parse the form using the jQuery Unobtrusive Validation like this:
function SuccessCallback() {
//You can also use the keyword "this" instead of getting the form with jquery
$.validator.unobtrusive.parse($(this));
//or
$.validator.unobtrusive.parse($form);
}
Very useful resources : Link - jQuery Unobtrusive AJAX - GitHub
Update
What i did in previous projects is to include an empty edit modal (a modal with an empty body) then using the library and the data-ajax-update i would replace the body of that modal every time the user pressed the edit button on a table item like this:
<div class="modal fade" id="eModal" data-keyboard="false" data-backdrop="static">
<div class="modal-dialog modal-lg">
<div class="modal-content id="modalContentE">
<div class="modal-header">
<h4 class="modal-title"><i class="nav-icon fas fa-edit"></i> Edit Data</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true"><i class="fas fa-times-circle text-white"></i></span>
</button>
</div>
//New data goes here
</div>
</div>
</div>
And your add Modal would be a regular full modal and each time the user use it to submit data, clear the form.

ASP .NET MVC dynamically created fields not bind to FormCollection

I created a Partial Razor view with dynamically created fields:
for (int i = 0 ; i < atr.Count; i++)
{
<div class="col-md-12 panel panel-default sx-box-shadow-on-hover">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="##string.Format("{0}{1}", "collapse", #atr[i].Id)" aria-expanded="true">
#atr[i].Label
<span class="caret"></span>
</a>
</h2>
</div>
<div id=#string.Format("{0}{1}", "collapse", #atr[i].Id) class="col-md-12 panel-collapse collapse" aria-expanded="true">
<form>
<div class="form-group">
#switch (atr[i].AtrType)
{
case "TXT":
case "NUM":
<input id=#atr[i].Id class="form-control margin5" name=#atr[i].Name type="text" />
break;
case "CHB":
<input class="form-control margin5" name=#atr[i].Name type="checkbox" />
break;
case "DTP":
#(Html.Kendo().DatePicker()
.Name(#atr[i].Name)
.Value(DateTime.Now)
.HtmlAttributes(new { style = "margin-top: 5px; width:100% !important", title = #atr[i].Name })
)
break;
case "WTXT":
<textarea name=#atr[i].Name , rows="3"></textarea>
break;
}
</div>
</form>
</div>
</div>
}
Partial view is placed in other view with static fields and button. When I make POST action using button, in FormCollection I have only values from static fields. I can't bind this field's to Model because user can add or delete them in any moment. Every dynamic field created in partial view has it's own Id and Name. What am I missing here?
Post Action:
[HttpPost]
[Authorize]
public ActionResult Search(FormCollection form)
{
//
}
Main Razor Page:
#using (Html.BeginForm("Search", "Home", FormMethod.Post))
{
<div class="col-md-12 panel panel-default sx-box-shadow-on-hover">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#searchCollapse" aria-expanded="true">
Search options
<span class="caret"></span>
</a>
</h2>
</div>
<div id="searchCollapse" class="col-md-12 panel-collapse collapse in" aria-expanded="true">
<div class="form-group">
<label class="col-md-12 fontBold margin5">Document type:</label>
#(Html.Kendo().DropDownList()
.Name("DocumentTypesDropDownList")
.DataTextField("Name")
.DataValueField("Id")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetDocTypes", "Home");
});
})
.Events(e =>
{
e.Change("docTypeOnChange");
})
.HtmlAttributes(new { style = "margin-top: 5px; width:100% !important", title = "DocumentTypesDropDownList" })
)
<button id="SearchButton" class="btn btn-primary form-control margin5">Search</button>
<div id="searchPanelDiv">
#{
Html.RenderPartial("SearchPanel");
}
</div>
</div>
</div>
</div>
}
Request body looks like this:
DocumentTypesDropDownList=1&Identificator=1234
Parameters from dynamic fields are missing.
I think if you place this:
[HttpPost]
[Authorize]
public ActionResult Search(FormCollection form)
{
var fields = new List<(string, string)>();
foreach (var item in Request.Form)
{
fields.Add((item.Key, item.Value));
}
// do some other stuff
}
in your controller, you are able to read all the fields located in your body request, no matter if they were added dynamically or not.
Nested forms are unsupported in HTML.
If you remove the <form> and </form> tags from the partial view you should be able to capture the dynamic inputs from the FormCollection that is created on the main page by the #using (Html.BeginForm.

How to show loader image until controller method completes in ASP.NET MVC?

I have an Index page like below and on button click I have some code to save data into database and then it goes on details page.
But I the code should go to the details page only after completing the database save operation; I want to show a loader image until then; how can I do this?
Currently I'm using begin post to post method and bind all model not using any ajax call. How can I show loader image and render before process complete to details page?
Index.cshtml
#model Dev.Models.DeviceReg
#using (Html.BeginForm("AddAsync", "Home", FormMethod.Post))
{
<div class="panel panel-primary">
<div class="panel-body">
<div class="row">
<div class="col-md-6">
<h4 id="aa">Name</h4>
<label>Select</label>
<table>
<tr>
<td>
#Html.DropDownListFor(m => m.Name, (SelectList)ViewBag.Name, "---Select Name---")
</td>
</tr>
</table>
</div>
</div>
<div class="row">
<div class="col-md-6">
<h4 id="aa">Model</h4>
<label>Select</label>
<table>
<tr>
<td>
#Html.DropDownListFor(m => m.Type, (SelectList)ViewBag.TypeName, "---Select Type---")
</td>
</tr>
</table>
</div>
</div>
<div class="panel-footer" align="left">
<button type="submit" id="save" class="btn btn-success">
<span class="glyphicon glyphicon-arrow-right"></span> save
</button>
</div>
</div>
}
HomeController.cs
public async Task<ActionResult> AddAsync(DeviceReg deviceRegistration)
{
foreach (var deviceId in collection)
{
// save device information into database
Models.Device newDevice = new Models.Device()
{
Id = Guid.NewGuid(),
DeviceTypeId = deviceRegistration.DeviceType,
PlatformId = deviceRegistration.PlatformType,
DeviceId = deviceId,
};
_repository.InsertDevice(newDevice);
_repository.Save();
}
return View("Details", deviceRegistration);
}
Details.cshml
#model Dev.Models.DeviceReg
<body style="background-color:black">
<div class="panel panel-primary">
<div class="panel-heading" align="center">
<h2 class="panel-title">Details</h2>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-6">
<h3><label>Current Data</label></h3>
<br />
</div>
</div>
<div class="row">
<div class="col-md-6">
<h4 id="aa">Name</h4>
<label>#Model.Name</label>
</div>
</div>
<div class="row">
<div class="col-md-6">
<h4 id="aa">Type</h4>
<label>#Model.TypeName</label>
</div>
</div>
<hr />
<br />
<label>Your process is running.</label>
<br />
<div class="row">
<div class="col-md-6">
<h3><label>Status</label></h3>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div style="clear: both">
<h2 style="float: left">10</h2>
<h6 style="float: right">Active Number</h6>
</div>
</div>
</div>
</div>
</div>
</body>
Well, if you need to show loader while post form is submitting, you can use javascript functions to show it, like
#using (Html.BeginForm("AddAsync", "Home", FormMethod.Post, new { onsubmit = "showLoader(this);" }))
{
...
}
plus JS
<script>
var showLoader = function(form){
$("<div />").css({
'position' : 'fixed',
'left' : 0,
'right' : 0,
'bottom' : 0,
'top' : 0,
'background' : '#0020ff36',
'z-index' : '99',
'text-align' : 'center'
}).appendTo($("body"))
.append(
$("<img />").attr("src", "https://mir-s3-cdn-cf.behance.net/project_modules/disp/35771931234507.564a1d2403b3a.gif")
);
}
</script>
or by jquery event, like
<script>
$("form").submit(function(){
//show loader
});
</script>
example of this code https://dotnetfiddle.net/gfEVSE
But, regarding to your clarification of the issue in comments, it's impossible to show Details page with progress of saving without Javascript or another additional requests.
Example without ajax but with aditional requests every N seconds
[HttpPost]
public ActionResult AddAsync(SampleViewModel deviceRegistration)
{
Task.Run(()=>
{
//Saving to DB
});
return RedirectToAction("Details", id = deviceRegistration.id);
}
public ActionResult Details(int id)
{
var isObjectExistInDb = checkIfExistInDb(id);
if (!isObjectExistInDb){
return View("ShowLoader", id);
}
return View(object);
}
where in ShowLoader.cshtml you need to reload page every N seconds.
With ajax it will be more clear, pretty code. Please, let me know, if you need example with ajax :)

Partial View Not Rendering Inside View

I have a partial view inside another partial view which, when first running the application loads as expected, but when you click to reload the view to push a model into it, it then renders as it's own completely separate view as if it weren't a partial.
I'm calling it inside an Ajax Form like so (On the Action link click, the _GetSearchModal method):
<div id="modelSearch">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">
<i class="fa fa-search"></i> Search by Model / Manufacturer
</h3>
</div>
<div class="panel-body">
#using (Ajax.BeginForm("_GetSearch", "Home", new AjaxOptions() {UpdateTargetId = "modelSearch"}))
{
#Html.AntiForgeryToken()
<div class="input-group">
#Html.TextBox("search", null, new {id = "name", #class = "form-control", placeholder = "Please enter a manufacturer or model"})
<span class="input-group-btn">
<button id="search" class="btn btn-default" type="submit"><i class="fa fa-search"></i></button>
</span>
</div>
if (Model != null)
{
<div id="searchResults" class="fade-in two">
#foreach (var s in Model)
{
<div class="result">
#switch (s.ResultType)
{
case "Man":
#s.Manufacturer
break;
case "Mod":
#Html.ActionLink(s.Manufacturer + Html.Raw(s.Model), "_GetSearchModal", "Home", new {id = s.MachineId}, new {toggle = "modal", data_target = "#MachineModal"})
<img src="~/Images/General/Tier/#(s.TierId).png" alt="Tier #s.TierId"/>
break;
}
</div>
}
</div>
}
}
</div>
</div>
</div>
<!-- Product Modal -->
<div class="modal fade" id="MachineModal" tabindex="-1" role="dialog" aria-labelledby="MachineModalLabel">
#Html.Partial("_SearchModal", new MachineModal())
</div>
And the view itself should load a different view model (MachineModal):
#model SpecCheck.Portals.Web.UI.ViewModels.MachineModal
#if (Model != null)
{
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="MachineModalLabel">#Model.Manufacturer #Model.Model</h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-6">
<img src="~/Images/#Model.Manufacturer/logo.png" alt="#Model.Manufacturer" /><br />
Wiki
</div>
<div class="col-md-6">
#Model.Catagory1 | #Model.Category2<br /><br />
<span class="modal-em">Region: </span> #Model.Region<br />
<span class="modal-em">Status: </span>#Model.Status<br />
<span class="modal-em">Spec Date: </span>#Model.SpecDate
</div>
</div>
</div>
<div class="modal-footer">
View
Quick Compare
Compare
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
}
And the action to do this in the "Home Controller" is:
public ActionResult _GetSearchModal(string machineId)
{
using (var db = new SpecCheckDbContext())
{
MachineModal machine = new MachineModal();
var searchHelper = new SearchHelper(db);
//Get Machine Details
var dbResults = searchHelper.SearchModal(Convert.ToInt32(machineId));
machine.Model = dbResults.Model;
machine.Catagory1 = dbResults.Catagory1;
machine.Category2 = dbResults.Category2;
machine.Manufacturer = dbResults.Manufacturer;
machine.Region = dbResults.Region;
machine.SpecDate = dbResults.SpecDate;
machine.Status = dbResults.Status;
machine.MachineId = dbResults.MachineId;
machine.ManufacturerId = dbResults.ManufacturerId;
var model = machine;
return PartialView("_SearchModal", model);
}
}
First thing I checked was the scripts, they're all in place when the layout page loads so it's not a script issue. Not sure what to change to even try at this point so any suggestions welcome.
In the ajax form:
_GetSearch => _GetSearchModal(name of the action)
Try to return machine to the partial view? Maybe see in the View hierarchy, is there is second _SearchModal partial view, that gets returned?

Add onsubmit event to call JS function in MVC3

I have a problem with calling JS method from form in MVC3 project: I have a "search"page without forms with two buttons - Search and Cancel. Click on search runs JS function runSearch in ProductDefinition.
<div id="productSearch-dialog" class="modal fade" style="width: 1000px; display: none">
<div class="modal-header">
<button class="close" aria-hidden="true" data-dismiss="modal" type="button">×</button>
<h3>Search Results</h3>
</div>
<div class="modal-body" style="height: 650px;">
<div>
<input id="inputname" type="text" /><font class="red-font" id="lblrequired" style="display: none">*</font>
</div>
<div id="searchresultcontain" class="grid">
</div>
<div id="Pagination" class="pagination">
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" onclick="productDefinition.runSearch();">Search</button>
<button class="btn btn-primary" data-dismiss="modal">Cancel</button>
</div>
How can I run this JS method (runSearch) when I press ? As far as I understand, this will be onsubmit event which is form event, so I am need to add form element with onsubmit property. I tried surrounding input field with BeginForm helper method:
#using (Html.BeginForm(new { onsubmit = "productDefinition.runSearch();" }))
{
<input id="inputname" type="text" /><font class="red-font" id="lblrequired" style="display: none">*</font>
<input type="submit" value="Submit" style="visibility: hidden" />
}
but it does not seem to be working - when I press enter I for some reason get source of the page and arrive at localhost/?onsubmit=productDefinition.runSearch() URL.
What can be the source of the problem and how can I get the same behaviour for onsubmit as for onclick?
#using (Html.BeginForm(new { onsubmit = "return runSearch();" }))
<script type="text/javascript">
function runSearch() {
// your logic to perform the search.
return true;
}
</script>
You need to use the following version of BeginForm method in order to specify html attributes.
However, it is considered a bad practice to use inline javascript so I would suggest to assign and id attribute to your form and handle its submit event in the external javascript file instead. If you are using jQuery for your project, here is a good example from their docs - http://api.jquery.com/submit/. In plan JavaSCript it is a bit more tricky but still easy to do.
#model Models.Person
<script type="text/javascript">
$(document).ready(function () {
$('#registerInputId').click(function () {
alert('what do you do before send? For example encrypt the password');
$('#Password').val(CryptoJS.MD5($('#Password').val()));
})
});
</script>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal" style="display: inline-block; margin: 5% auto;">
<div style="font-size: 18px; margin-right:2px; margin-bottom:20px; text-align:right;">Add form</div>
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-5" })
<div class="col-md-7">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Password, htmlAttributes: new { #class = "control-label col-md-5" })
<div class="col-md-7">
#Html.EditorFor(model => model.Password)
#Html.ValidationMessageFor(model => model.Password)
</div>
</div>
<div class="form-group" style="margin-top: 30px;">
<div class="col-md-offset-3 col-md-6">
<input id="registerInputId" type="submit" value="Register" class="btn btn-default" />
</div>
</div>
</div>
}
Form.Id is required if onsubmit handler implements generic functionality, applicable for multiple forms. (example : disabling all input fields)
Form
#using (Html.BeginForm(new {
id = "form24",
onsubmit = "return onSubmitHandler(id);"
}))
handler
<script type="text/javascript">
function onSubmitHandler(formId) { /*formId is form24 */ }
</script>

Categories