Using Html.BeginForm and ajax call same action conflict? - c#

When I try to add Ajax to pass another data into my action controller my model parameter was affected the value was null and my Ajax parameter has a value. I do not think it is because I am using Html.beginform('index', 'payable') and I used Ajax url: '#Url.Action("index", "payable")', with the same ActionResult.
You can see the reference below.
#using (Html.BeginForm("index", "payable", FormMethod.Post, new { enctype = "multipart/form-data" }))<div class="col-md-2">
<div class="form-group">
#Html.LabelFor(x => x.Amount, new { #class = "form-label" })
#Html.TextBoxFor(x => x.Amount, new { #class = "form-control" })
</div>
</div>
<div class="col-md-2">
<div class="form-group">
#Html.LabelFor(x => x.ImagePath, new { #class = "form-label" })
<input type="file" name="file" id="files" />
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<button type="submit" id="btnUpload" class="btn btn-primary btn-sm" onclick="saveSelected()"><i class="fas fa-save"></i> Submit Payment</button>
</div>
</div>{
My Ajax
function saveSelected() {
$.ajax({
url: '#Url.Action("index", "payable")',
type: 'POST',
data: { ids: ids },
traditional: true,
success: function (data) {
alert("success");
}
});
}
My Controller
public ActionResult Index(PayableFormModel model, HttpPostedFileBase file, int[] ids)
{
return View();
}

Html.Beginform and ajax cannot use at same time,even you add a
onclick function. So the ajax won't work and all data are submitted
by form. If you want to submit model and any other data, put all them into form or only use ajax.
When you upload file, model cannot get file's name or path directly. You should store file into a folder or directory,then assign this path to model's imagepath.(Examle code is blew)
In index page, {} should follow using(), otherwise it will report error.
public ActionResult Index(PayableFormModel model,HttpPostedFileBase file,int[] ids)
{
string filepath = Server.MapPath("~/image/");
Directory.CreateDirectory(filepath);
file.SaveAs(Path.Combine(filepath, file.FileName));
model.ImagePath = filepath + file.FileName ;
return View();
}

Related

How do you change view by changing dropdownlist?

I have a dropdown list in a View. And if I change the selection, I want to change immediately the values in the View. The textbox of Type and Description.
How do you do that?
#Model GenreModel
#using (Html.BeginForm("EditGenre", "Home", FormMethod.Post))
{
#model GenreModel
<div class="text-center">
<h1 class="display-4">Edit genre</h1>
<p> <input type="submit" value="submit" name="Save" /></p>
<p>
<label>Select genre: </label>
#Html.DropDownListFor(Model => Model.Description, new SelectList(ViewBag.GenreList, "Description", "Description"), new { onchange = "onChangeSelection(this.value);" });
</p>
<p>
<label>Type</label>#Html.TextBoxFor(Model => Model.Type)
</p>
<p>
<label>Description</label>#Html.TextBoxFor(Model => Model.Description)
</p>
</div>
}
This is the method in the Controller.
[HttpPost]
public IActionResult EditGenre(string description)
{
var dto = _genreService.GetGenreByName(description);
var model = _mapper.Map<GenreDto, GenreModel>(dto);
ViewBag.GenreList = _genreService.GetAllGenres().OrderBy(g => g.Description);
return View(model);
}
and finally:
<script>
function onChangeSelection(val) {
{
$.ajax({
url: #Url.Action("EditGenre", "Home"),
//type: "POST",
data: { description: val },
success: function (data) {
// put result of action into element with class "result"
$('.result').html(data);
},
error: function () {
alert(val + ' not found.');
}});
}
</script>
Change the DropDownList like this:
#Html.DropDownListFor(Model => Model.Description, new SelectList(ViewBag.GenreList, "Description", "Description"));
And submit the form in the onchange function:
<script>
$("#Description").on("change", function () {
$(this).closest("form").submit();
})
</script>
It seems my DropDownList didn't fire a Submit. I leave the javascript and using a hidden field.
And this solution works fine.
<p>
<label>Select genre: </label>
#Html.Hidden("#Discription")
#Html.DropDownListFor(Model => Model.Description, new SelectList(ViewBag.GenreList, "Description", "Description"), new { onchange = "this.form.submit();" });
</p>

Using AJAX to contact a method on server

I want to use ajax/call a webmethod in the controller by clicking a button that is in a BeginForm
I have a submit button in a Html.BeginForm. Clicking this button will as we know, send the info from the model to the server. Here is the simplified code.
#using (Html.BeginForm())
{
...
<div class="form-group">
#Html.LabelFor(model => model.FirstName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { #class = "form-control", #readonly = "readonly" } })
#Html.ValidationMessageFor(model => model.FirstName, "Navn skal angives", new { #class = "text-danger" })
</div>
</div>
...
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Tilføj" class="btn btn-default" id="submitBut" />
</div>
</div>
}
The corresponding Controller looks like this
[HttpPost]
public ActionResult AttachCard(Card model, int MemberID)
{ ... }
I will need to add the annotation [WebMethod]
My issue is that I want to use JQuery Dialog to notify the client, when the card is added. For this I need a true or false value from the server. The dialog message will depend on this boolean value.
I have written some AJAX code. This is not tested yet, as I'm stuck
function attachCard(MemberID, action, controller) {
var url = '/' + action + '/' + controller;
$.ajax({
type: "POST",
url: url,
data: $("form").serialize(),
contentType: 'application/html; charset=utf-8',
dataType: "html",
success: function (status) {
alert("Test from server: " + status);
},
error: function (msg) {
alert("Error");
}
})
}
I want this ajax function to run when the user clicks on the button that you see in my Html.BeginForm. But is this possible? If I add an onclick listener while it's in the BeginForm, then the webmethod will be called twice I think, and this will result in an exception. I am thinking about moving that button out of the BeginForm, and add an onclick event on the button. But then the rest of the info from the model (in the BeginForm) won't be submittet.
How can I do this?
You can use Ajax.BeginForm instead. Here is my working sample code
#using (Ajax.BeginForm("CreateAndUpdate", "WidgetContent", new AjaxOptions
{
OnSuccess = "GroupSubmitted",
OnFailure = "GroupError",
}, new { role = "form", #id = "groupform" }))
{
}
And your Javascript callback functions
function GroupError(ajaxContext) {
//Error message
}
function GroupSubmitted(result) {
if (result.success) {
}
else {
}
}

Passing and handling of varibles to a function with AJAX in MVC

I'm having trouble passing a variable into a function in my view. I'm fairly new to MVC and not sure how I save and pass information.
#model Models.Schedule.SheduleModel
#{
Layout = null;
}
<div>
<div class="tableRow">
<p>Make a schedule reminder.</p>
</div>
<div class="tableRow tableRowHeading">
<div class="row" style="width: 210px">Name</div>
<div class="row" style="width: 210px">Number</div>
</div>
#foreach (var shedule in Model.ScheduleList)
{
<div class="tableRow">
#using (Html.BeginForm("UpdateSchedule", "Schedule", FormMethod.Post))
{
<div class="cell" style="width: 210px">
#Html.HiddenFor(model => schedule.Id)
#Html.TextBoxFor(model => schedule.Name, new { #class = "inputFieldText" })
#Html.ValidationMessageFor(model => schedule.Name)
</div>
<div class="cell" style="width: 210px">
#Html.TextBoxFor(model => agent.ContactNumber, new { #class = "inputFieldText" })
#Html.ValidationMessageFor(model => agent.ContactNumber)
</div>
<div class="cell">
<button name="Update" type="submit" value="Update" class="button" title="Update details">
<span class="text">Update</span>
</button>
</div>
<div class="cell">
<button class="button" type="button" onclick="deleteFromSchedule();" value="Delete">
<span class="text">Delete</span>
</button>
</div>
}
</div>
}
</div>
#Scripts.Render("~/bundles/jqueryval")
<script>
function deleteFromSchedule() {
$.ajax(
{
type: 'POST',
url: urlBase + 'Schedule/UpdateSchedule/' + Id,
data:
{
Id: Id
},
success: function (data) {
console.log(data);
},
error: function () {
var errorMessage = 'Error occurred while sending message';
console.log(errorMessage);
}
});
}
}
</script>
I'm trying to pass the schedule Id in HiddenFor into the delete function but everything I try doesn't work, i'm also curious on how to handle the information gotten from the text box in a later unwritten div, I'd like to produce text on the screen saying
User #Model.Name and number #Model.Number will be notified of schedule change but I keep displaying blank spaces. an I use the form I'm creating for this information, what would the syntax be?. My method in the schedule controller is very straight forward.
[HttpPost]
public void UpdateSchedule(int Id)
{
////do stuff here
}
The simplest way is to add your id from the schedule into the inline function call (using razor), and add an id param into your javascript delete function:
<div class="cell">
<button class="button" type="button" onclick="deleteFromSchedule(#schedule.Id);" value="Delete">
<span class="text">Delete</span>
</button>
</div>
<script>
function deleteFromSchedule(id) {
$.ajax(
{
type: 'POST',
url: urlBase + 'Schedule/UpdateSchedule/' + id,
data:
{
Id: id
},
success: function (data) {
console.log(data);
},
error: function () {
var errorMessage = 'Error occurred while sending message';
console.log(errorMessage);
}
});
}
}
</script>

MVC button click call POST Action method

How can I call an MVC action method with complex parameters, like the below, from a button click event?
[ValidateInput(false)]
[HttpPost]
public ActionResult Export(ViewModel vm)
{
// some logic
}
I have made it a POST action because I need to pass HTML tags of the current page on which the button is to the action method which is too long. I have tried this but this its for a GET operation
<input type="button" value="Detail" onclick="location.href='#Url.Action("Export", "Report")?html=' + $('#test').html()" />
If you want to do this using a button click you can subscribe the to click event of the button in JS. In your JS, you can do an ajax post, which will post a JSON object (your VM) to your action:
Razor:
<input type="button" value="Detail" id="buttonId" />
JS:
$('#buttonId').click(function () { //On click of your button
var property1 = $('#property1Id').val(); //Get the values from the page you want to post
var property2 = $('#property2Id').val();
var JSONObject = { // Create JSON object to pass through AJAX
Property1: property1, //Make sure these names match the properties in VM
Property2: property2
};
$.ajax({ //Do an ajax post to the controller
type: 'POST',
url: './Controller/Action',
data: JSON.stringify(JSONObject),
contentType: "application/json; charset=utf-8",
dataType: "json"
});
Another way to do this is submit the view model using a form.
#using (Html.BeginForm("ActionName", "ControllerName", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.PropertyName1, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<input type="text" id="PropertyName1" name="PropertyName1" class="form-control" />
#Html.ValidationMessageFor(model => model.PropertyName1, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.PropertyName2, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.PropertyName2, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.PropertyName2, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Button text" class="btn btn-primary" />
</div>
</div>
</div>
}
You can do that with HTML form
<form action="#Url.Action("Export", "Report")" method="POST">
<input type="hidden" name="html" value="ADD YOUR HTML HERE">
<input type="button" value="Detail" />
</form>
And inside your controller you need to use html parameter
[ValidateInput(false)]
[HttpPost]
public ActionResult Export(ViewModel vm, string html)
{
// some logic
}
try this
<form action="#Url.Action("Export", "Report")" method="POST">
<input type="hidden" name="html" id="html" value="ADD YOUR HTML HERE">
<input type="button" id="btn1" value="Detail" />
</form>
add Script in js
$("#btn1").click(function(){
$("#html").val($('#test').html());
})
add param in your method string html

table id is not passing from view to controller in ASP.NET MVC5

I am using asp.net mvc5 app and I have partialView which I am using for both add and delete operations and I have separate actionResult to deal each requested according that is fire by jQuery Ajax functions.... I got figure problem when I try to edit record. it pick right record and display in screen in HttpGet actionResult but when I submit record with updated field, it doesn't update that in database and is because it doesn't send recordID {PK} back to action in controller unless I use hidden value for primary key in view... however with this I can't create new record!
partial View
#model DatabaseLayer.TableMappings.FeeZone
<script>
function CancelPage() {
$.ajax({
type: "POST",
url: "/Qualification/FeeZoneHome",
dataType: 'json',
success: function (jsonData) {
window.location = jsonData.redirectUrl;
},
error: function (error) {
}
});
}
</script>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>FeeZone</h4>
<hr />
#Html.ValidationSummary(true)
<!--<div class="form-group">
<div class="col-md-10">
#Html.HiddenFor(model => model.FeeZoneID)
</div>
</div>-->
<div class="form-group">
#Html.LabelFor(model => model.FeeZoneDescription, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FeeZoneDescription)
#Html.ValidationMessageFor(model => model.FeeZoneDescription)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default">
<input type="button" value="Cancel" class="btn btn-default" onclick="CancelPage();" />
</div>
</div>
</div>
}
controller Method
[HttpGet]
public ActionResult EditFreeZoneByID(string FreeZoneID)
{
int numID = Convert.ToInt32(FreeZoneID);
return PartialView("Partial_CreateNewFreeZone", Q_UOF.GetFreeZoneByID(numID));
}
[HttpPost]
public ActionResult EditFreeZoneByID(FeeZone obj)
{
try
{
if (ModelState.IsValid)
{
Q_UOF.EditSubject(obj);
}
}
catch (DataException)
{
ModelState.AddModelError("FeeZone", "Unable to Save Changes.");
}
return RedirectToAction("FreeZone");
}
You need to send the Primary Key value from your form to your Action method so that it can update the proper record. For this you definitly need to keep the ID in the form in a hidden field.
I am not sure what you mean by "You can not create new record if you keep the hidden variable". I do not think it is going to be a problem. You can use the same HttpPost action method to save New record and update an existing record. You may simply check the value of your primary key property and If it is 0, Add a new record , else update existing record
[HttpPost]
public ActionResult EditFreeZoneByID(FeeZone obj)
{
if(obj.FreeZoneID==0)
{
//This is a new record. Save it
}
else
{
//Update an existing record now.
}
// to do : Return somethign valid or redirect
}

Categories