MVC3 Ajax.ActionLink - asp.net-mvc-3

For the following:
#Ajax.ActionLink("Delete", "Delete", "AdminGroup", new { id = item.AdminGroupId }, new AjaxOptions { Confirm = "Delete?", HttpMethod = "Delete", OnSuccess = "function() { $(this).parent().parent().remove() }" })
OnSuccess get's errored out. please help.
thanks

It should be like this:
#Ajax.ActionLink(
"Delete",
"Delete",
"AdminGroup",
new { id = item.AdminGroupId },
new AjaxOptions {
Confirm = "Delete?",
HttpMethod = "Delete",
OnSuccess = "handleSuccess"
}
)
where you have:
<script type="text/javascript">
function handleSuccess() {
// TODO: handle the success
// be careful because $(this) won't be
// what you think it is in this callback.
}
</script>
Here's an alternative solution I would recommend you:
#Html.ActionLink(
"Delete",
"Delete",
"AdminGroup",
new { id = item.AdminGroupId },
new { id = "delete" }
)
and then in a separate javascript file AJAXify the link:
$(function() {
$('#delete').click(function() {
if (confirm('Delete?')) {
var $link = $(this);
$.ajax({
url: this.href,
type: 'DELETE',
success: function(result) {
$link.parent().parent().remove();
}
});
}
return false;
});
});

Related

what is the alternative of using url.action in ajax

E.g.
#url.Action("Actionname", "ControllerName", new { id=#item.id, #class="test"})
I want such a thing in Ajax, like this:
#Ajax.action("Actionname", "ControllerName",new { id=#item.id, #class="test"})
I tried this, but it did not benefit me:
#Ajax.ActionLink(".", "DeleteCountry", "Main", new AjaxOptions { HttpMethod = "Post", InsertionMode = InsertionMode.Replace, UpdateTargetId = "Details" }, new { CountryID = item.CountryID , #class="fa fa-times"}) #Ajax.ActionLink(".", "EditCountry", "Main", new AjaxOptions { HttpMethod = "POST", InsertionMode = InsertionMode.Replace, UpdateTargetId = "Details" }, new {CountryID=item.CountryID,#class="fa fa-pencil"})
Can anyone assist me with this?
In asp.net mvc I use both Ajax.BeginForm
#Ajax.BeginForm("Action", "Controller", new AjaxOptions { HttpMethod = "POST", OnSuccess = "successFunction", ... })
{
#Html.HiddenFor(item => item.id)
//etc fields you want to send
}
and JQuery ajax
$.ajax({
url: '#Url.Action("Action", "Controller")',
type: "GET",
data: { 'id': '#item.id' },
success: ...
});
Think it will help you.

$.ajax within jquery plugin not updating variable

Fiddle: http://jsfiddle.net/gpTpK/
The issue I am having is that the title variable is not updated/changed when the $.ajax is executed, I know that the ajax call is working as I have tried replacing the line
title = $(xml).find("title").text();
with
console.log($(xml).find("title").text());
and sure enough it does return the title however when using the orginal line the variable title doesn't change
I have tried and it does work putting the ajax call outside (function($){})(jQuery);
(function($) {
$.fn.getPost = function(options) {
var $this = $(this);
var defaults = {
method: "html",
blogID: "",
postID: "",
done: null
};
var options = $.extend(defaults, options);
var title;
$.ajax({
type: "GET",
url: "http://www.blogger.com/feeds/724793682641096478/posts/default/3551136550258768001",
dataType: "xml",
dataType: 'jsonp',
success: function(xml) {
title = $(xml).find("title").text();
}
});
return $this.each(function() {
if (options.done) {
options.done.call(undefined, title);
}
});
};
})(jQuery);
I have tried the below and i have also tried wrapping the ajax in a function such as getTitle(){ajax code here with return title;}
(function($) {
$.fn.getPost = function(options) {
var $this = $(this);
var defaults = {
method: "html",
blogID: "",
postID: "",
done: null
};
var options = $.extend(defaults, options);
var title;
getAjax();
return $this.each(function() {
if (options.done) {
options.done.call(undefined, title);
}
});
function getAjax() {
$.ajax({
type: "GET",
url: "http://www.blogger.com/feeds/724793682641096478/posts/default/3551136550258768001",
dataType: "xml",
dataType: 'jsonp',
async: false,
success: function(xml) {
title = $(xml).find("title").text();
}
});
}
};
})(jQuery);
sorry, I have spent ages trying to figure it (I didn't ask out of laziness :P), regardless here's the solution for those interested :)
(function($) {
$.fn.getPost = function(options) {
var $this = $(this);
var defaults = {
method: "html",
done: null
};
var options = $.extend(defaults, options);
var title;
var sorf;
$.ajax({
type: "GET",
url: "http://www.blogger.com/feeds/724793682641096478/posts/default/3551136550258768001",
dataType: "xml",
dataType: 'jsonp',
success: function(xml) {
title = $(xml).find("title").text();
sorf = 1;
},
error: function(){
sorf = 0;
},
complete: function() {
returnvals(sorf);
}
});
function returnvals(sorf) {
if(sorf){
//success
return $this.each(function() {
if (options.done) {
options.done.call(undefined, title);
}
});
}else{// failure}
}
};
})(jQuery);

How to post various custom data types using Ajax in MVC3?

I have this ViewModel to represent each Category and it's several Sub-Categories in my project:
public class Categories
{
//a simple string for the category name
[Required]
public string Cat_Name { get; set; }
//a list of strings for the sub-categories
public List<string> SubCat_Name { get; set; }
}
I pass this model to the view, and I use it to construct my form like this:
#using (Html.BeginForm("Category", "Admin", FormMethod.Post))
{
#Html.TextBoxFor(m => m.Name, new { #class = "Cat" })
#Html.TextBoxFor(m => m.SubName, new { #class = "Sub" })
#Html.TextBoxFor(m => m.SubName, new { #class = "Sub" })
#Html.TextBoxFor(m => m.SubName, new { #class = "Sub" })
#Html.TextBoxFor(m => m.SubName, new { #class = "Sub" })
<input type="button" value="Create New Category" name="Category" onclick="DoIt()" />
}
And as you see, the javascript function "DoIt()" is called by the click on the input button.
here's the function :
function DoIt() {
var stringArray = new Array();
//I put all of the sub-categories inside an array, to be like a list<string>
$(".Sub").each(function (index, value) {
stringArray[index] = this.value;
});
$.ajax({
url: '/Admin/Category',
type: "POST",
data: JSON.stringify($(".Cat").attr("value") , stringArray),
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function () { console.log("post done"); },
error: function () { }
});
}
As you can see, in the ajax method I'm trying to pass the "Category Name" $(".Cat").attr("value") and it's "Sub-Category Names" stringArray to the corresponding action method which requires Categories datatype I created as a viewmodel before. It looks like this:
public ActionResult Category(Categories CAT)
{
//Do something
return View();
}
The problem is the ajax method can't post two datatypes at once, or just that I don't know how to do it.
I also tried this :
var postdata = {
Name: $(".Cat").attr("value"),
SubName: stringArray
};
and put postdata inside the JSON.stringify() instead. But still nothing is passed to the action method.
I think you are very close.
Try this
var postdata = {
Cat_Name: $(".Cat").val(),
SubCat_Name: stringArray
};
&
$.ajax({
url: '/Admin/Category',
type: "POST",
data: JSON.stringify(CAT:postdata),
dataType: "json",
contentType: "application/json",
success: function () { console.log("post done"); },
error: function () { }
});
Try to send data formatted like this:
$.ajax({
url: '/Admin/Category',
type: "POST",
data: JSON.stringify({ Cat_Name: $(".Cat").val(), SubCat_Name: stringArray }),
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function () { console.log("post done"); },
error: function () { }
});

Jquery dialog & Ajax posting wrong(?) result in ASP.NET MVC3 (razor)

What i want to do:
at page load to automatically pop up a jquery dialog fill in some data, post that to an action and close the dialog (regardless if the action succeeds or not).
in the View in which the pop up should occur i have the following:
<script type="text/javascript">
$(function () {
$('#PopUpDialog').dialog(
{
modal: true,
open: function ()
{
$(this).load('#Url.Action("Subscription", "PopUp")');
},
closeOnEscape: false
}
);
$('.ui-dialog-titlebar').hide();
$('#closeId').live('click',function () {
$('#PopUpDialog').dialog('close');
return false;
}
);
$('#SubscriptionForm').submit(function () {
$("#PopUpDialog").dialog("close");
$.ajax({
url: encodeURI('#Url.Action("Subscription", "PopUp")' ),
type: this.method,
data: $(this).serialize()
})
return fase;
}
);
});
</script>
the Subscription view has the following:
#using (Html.BeginForm( new { id = "SubscriptionForm" }))
{
#Html.ActionLink(Deals.Views.PopUp.SubscriptionResources.AlreadySubscribed, "", null, new { id = "closeId" })
<br />
<br />
#Deals.Views.PopUp.SubscriptionResources.FillEmail
#Html.TextBoxFor(m => Model.Email)
<input type="submit" id="subscribeId" value="#Deals.Views.PopUp.SubscriptionResources.IWantToSubscribe" />
<br />
}
which works fine.
The POST action is defined as follows:
[AcceptVerbs(HttpVerbs.Post)]
public JsonResult Subscription(FormCollection formValues)
//public void Subscription(FormCollection formValues)
{
Deals.ViewModels.PopUpSubscriptionVM VM = new ViewModels.PopUpSubscriptionVM();
TryUpdateModel(VM);
if (!String.IsNullOrEmpty(VM.Email))
{
//do the update to the dbms
}
return Json(new { success = true });
}
The problem is that after posting back i get an empty screen with the success message, which i don't want!
What am i doing wrong?
You can handle the success and error callbacks:
$('#SubscriptionForm').submit(function () {
$("#PopUpDialog").dialog("close");
$.ajax({
url: encodeURI('#Url.Action("Subscription", "PopUp")' ),
type: this.method,
data: $(this).serialize(),
success: function (result) {
//Do Whatever you want to do here
},
error: function (x, e) {
//Do Whatever you want to do here
}
})
return fase;
}
To see what i am doing wrong i set up a small project (ASP.NET MVC 3) with the following ingredients:
<script type="text/javascript">
$(function () {
// Does not cache the ajax requests to the controller e.g. IE7/9 is doing that...
$.ajaxSetup({ cache: false });
var $loading = $('<img src="#Url.Content("~/images/ajax-Loader.gif")" alt="loading" class="ui-loading-icon">');
var $url = '#Url.Action("Subscription", "PopUp")';
var $title = 'Some title';
var $dialog = $('<div></div>');
$dialog.empty();
$dialog
.append($loading)
.load($url)
.dialog({
autoOpen: false
, closeOnEscape: false
, title: $title
, width: 500
, modal: true
, minHeight: 200
, show: 'fade'
, hide: 'fade'
});
$dialog.dialog("option", "buttons", {
"Cancel": function () {
$(this).dialog("close");
$(this).empty();
},
"Submit": function () {
var dlg = $(this);
$.ajax({
url: $url,
type: 'POST',
data: $("#SubscriptionForm").serialize(),
success: function (response) {
//$(target).html(response);
dlg.dialog('close');
dlg.empty();
});
}
});
$dialog.dialog('open');
})
</script>
The controllers' actions:
public ActionResult Subscription()
{
Thread.Sleep(2000); //just for testing
TestModalAjax.ViewModels.PopUpVM VM = new ViewModels.PopUpVM();
return View(VM);
}
//POST
[AcceptVerbs(HttpVerbs.Post)]
//[OutputCache(CacheProfile = "ZeroCacheProfile")]
public ActionResult Subscription(FormCollection formValues)
{
TestModalAjax.ViewModels.PopUpVM VM = new ViewModels.PopUpVM();
TryUpdateModel(VM);
return Json(new { success = true });
}
...and the according View:
#model TestModalAjax.ViewModels.PopUpVM
#{
Layout = null;
ViewBag.Title = "Subscription";
}
<h2>Subscription</h2>
#* ----- NOTICE THE FOLLOWING!!! WITHOUT THIS DATA GETS NOT POSTED BACK!!!! ---- *#
#using (Html.BeginForm("Subscription","PopUp",FormMethod.Post, new { id="SubscriptionForm"}))
{
<h1> Give me your name</h1>
#Html.TextBoxFor(M => Model.Name)
}
...so it seems everything works as expected!

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

Resources