Can I pass a parameter with the OnSuccess event in a Ajax.ActionLink - asp.net-mvc

When I use:
new AjaxOptions
{
UpdateTargetId = "VoteCount" + indx,
OnSuccess = "AnimateVoteMessage"
}
everything works fine...but I am trying to animate items in a list, with automatically assigned ID's. Since I want each of these to be addressable from my javascript, I believe I need to pass a parameter to my javascript. But when I use:
new AjaxOptions
{
UpdateTargetId = "VoteCount" + indx,
OnSuccess = "AnimateVoteMessage(2)"
}
I get an " Sys.ArgumentUndefinedException: Value cannot be undefined." exception. Well I get that when using the debug versions of MicrosoftMvcAjax.js. When using the compressed version I get a "Microsoft JScript runtime error: 'b' is null or not an object"
So my question is, can I pass a parameter to my javascript function using the OnSuccess event for a ActionLink?
Is this the right approach? How else am I going to have one javascript function have the ability to be run on 10 items (in my case the IDs of multiple DIVs) on my page?

There is a better way to do this - use the built in parameters that the OnSuccess call can be expected to pass
the built in parameters (the ones I found so far anyway) are data, status and xhr
data = whatever you return from the action method
status = if successful this status is just a string that says "success"
xhr = object that points to a bunch of javascript stuff that I will not be discussing...
so you would define your javascript like this (you can leave out the arguments you don't need - since all we want is our data back from the action we will just take the data argument)
function myOnSuccessFunction (data)
{
..do stuff here with the passed in data...
}
like I said before, data is whatever JSON that may be returned by the ActionResult so if your controller action method looks like this...
public ActionResult MyServerAction(Guid modelId)
{
MyModel mod = new MyModel(modelId);
mod.DoStuff();
return Json(mod, JsonRequestBehavior.AllowGet);
}
you would set up your action link like this...
#Ajax.ActionLink("Do Stuff", "MyServerAction", new { modelId = Model.Id }, new AjaxOptions { OnSuccess = "mySuccessScript(data);", OnFailure = "myFailureScript();", Confirm = "Are you sure you want to do stuff on the server?" })
this will create a confirmation message box asking if you want to actually invoke the action - clicking yes on the prompt will invoke the call to the controller - when the call comes back - the data argument will contain a JSON object of whatever you returned in your action method. Easy Peasy!
But wait! What if I want to pass another custom argument?! Simple! Just add your arguments to the front of the list...
instead of this...
function myOnSuccessFunction (data)
{
..do stuff here with the passed in data...
}
do this (you can have more than one custom argument if you like, just keep adding them as needed)...
function myOnSuccessFunction (myCustomArg, data)
{
..do stuff here with the passed in data and custom args...
}
then in your setup - just get the argument through some client side script within your ActionLink definition... i.e.
#Ajax.ActionLink("DoStuff", "MyServerAction", new { modelId = Model.Id }, new AjaxOptions { OnSuccess = "mySuccessScript(myClientSideArg, data);", OnFailure = "myFailureScript();", Confirm = "Are you sure you want to do stuff on the server?" })
Note that "myClientSideArg" in the OnSuccess parameter can come from wherever you need it to - just replace this text with what you need.
Hope That Helps!

or...a bit different syntax that worked for me:
OnSuccess = "( function() { MyFunction(arg1,arg2); } )"

There is a better way, which I believe is how Microsoft intended it: Set the AjaxOptions.OnSuccess to a function pointer, i.e. just the name of the function, no parameters. MVC will send it parameters automagically. Below is an example.
JScript parameter:
public class ObjectForJScript
{
List<int> Ids { get; set; }
}
Jscript function:
function onFormSuccess(foobar){
alert(foobar);
alert(foobar.Ids);
alert(foobar.Ids[0]);
}
View code:
#using (Ajax.BeginForm("ControllerAction", "ControllerName",
new AjaxOptions
{
OnSuccess = "onFormSuccess" //see, just the name of our function
}))
{
#Html.Hidden("test", 2)
}
Controller code:
public JsonResult ControllerAction(int test)
{
var returnObject = new ObjectForJScript
{
Ids = new List<int>{test}
};
return Json(returnObject);
}
Note that the parameter name in the JScript function doesn't matter, you don't have to call it "returnObject" even though the controller names it so.
Also note that Json() conveniently turns our List into a JScript array. As long as the methods of the C# object are translatable to Json, you can call them in the JScript like I've done.
Finally, the controller doesn't have to return a JsonResult, it can be ActionResult (but it's usually better to have a controller action do just one thing).
The above example will alert two objects (the Json and the array object which it contains), and then 2.

You can simply do this
Razor:
... OnSuccess = "AnimateVoteMessage('" + YourParameter + "')"
Please note the single quotes!
JavaScript:
function AnimateVoteMessage(YourParameter){
alert(YourParameter);
}
Enjoy,

Try this - it works for me:
OnSuccess = "new Function('MyFunction(" + myParameter + ")')"

Use this:
OnSuccess = "function(){yourfunction(" + productcode + ");}"
or
OnSuccess = "function(){yourfunction(this, " + productcode + ");}"

I ran in this issue too... and did not find a way to solve it!
I did a workaround (which is not nice but solved it for now... maybe until someone posts a solution here)...
what I did was place a hidden field in the TargetId div and OnSuccess I called a js method which retrieves the value from the hidden field <- this could happen in your AnimateVoteMessage method ...

See http://www.codeproject.com/KB/ajax/Parameters-OnSuccess.aspx
Basically:
function yourCallBack(arg1,arg2) {
return function(result) { // Your old function
alert(arg1); // param will be accessible here
alert(arg2); // param will be accessible here
alert(result);// result = the response returned from Ajax
}
}

Simply, at AjaxOptions, use the following:
OnSuccess = "onSuccessFunction(data, 'Arg1');"
Then at your function, you will get the new value as:
function onSuccessFunction(result, myNewArg) {
//Prints Arg1
Console.Write(myNewArg)
}

Related

Calling controller method with a get type not working in ASP.NET MVC

I have a java script function that calling a controller method using Ajax, this call should get me the user profile page, I have a controller for this purpose. When I run the program and fire the java script function it's trigger the controller and every thing is good but when the debugging has ended no changes happens and the view doesn't present in the screen.
I tracked the call and every thing is working fine, passing parameter and reaching the method in the controller.
Note: the view which has the JS call related to a different controller.
View contain java script call:
<td onclick="ViewProfile('#item.CustomerId')"></td>
Java script file
function ViewProfile(id) {
console.log("sucsses");
$.ajax({
type:"GET",
url: "/ViewUserProfile/Index",
data: { "userId": id }
});
};
Controller: ViewUserProfileController
public ActionResult Index(string userId)
{
var ProfileInformation = new UserProfileVM
{
//some logic here
};
return View(ProfileInformation);
}
You are fetching ViewUserProfile in $.ajax but you are not using .done(function() { }) to process the result you receive from that call.
In your case I would simply suggest to use window.location.href in ViewUserProfile() as below.
function ViewProfile(id) {
window.location.href = "/ViewUserProfile/Index?userId=" + id;
}

How to check Unique attribute in mvc 3?

I have a textbox for username in a form, when user enter the username, i need to check if that username is already in data base. I'm thinking to catch the blur event of the text box & to write a javascript function to query & check in database. I'm trying some thing like this:
#html.textboxfor(x=>x.UserName, new{#id="UserName"})
<script type="text/javascript">
$(document).ready(function(){$('#UserName').blur("then some code here");})
</script>
Now I need to know if I'm following the right way? If so then please let me know how can I call a action method which will interact with the database within the blur function or whats the right way? Thanks in advance.
Yes, that looks right. You can use a JQuery Ajax call, along with the Url.Action helper method.
$(document).ready(function(){
$('#UserName').blur(function() {
var name = this.value;
$.get(#Url.Action("VerifyUsername") + "?name=" + value, function(result) {
if (result.ok == false) {
$("#message").text("Username '" + name + "' is already taken, please try another");
}
});
});
});
This will call an action VerifyUsername in the current controller. It assumes that the action returns JSON like {ok:true} to verify the name:
public ActionResult VerifyUsername(string name)
{
bool isOk;
// check the database
return new JsonResult() {
Data = new { ok: isOk },
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
you can use remote validation in MVC3
http://msdn.microsoft.com/en-us/library/gg508808(v=vs.98).aspx

Html ActionLink not posting to action method

I am trying to submit to a controller action method by using Html.ActionLink in my view. I am doing this as non-ajax submit because the return type of my action is FileContentResult (thanks to #Darin for this info). However, my action link is not posting my view to Action Method. Below is my code
View's Code (Partial view)
#Html.ActionLink("Save", "SaveFile", "ui", new { htmlResult="asdf"})
Here, UI is controller name, SaveFile is method name.
Controller method
public FileContentResult SaveFile(string htmlString)
{
...
...
pdfBytes = pdfConverter.GetPdfBytesFromHtmlString(html);
var cd = new ContentDisposition
{
FileName = "MyFile.pdf",
Inline = false
};
Response.AddHeader("Content-Disposition", cd.ToString());
return File(pdfBytes, "application/pdf");
}
When I hit the same URL from browser address bar, then it is hit and also returns the pdf file with no issues. Same this is not happening through action link. I also tried putting the action link inside #using Html.BeginForm().... but no use.
Can you please tell me where I might be doing wrong here?
Thanks!
Html.ActionLink has a lots of overloads and it's very easy to use the wrong one. You are currently using the (String, String, Object, Object) overload which treats your third argument "ui" this route values which leads to a wrongly generated link.
Use this overload instead:
#Html.ActionLink("Save", //Link text
"SaveFile", // Action Name
"ui", // Controller name
new { htmlResult="asdf"}, //Route values
null /* html attributes */)

Json isn't returning a result that is accessible as an array

I'm having troubles reading a Json result back from a controller method...
I have this method in my controller:
[AcceptVerbs(HttpVerbs.Post)]
public JsonResult GetCurrent()
{
IList<string> profile = new List<string>();
profile.Add("-1");
profile.Add("Test");
profile.Add("");
return this.Json(profile);
}
And it is being called by this jquery ajax post:
$.post("/Profile/GetCurrent", function(profile) { profileCompleteOpen(profile); }, "json");
and the javascript function called on the post's callback:
function profileCompleteOpen(profile) {
alert(profile);
alert(profile[0]);
}
The result of the first alert shows the array like this:
["-1","Test",""]
But the result of the second alert shows this:
[
rather than
-1
What am I doing wrong here... I've compared it to one of the other times I'm doing this and it seems to be the exact same. Why isn't it recognizing it's an array?
Thanks,
Matt
Try converting the json data in profile to a proper object by using eval() on it.
Example:
var profileObject = eval('(' + profile + ')');
Hmmm, I'd be doing what you're trying to do a little differently.
I'd either return a fully qualified object and then use it's properties;
class MyObj
{
public string name{get;set;}
}
fill the object and return it as a json object. then you're jquery code can access like any other object.
The other way might be to do a return PartialView("MyView", model);
That will return the partial view as html back to your page which you can then append to your html.
I think the type of profile is string instead of array. Why? Check the $.post method parameters. Maybe the problem is there.
$.post("url", null, function(profile) { ... }, "json");

MVC ActionMethod not finding passed in Value

I have a Create ActionMethod, something along the lines of:
[AcceptVerbs(HttpVerbs.Post)]
public ActionMethod Create(Journey journey)
{
if (Request.IsAjaxRequest())
{
//Save values
return Json(new { JourneyID = journey.JourneyID } );
}
}
The Journey object that I pass in is from my LINQ2SQL datamodel. I call the above ActionMethod from my Javascript using the JQuery.Post function, like:
var journeyData = {
CustomerID: $('#CustomerID').val(),
JourneyID: $('#JourneyID').val(),
EstimatedTravelTime: $('#EstimatedTravelTime').val(),
RouteName: $('#RouteName').val(),
.....
};
$.post('/Journey/Create',
journeyData,
function(jsonResult) {
//deal with result
},
'json'
);
The issue that I am having is that in the ActionMethod Journey.RouteName is always returning as null but the JSON that I pass back has a value, I check this using
alert(JSON.stringify(journeyData));
and in the resultant JSON object RouteName has a value, e.g. 'Go to work'. Any ideas why this wouldn't be being set in the ActionMethod? All other values that I pass back are being set fine.
Just a try and error suggestion:
First thing i would try is to rename "RouteName" param with somethign different, as "RouteName" is also a property of some MVC-redirect methods..
Have you examined your request JSON object that's going to the server?
Have you tried adding quotes to your string property value?
Like this:
var journeyData = {
CustomerID: $('#CustomerID').val(),
JourneyID: $('#JourneyID').val(),
EstimatedTravelTime: $('#EstimatedTravelTime').val(),
RouteName: '"' + $('#RouteName').val() + '"',
.....
};
There are a couple of things to consider. I'm guessing this is already in place, but your model must have a getter and setter on the RouteName property in order to be properly bound. Another thought is you might not be establishing the strong binding. This is usually done as part of the view's page declaration (e.g. Inherits="System.Web.Mvc.ViewPage") but I'm not sure this is happening prior to your post.

Resources