Passing user input from View to Javascript function - javascript

I have a view which asks for user input. View is as below -
#(Html.Input(m => m.SchoolName).Id("SchoolName"))
#(Html.Input(m => m.Address).Id("Address"))
#(Html.Input(m => m.Phone).Id("Phone"))
<button class="btn btn-primary" name="btnSchoolSave" id="btnSave">
Submit
</button>
Then I have a javascript function, which handles the click event of the button -
function () {
$("button[name='btnSchoolSave']").on('click', function () {
$.ajax({
url: '/School/SaveSchool', //School is my controller and 'SaveSchool' is the method in the controller.
contentType: 'application/html; charset=utf-8',
type: 'POST',
dataType: 'html'
})
.success(function (result) {
alert("saved")
})
.error(function (xhr, status) {
alert(status);
})
})
};
My Controller method is like below. I have not implemented the method yet.
public void SaveSchool(Models.School model)
{
//TODO
}
My idea is - I want to get all the values inputted by the user in the View, get all those Model values, and pass it to Javascript function and javascript function in return passes the Model to the controller method and save it.
Now, I know that I can directly call my Controller action method from the view and get the saving of data taken care of. But, my requirement is to pass the data to javascript and from javascript call the method and save user input.
How can I do that?
Thanks

#model XXX.YourViewModel
<form id="your-form" style="margin: 0px;">
#Html.AntiForgeryToken()
#Html.HiddenFor(m => m.Id)
#Html.LabelFor(m => m.SchoolName)
#Html.TextBoxFor(m => m.SchoolName)
#Html.ValidationMessageFor(m => m.SchoolName)
#Html.LabelFor(m => m.Address)
#Html.TextBoxFor(m => m.Address)
#Html.ValidationMessageFor(m => m.Address)
#Html.LabelFor(m => m.Phone)
#Html.TextBoxFor(m => m.Phone)
#Html.ValidationMessageFor(m => m.Phone)
<button id="btnSchoolSave" name="edit" type="button">Save</button>
</form>
$("#btnSchoolSave").on('click', function () {
//get the form
var form = $("#your-form");
//validate form
if (!form.valid()) {
return;
}
//serialize the form
serializedForm = form.serialize();
//ajax post
$.ajax({
url: "#Url.Action("CompanyEdit", "CV")",
type: "POST",
data: serializedForm
.........
......
Now the serializedForm will be posted to your controller parameter as the ViewModel
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SaveSchool(YourViewModel modal)
{
//find school
var school = repository.FindSchool(modal.Id)
//map value from modal
school.SchoolName = modal.SchoolName;
..........
repository.SaveScool(school);
}

Related

upload entire model to API via AJAX (mvc c#)

I am working with Ajax, mvc and c#, uploading my model to my api action, using this information I found here: stackoverflow: How to append whole set of model to formdata and obtain it in MVC.
This is my problem When following step by step the above link, my model in the api side comes null:
//this is the conten of the viewmodel object in the api action
guid:{00000000-0000-0000-0000-000000000000}
descripcion:null
Imagen:null
Title:null
This is my viewmodel
public class myViewModel
{
public Guid CursoId { get; set; }
[MaxLength(125)]
public string Titulo { get; set; }
public string Descripcion { get; set; }
[Required(ErrorMessage = "select image file for course")]
[DataType(DataType.Upload)]
public HttpPostedFileBase Imagen { get; set; } //note this is the image
}
My web api, it is a simple action to test
// POST: api/Test
[Route("test")]
public void Post([FromBody]myViewModel model)
{//do something
}
this is my view:
#model ajaxtest.ViewModel.myViewModel
<form id="Editcurso" method="post" action="#" enctype="multipart/form-data">
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "Please fix the following errors.")
<div class="container">
<div class="form-group">
#Html.LabelFor(c => c.Titulo)
#Html.TextBoxFor(c => c.Titulo, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Titulo)
</div>
<div class="form-group">
#Html.LabelFor(c => c.Descripcion)
#Html.TextAreaFor(c => c.Descripcion, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Descripcion)
</div>
<div class="form-group">
#Html.LabelFor(m => m.Imagen)
#Html.TextBoxFor(m => m.Imagen, new { type = "file" })
#Html.ValidationMessageFor(m => m.Imagen)
</div>
<button id="submiter" type="submit" class="btn btn-primary">Listo!</button>
</div>
Here is my javascript:
$('#Editcurso').submit(function(e) {
e.preventDefault(); // prevent the default submit
if (!$(this).valid()) {
return; // exit the function and display the errors
}
jQuery.support.cors = true;
// Create a formdata to pass the model, since the view was generated from viewmodel, it should contain the model.
var model = new FormData($('#Editcurso').get(0));
$.ajax({
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
url: '/api/test/test',
type: 'post',
dataType: 'json',
data: JSON.stringify(model),
processData: false,
contentType: false,
success: function (data) {
console.log(data);
return false;
},
error: function () {
alert('error al postear');
return false;
}
});
e.preventDefault(); // avoid to execute the actual submit of the form.
});
});
What do you think is wrong and how can I fix it? thanks.

How to send files using modal window and MVC

I have a working modal window that saves an entity to the database, my question is how to send files from the modal?
Here as my current JavaScript function:
$('#btn-save').on('click', function () {
$.ajax({
url: '#Url.Action("CreateModal", "Suggestions")',
type: 'POST',
data: $('#modal-form').serialize(),
success: function (data) {
if (data.success == true) {
$('#suggestion-modal').modal('hide');
location.reload(true);
} else {
$('.modal-content').html(data);
$('#suggestion-modal').modal('show');
}
}
});
});
This part does not send data, but works fine when not using modal and using standard MVC Create template:
<form id="modal-form" method="post" enctype="multipart/form-data">
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.UserId)
<div>
#Html.LabelFor(model => model.Title)
#Html.EditorFor(model => model.Title)
#Html.ValidationMessageFor(model => model.Title, "")
</div>
<div>
#Html.LabelFor(model => model.Images, "Images")
<input type="file" name="upload" multiple />
</div>
<div>
<input id="btn-save" type="button" value="" />
</div>
</form>
I've left the rest of the partial view out as that all works correctly.
EDIT: Just added where my button was in the form. It was there, I just removed much of the code not relevant to the question - should have left the button in. Also added extra model properties - These must be sent with the file, including validation token.
EDIT: Many thanks to Jasen. I've included the JavaScript below for anyone else struggling with this.
$('#btn-save').on('click', function () {
var formData = new FormData($('form').get(0));
$.ajax({
url: '#Url.Action("CreateModal", "Suggestions")',
type: 'POST',
processData: false,
contentType: false,
data: formData,
success: function (data) {
if (data.success == true) {
$('#suggestion-modal').modal('hide');
location.reload(true);
} else {
$('.modal-content').html(data);
$('#suggestion-modal').modal('show');
}
}
});
});

Textbox lost focus event in MVC.NET

I am working on a MVC project and I am having few issues with textbox lost focus event.
First I have a form there are four textboxes field, on first text box we need to pass name of the employee but we have called this textbox lost focus event to populate all records of Employee if it is already in the database but I am having problem when I pass name in the textbox and clicking "save" button then first textbox event called to check if record exist in the database or not then I need to reclick button once again to save my records if not exist.
So in that case I have to click button twice.
Please help with your thoughts I do not want user to click twice.
Thanks
I would say, you may use Jquery ajax to do the work.
When the textbox focus is lost, an ajax get call will be made to the controller action which will check the DB and will return the status whether the username already exist or not.
Jquery:
$(document).ready(function () {
$("#UserName").focusout(function () {
var username = $("#UserName").val();
var fullurl = '/User/UserNameCheck?username=' + username;
if (username.length > 0) {
$.ajax({
url: fullurl,
type: 'GET',
dataType: 'json',
contentType: 'application/json; charset=utf-8',
//data: username,
success: function (data) {
if (data == 'UserNotPresent') {
$("#username_NotPresent_lbl").show();
}
else if (data == 'UserPresent') {
$("#username_Present_lbl").show();
}
else {
$("#failed_check_lbl").show();
}
},
error: function (e) {
$("#failed_check_lbl").show();
}
});
}
});
$("#UserName").focus(function () {
$("#username_NotPresent_lbl").hide();
$("#username_Present_lbl").hide();
$('#failed_check_lbl').hide();
}); });
Controller Action:
[AllowAnonymous]
[HttpGet]
public JsonResult UserNameCheck(string username)
{
Users loggedInUser = db.Users.FirstOrDefault(x => x.UserName == username);
if (loggedInUser != null)
{
return Json("UserPresent", JsonRequestBehavior.AllowGet);
}
else
{
return Json("UserNotPresent", JsonRequestBehavior.AllowGet);
}
}
View:
<div class="form-group">
#Html.LabelFor(model => model.UserName, new {#class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.UserName)
#Html.ValidationMessageFor(model => model.UserName)
#Html.Label("Sorry this user name is already in use", new {id="username_Present_lbl", #class ="ErrorLbl"})
#Html.Label("User name available for use", new {id="username_NotPresent_lbl", #class ="SuccesLbl"})
#Html.Label("Failed to validate the user name", new {id="failed_check_lbl", #class ="FailedCheckLbl"})
</div>
</div>

the required anti-forgery form field __requestverificationtoken is not present Error while ajax call

anti-forgery form field “__RequestVerificationToken” is not present
when using jQuery Ajax and the Html.AntiForgeryToken()
How to make ajax request with anti-forgery token in mvc
AJAX Posting ValidateAntiForgeryToken without Form to MVC Action Method
All the answers above did not help me. I get this error in my request with Jquery Ajax call:
"The required anti-forgery form field "__RequestVerificationToken" is
not present"
If I comment [ValidateAntiForgeryToken] attribute at POST action method it is working fine. I want to know why I am getting this error.
#using (Html.BeginForm("Save", "AddPost", FormMethod.Post, new { id = "CreateForm" }))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>GropPost_Table</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.Body, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.Body, new { id = "Bf" })
#Html.ValidationMessageFor(model => model.Body)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input id="btnAdd" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult Save([Bind(Include = "Body")] GropPost_Table groppost_table)
{
if (ModelState.IsValid)
{
groppost_table.GroupID = 1;
groppost_table.ID = 1;
groppost_table.PostDate = System.DateTime.Now;
db.GropPost_Table.Add(groppost_table);
db.SaveChanges();
return Json(groppost_table);
}
else
{
return Json("we Couldent add your post");
}
}
<script type="text/javascript">
$("#btnAdd").click(function () {
var GropPost_Table = {
"Body": $("#Bf").val()
};
var token = $('#CreateForm input[name=__RequestVerificationToken]').val()
var headers = {};
headers['__RequestVerificationToken'] = token;
$.ajax( {
type: "POST",
url: "#Url.Action("Save","AddPost")",
data: JSON.stringify(GropPost_Table),
contentType: "application/json;charset=utf-8",
processData: true,
headers:headers,
success: function (dataR) {
$("#Bf").val('');
},
error: function (dataR) {
$("#Bf").val('');
alert(dataR.toString());
}
});
});
</script>
I've alway included the Request Verification Token in the data of the POST and not the headers. I would approach it like this:
First add type="submit" to your input button so it will submit the form when clicked. Then in your javascript:
// Listen for the submit event on the form
$('#CreateForm').on('submit', function(event) {
var $form = $(this);
$.ajax({
// Html.BeginForm puts the url in the
// "action" attribute
url: $form.attr('action'),
// Serializing the form will pick up the verification
// token as well as other input data
data: $form.serialize(),
success: function(dataR) {
$('#Bf').val('');
},
error: function(dataR) {
$('#Bf').val('');
alert(dataR.toString());
}
});
// Preventing the default action will keep the form
// from doing a full POST.
event.preventDefault();
});

JQuery ui autocomplete in a MVC partial view only works once

I've been trying to get autocomplete to work for my partial view using JQuery ui. The partial view is updated using AJAX.
The problem is that the autocomplete only works up until the point where the partial view is updated.
This is my partial view
<div id="tagList">
#using (Ajax.BeginForm("AddToTagList", new { urlLocation = Model.UrlLocation }, new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.Replace, UpdateTargetId = "tagList" }))
{
if (Model.TagList != null)
{
<div class="form-group">
#Html.LabelFor(model => model.Tag.Text, "Tags", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-xs-10">
<div class="input-group" style="max-width: 300px;">
#Html.EditorFor(model => model.Tag.Text, new { htmlAttributes = new { #class = "form-control", #id = "search_term" } })
#Html.ValidationMessageFor(model => model.Tag.Text, "", new { #class = "text-danger" })
<div class="input-group-btn">
<button type="submit" value="Add Tag" class="btn btn-default">+</button>
</div>
</div>
</div>
</div>
}
}
</div>
This is my JavaScript
$(document).ready(function () {
$("#search_term").autocomplete({
source: function (request, response) {
$.ajax({
url: "/Tag/SearchAutoComplete",
type: "POST",
dataType: "json",
data: { term: request.term },
success: function (data) {
response($.map(data, function (item) {
return { label: item.Text, value: item.Text };
}));
}
});
},
});
});
and this is my autocomplete search action
public JsonResult SearchAutoComplete(string term)
{
using (IDocumentSession session = RavenDbConfig.RavenDBDocumentStore.OpenSession())
{
var results = session.Query<Tag>().Where(x => x.Text.StartsWith(term)).ToList();
return Json(results,JsonRequestBehavior.AllowGet);
}
}
So, my question is, how can i make this work even after the partial view has been updated once?
Your problem is when you reload your PartialView you basicaly delete some part of DOM in your html document and create new one. And all your bindings that you add in $(document).ready() event will be lost.
One of the posible solutions for this problem is to place your autocomplete init code in addition to .ready() event in jquery .ajaxSuccess() global event becouse you reload your PartialViews via Ajax. Like this:
$(document).ajaxSuccess(function() {
$("#search_term").autocomplete({
source: function (request, response) {
$.ajax({
url: "/Tag/SearchAutoComplete",
type: "POST",
dataType: "json",
data: { term: request.term },
success: function (data) {
response($.map(data, function (item) {
return { label: item.Text, value: item.Text };
}));
}
});
},
});
});
That way you will init your autocomplete every time you reload PartialView.

Categories

Resources