Pass two parameters to controller, syntax error - asp.net-mvc

I have a dropdown list. I want to click any item then redirect the view by parameters.
$(document).ready(function () {
$("#Languages").change(function () {
var selectedValue = $(this).find('option:selected').val();
window.location.href = "/Survey/SelectLanguage/" + selectedValue+"/id/"+#Model.CampaignGuid;
});
});
The action method in controller is:
public ActionResult SelectLanguage(string languageName, Guid id)
{
}
But I found in chrome debugger, there is an error.
Uncaught SyntaxError: Invalid or unexpected token
If I comment it out the code window.location.href = "/Survey/SelectLanguage/" + selectedValue+"/id/"+#Model.CampaignGuid;.
Then the error is gone. So what is wrong?

Change
window.location.href = "/Survey/SelectLanguage/" +
selectedValue + "/id/" + #Model.CampaignGuid;
to
window.location.href = "/Survey/SelectLanguage/" +
selectedValue + "/id/#Model.CampaignGuid";
If CampaignGuid is really a Guid, then you're writing out "/id/" + d0164584-bac0-485b-8a84-b7923caa6ee7 to your html, and Chrome's javascript engine doesn't know what d0164584-bac0-485b-8a84-b7923caa6ee7 is, it needs to be a string.

Well, since you do not have the url defined and you are using the default route, the default is based on query string. Try this:
$(document).ready(function () {
$("#Languages").change(function () {
var selectedValue = $(this).find('option:selected').val();
window.location.href = "/Survey/SelectLanguage/#Model.CampaignGuid?languageName=" + selectedValue;
});
});
By following the default route of asp.net mvc, you can pass an argument named id on the url as part of it, then you can use CampingGuid as id, and languageName you can use query string.

Try to define your url as
"/Survey/SelectLanguage?selectedValue=" + selectedValue + "&id=#Model.CampaignGuid"

Related

ASP.NET MVC pass parameters to controller that returns File?

In a situation when you do not need to pass any parameters below example works fine:
Controller without parameters:
[Authorize]
public ActionResult GetExcelTable()
{
XlWorkBook table = new XlWorkBook();
MemoryStream stream = new MemoryStream();
table.SaveAs(stream);
return File(stream, MyLib.MIMETypes.GetFileMIMEType(".xlsx"), "Kr-ti-" + Year + "-" + Month.ToString() + "_" + DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss") + ".xlsx");
}
Client:
Get excel
But what if I want to pass some parameters to the controller and download the file? Is there anyway to simulate the click on a tag from jquery and pass the parameters along. I know that you can not get the file with jquery ajax call.
Month and Year parameters are on the client side dynamic values that user specifies them in the dropdown list. I have to read this values before the controller is called and pass them to controller.
Controller with parameters:
[Authorize]
public ActionResult GetExcelTable(int Month, int Year)
{
XlWorkBook table = new XlWorkBook(Month, Year);
MemoryStream stream = new MemoryStream();
table.SaveAs(stream);
return File(stream, MyLib.MIMETypes.GetFileMIMEType(".xlsx"), "Kr-ti-" + Year + "-" + Month.ToString() + "_" + DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss") + ".xlsx");
}
You can do it easily with one of overloads #Url.Action that have routeValues:
Get excel
If you want to pass them dynamicaly you should use Js, with Jquery it will be:
<a id="get-excel">Get excel</a>
<script>
$(document).ready(function () {
$(a#get-excel).click(function(){
var month = $(select#monthdd).val();
var year = $(select#yeardd).val();
window.location.href = '#Url.Action("GetExcelTable", "Home")?Month='+ month +'&Year=' + year;
});
});
<script/>

Custom ValidationAttribute trigger on different client property change

I have built a custom validation attribute - LessThanDifference. Basically I give it two properties, and it checks to see if the value of the validated field is less than the difference of the two property names. Basically "is FieldC < (FieldA - FieldB)". That part works.
The IsValid function works fine, here is my client validation rules. (Bonus question - Is there any way to get the display name for firstoperand and secondoperand? It has the property name by attribute parameter.)
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ValidationType = "lessthandifference",
ErrorMessage = FormatErrorMessage(metadata.GetDisplayName())
};
rule.ValidationParameters.Add("firstoperand", FirstOperand);
rule.ValidationParameters.Add("secondoperand", SecondOperand);
yield return rule;
}
Where I'm totally lost is how to trigger the validation If A(firstoperand) or B(secondoperand) changes.
$.validator.addMethod(
'lessthandifference',
function (value, element, params) {
var firstVal = $('#' + params.firstoperand).val();
var secondVal = $('#' + params.secondoperand).val();
return (value <= (firstVal - secondVal));
});
$.validator.unobtrusive.adapters.add(
'lessthandifference', ['firstoperand', 'secondoperand'], function (options) {
var params = {
firstoperand: options.params.firstoperand,
secondoperand: options.params.secondoperand
};
options.rules['lessthandifference'] = params;
options.messages['lessthandifference'] = options.message;
//Set up Trigger?
});
I've tried to pass something like (#' + options.params.secondoperand) into another method, but have been unable to get the prop name for the base attribute (FieldC).
$().change seems like it would be the way to go if I could get it set right.
Thoughts?
I solved the main issue:
function addSecondaryValidatorCheck(mainElement, secondaryElement) {
$(secondaryElement).change(function () {
if ($(mainElement).val() > 0)
$(mainElement).valid();
});
And Implementation from the $.validator.unobtrusive.adapters.add function
addSecondaryValidatorCheck('#' + options.element.id, '#' + options.params.compareAttribute);
Still looking for a good way to pass the display name.

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

Unexpected href generated by Html.ActionLink

I have this Html.ActionLink in my code:
#Html.ActionLink("Up",
"GetCategory",
"Category",
new { C_ID = CID, D_ID = DID, E_ID = EID, F_ID = FID },
new { id = "item-" + ItemID + "-getcategories-" + ItemLevel,
#class = "getCategory" })
I want to append a Javascript variable's value to the route dictionary. For this, I used the solution specified in this SO question ASP.NET MVC 2 Html.ActionLink with JavaScript variable
I attempted to customise the answer and this is what I have:
$(function ()
{
$('a.getCategory').click(function ()
{
.
.
.
var CatID = 0; //Calculate from this.ID
this.href = this.href + '?Cat_ID=' + CatID;
});
});
Thing is, the value of this.href is not the value generated by Html.ActionLink. Rather, it is the current URL of the page.
My understanding was this.href should refer to the ActionLink's href (since this refers to the anchor element generated by the ActionLink). What am I doing wrong?
EDIT
What is even more confusing: The Html.ActionLink is for one of the tabs (I'm using Jquery UI Tabs). So if I use .attr('href') to read the value in the JS function, I get a completely different value:
var AnchorHref = $(this).attr('href');
The value of AnchorHref is #ui-tabs-XX (where XX is a number) - this is a div auto-generated by Jquery UI tabs.

Can I pass a parameter with the OnSuccess event in a Ajax.ActionLink

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)
}

Resources