Passing the Model back to Server when doing Ajax - ajax

here's the code in my .cshtml:
#model WebComposite.Models.MyModel
#using (Html.BeginForm())
{
#Html.TextBoxFor(m => m.id)
#Html.TextBoxFor(m => m.name)
}
#Scripts.Render("~/Scripts/MyScript.js")
here's the code in MyScript.js:
$('form').submit(function (e)
{
e.preventDefault();
//normal Ajax (my own custom version as i'm sure every one has one of these:)
SimpleAjax("MyAction", function () { alert("Done"); });
});
And the Controller code:
[HttpPost]
public ActionResult MyAction(MyModel model)
{
//Problem here is model.id and model.name are empty
}
any ideas?
thanks in advance

After a quick look around I guess the solution is pretty darn simple (thank you jquery!!):
Simply serialize everything you have in the form and post it back to the controller from your ajax call:
$("form").serializeArray();
Here's my own full implementation of Ajax calls
There are 3 functions (you'll to call SimplAjaxPost(url, funcDelegate) and it will do the rest for you
function Ajax(url, dataObj, getOrPost, theContext, theContentType, theDataType, successFuncName, failedFuncName, alwaysFuncName)
{
//GET or POST:
if (getOrPost == null) { getOrPost = 'POST'; }
//Header (what we're sending to the server): http://stackoverflow.com/questions/2722750/ajax-datatype
if (theContentType == null) { theContentType = 'application/x-www-form-urlencoded; charset=UTF-8'; }
//response (what we're expeting in return):http://stackoverflow.com/questions/2722750/ajax-datatype
if (theDataType == null) { theDataType = ""; }
//exposing "this" to whatever: http://stackoverflow.com/questions/5097191/ajax-context-option
if (theContext == null) { theContext = document.body; }
var theURL = NoCache(url);
$.ajax(
{
url: theURL,
data: dataObj,
type: getOrPost,
contentType: theContentType,
dataType: theDataType,
context: theContext,
async: false,
success: successFuncName,
fail: failedFuncName,
always: alwaysFuncName,
complete: AjaxScripts
});
}
function SimpleAjax(url, successFunctionName)
{
var dataObj = null;
Ajax(url, dataObj, null, null, null, null, successFunctionName, null, null)
}
function SimpleAjaxPost(url, successFunctionName)
{
var dataObj = null;
if ($("form").length == 1)
{
dataObj = $("form").serializeArray();
}
Ajax(url, dataObj, null, null, null, null, successFunctionName, null, null)
}
function NoCache(url)
{
var t = new Date();
var qps = "?";
if (url.indexOf("?") > 0)
{
qps = "&";
}
return url + qps + t.getYear() + t.getMonth() + t.getDay() + t.getHours() + t.getMinutes() + t.getSeconds() + t.getMilliseconds();
}

Related

ASP.net cascading dropdown list

trying to implement country state dropdown in mvc but couldn't..
conotroller :-
[HttpGet]
public ActionResult GetCities(int StateId)
{
Business.Services.City cityService = new Business.Services.City();
List<Business.Models.City> stateList = cityService.GetCityByStateId(StateId);
//var jsonSerialiser = new JavaScriptSerializer();
//var json = jsonSerialiser.Serialize(stateList);
return Json(new { stateList }, JsonRequestBehavior.AllowGet);
}
method:
public List<Models.City> GetCityByStateId(int StateId)
{
try
{
var list = new List<SelectListItem>();
Collection<DBParameters> parameters = new Collection<DBParameters>();
parameters.Add(new DBParameters() { Name = "StateId", DBType = DbType.Int32, Value = StateId });
var city = this.ExecuteProcedure<Models.City>("GetCityByState", parameters).ToList();
//if (city != null && city.Count > 0)
//{
// list = city.Select(x => new SelectListItem { Text = x.CityName, Value = x.StateId.ToString() }).ToList();
//}
return city;
}
catch (Exception ex)
{
throw;
}
}
change event:
$('.ddlstate').change(function () {
debugger;
$.ajax({
url: '#Url.Action("GetCities", "User")',
type: "GET",
data: { StateId: $(this).val() },
dataType: "json",
success: function (result) {
debugger;
//alert(result.stateList[0].CityId);
$.each(result.stateList, function () {
debugger;
$('.cityddl').append($("<option></option>").val(CityId).html(CityName));
});
},
error: function (result, status, jQxhr) {
alert("Error: " + result + "-" + status + "-" + jQxhr);
}
});
});
i get count of the citites in method and controller but when i run project and change state dropdown i got blank city dropdown. what is wrong?
It looks like you're missing a couple of things in the $.each() call.
You should pass the JSON result from the ajax call to the $.each
You also need to provide a parameter to the callback function so that the callback function has something to work with
It could look something like this:
$.each(result.stateList, function(index, city) {
$('.cityddl').append($("<option></option>").val(city.CityId).html(city.CityName));
});

MVC Ajax function call twice

I have a problem with an ajax function. I want to send param to method on controller and this ajax function call method twice.
ajax:
$(document).ready(function () {
$(document).on('click', '.exp', function (e) {
var st_date = $(this).parent().find('.start').val();
var ed_date = $(this).parent().find('.end').val();
$.ajax({
url: '/Reports/Report_CLeav/',
data: {
start_date:st_date,
end_date:ed_date
}
}).success(function (data) {
})
});
})
$(".exp").click(function() {
var st_date = $(this).parent().find('.start').val();
var ed_date = $(this).parent().find('.end').val();
$.ajax({
url: '/Reports/Report_CLeav/',
data: {
start_date:st_date,
end_date:ed_date
}
}).success(function (data) {
})
});
?
<th>
Start date: #Html.TextBox("start_date", null, new { #class = "dateClass start", id = "StartDate" })
End date: #Html.TextBox("end_date", null, new { #class = "dateClass end", id = "EndDate", #data_toggle = "popover", #data_content = "End date should be greater than Start date. ", #title = "Attention" })
#Html.ActionLink("Export Report", "Report_CLeav", "Reports", new { #class = "IndexButton exp", #style = "text-decoration: none;color:white" })
</th>
"Controller"
public class ReportsController : Controller
{
// GET: Export
public ActionResult Index()
{
return View();
}
public void Report_CLeav(DateTime ?start_date, DateTime ? end_date)
{
string path = HttpContext.Server.MapPath("~/App_Data/reports/Report_LeavingCompanyHCT.xlsx");
Models.Report.Report_CompLeav reportcompleav = new Models.Report.Report_CompLeav();
var fileinfo = new FileInfo(path);
using (ExcelPackage package = new ExcelPackage(fileinfo))
{
var currentWorksheet = package.Workbook.Worksheets["HC"];
using (var excelToExport = new ExcelPackage())
{
excelToExport.Workbook.Worksheets.Add(currentWorksheet.Name, currentWorksheet);
var workBook = excelToExport.Workbook.Worksheets["HC"];
try
{
workBook = reportcompleav.exportAllEmployeeDataRRecords(workBook,start_date,end_date);
}
catch (Exception e)
{
ViewBag.IsError = true;
}
excelToExport.Save();
Stream stream = excelToExport.Stream;
var memoryStream = stream as MemoryStream;
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats";
Response.AddHeader("Content-Disposition",
"attachment; filename=" + fileinfo.Name);
Response.BinaryWrite(memoryStream.ToArray());
}
}
}
}
}

Ajax post a JSON model to ASP.Net MVC4 with Anti-forgery token

I am submitting json model through ajax post. Its not working after adding user validation.
var token = $('input[name=""__RequestVerificationToken""]').val();
var headers = {};
headers['__RequestVerificationToken'] = token;
$.ajax({
url: '/SalesQuotation/Create',
cache: false,
headers: headers,
data: JSON.stringify(salesquotation),
type: 'POST',
contentType: 'application/json;',
dataType: 'json',
async: false,
success: function (result) {
if (result.Success == "1") {
window.location.href = "/SalesQuotation/Create";
}
else {
alert(result.ex);
}
}
});
Controller :
[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult Create(SalesQuotation salesquotation)
{
try
{
if (ModelState.IsValid)
{
if (salesquotation.QuotationId > 0)
{
var CurrentsalesQuotationSUb = db.SalesQuotationSubs.Where(p => p.QuotationId == salesquotation.QuotationId);
foreach (SalesQuotationSub ss in CurrentsalesQuotationSUb)
db.SalesQuotationSubs.Remove(ss);
var CurrentsalesQuotationDta = db.DTATrans.Where(p => p.QuotationId == salesquotation.QuotationId);
foreach (DTATran ss in CurrentsalesQuotationDta)
db.DTATrans.Remove(ss);
foreach (SalesQuotationSub ss in salesquotation.salesquotationsubs)
db.SalesQuotationSubs.Add(ss);
foreach (DTATran ss in salesquotation.dtatrans)
db.DTATrans.Add(ss);
db.Entry(salesquotation).State = EntityState.Modified;
}
else
{
db.SalesQuotations.Add(salesquotation);
}
db.SaveChanges();
}
}
catch (Exception ex)
{
return Json(new { Success = 0, ex = "Unable to save... " + ex.Message.ToString()});
}
return Json(new { Success = 1, ex = new Exception("Saved successfully.").Message.ToString() });
}
View:
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<input name="__RequestVerificationToken" type="hidden"
value="H4zpQFvPdmEdGCLsFgeByj0xg+BODBjIMvtSl5anoNaOfX4V69Pt1OvnjIbZuYrpgzWxWHIjbng==" />
The server return
What could be missing in my method. Please advice....
Attribute selectors should only have a single set of quotes around them. Your code has two quotes on each side.
This:
var token = $('input[name=""__RequestVerificationToken""]').val();
should be this:
var token = $('input[name="__RequestVerificationToken"]').val();
Use [ValidateJsonAntiForgeryToken] attribute in action method.

How to include the #Html.AntiForgeryToken() when deleting an object using a Delete link

i have the following ajax.actionlink which calls a Delete action method for deleting an object:-
#if (!item.IsAlreadyAssigned(item.LabTestID))
{
string i = "Are You sure You want to delete (" + #item.Description.ToString() + ") ?";
#Ajax.ActionLink("Delete",
"Delete", "LabTest",
new { id = item.LabTestID },
new AjaxOptions
{ Confirm = i,
HttpMethod = "Post",
OnSuccess = "deletionconfirmation",
OnFailure = "deletionerror"
})
}
but is there a way to include #Html.AntiForgeryToken() with the Ajax.actionlink deletion call to make sure that no attacker can send a false deletion request?
BR
You need to use the Html.AntiForgeryToken helper which sets a cookie and emits a hidden field with the same value. When sending the AJAX request you need to add this value to the POST data as well.
So I would use a normal link instead of an Ajax link:
#Html.ActionLink(
"Delete",
"Delete",
"LabTest",
new {
id = item.LabTestID
},
new {
#class = "delete",
data_confirm = "Are You sure You want to delete (" + item.Description.ToString() + ") ?"
}
)
and then put the hidden field somewhere in the DOM (for example before the closing body tag):
#Html.AntiForgeryToken()
and finally unobtrusively AJAXify the delete anchor:
$(function () {
$('.delete').click(function () {
if (!confirm($(this).data('confirm'))) {
return false;
}
var token = $(':input:hidden[name*="RequestVerificationToken"]');
var data = { };
data[token.attr('name')] = token.val();
$.ajax({
url: this.href,
type: 'POST',
data: data,
success: function (result) {
},
error: function () {
}
});
return false;
});
});
Now you could decorate your Delete action with the ValidateAntiForgeryToken attribute:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Delete(int id)
{
...
}
Modifying the answer by Bronx:
$.ajaxPrefilter(function (options, localOptions, jqXHR) {
var token, tokenQuery;
if (options.type.toLowerCase() !== 'get') {
token = GetAntiForgeryToken();
if (options.data.indexOf(token.name)===-1) {
tokenQuery = token.name + '=' + token.value;
options.data = options.data ? (options.data + '&' + tokenQuery)
: tokenQuery;
}
}
});
combined with this answer by Jon White
function GetAntiForgeryToken() {
var tokenField = $("input[type='hidden'][name$='RequestVerificationToken']");
if (tokenField.length == 0) { return null;
} else {
return {
name: tokenField[0].name,
value: tokenField[0].value
};
}
Edit
sorry - realised I am re-inventing the wheel here SO asp-net-mvc-antiforgerytoken-over-ajax/16495855#16495855

sending multiple parameters asp.net mvc jquery ajax

I get server error:status of 500 when I try to send 2 parameters to my action in a controller with jquery ajax, dont know why?
this is the jquery code:
$(".genreLinks").click(function () {
var genreId = $(this).attr("name");
var songId = $("#hiddenRank").val();
$.ajax({
beforeSend: function () { ShowAjaxLoader(); },
url: "/Home/AddPointAndCopyTopTenFavToPlaylist/",
type: "POST",
data: { id: songId, genre: genreId },
success: function (data) {
if (data.status === 1) {
HideAjaxLoader(), ShowMsg("Song Added Successfully")
}
else if (data.status === 4) {
HideAjaxLoader(), ShowMsg("you cannot add your own songs");
}
else if (data.status === 3) {
HideAjaxLoader(), ShowMsg("Cannot add the song. The song was most likely modified or Deleted, we advise you to refresh the page");
}
else if (data.status === 2) {
HideAjaxLoader(), ShowMsg("You cannot add the same song twice");
}
},
error: function () { HideAjaxLoader(), ShowMsg("Song could not be added, please try again") }
});
});
controller's action code that accepts two parameters from my request:
[HttpPost]
public ActionResult AddPointAndCopyTopTenFavToPlaylist(int id, int genre)
{
var song = repository.GetTopTenFav(id);
if (song != null)
{
if (!(song.UserName.ToLower() == User.Identity.Name.ToLower()))
{
foreach (var item in song.Points)
{
if (User.Identity.Name.ToLower() == item.UsernameGavePoint.ToLower())
{
return Json(new { status = 2 }, JsonRequestBehavior.AllowGet);
}
}
var newSong = new Song();
newSong.UserName = User.Identity.Name;
newSong.Title = song.Title;
newSong.YoutubeLink = song.YoutubeLink;
newSong.GenreId = genre;
newSong.Date = DateTime.Now;
repository.AddSong(newSong);
var point = new Point();
point.UsernameGotPoint = song.UserName;
point.UsernameGavePoint = User.Identity.Name;
point.Date = DateTime.Now;
point.Score = 1;
point.TopTenFavId = id;
repository.AddPoint(point);
repository.Save();
return Json(new { status = 1 }, JsonRequestBehavior.AllowGet);
}
else
{
return Json(new { status = 4 }, JsonRequestBehavior.AllowGet);
}
}
else
{
return Json(new { status = 3 }, JsonRequestBehavior.AllowGet);
}
}
I have also registered my new route:
routes.MapRoute(
"AddPoint", // Route name
"{controller}/{action}/{songId},{genreId}", // URL with parameters
new { controller = "Home", action = "", songId = UrlParameter.Optional, genreId = UrlParameter.Optional } // Parameter defaults
);

Resources