ActionLink in jQuery - c#

This is my method:
$(document).ready(function () {
$('td.clickableCell').click(function () {
var currentObject = null;
currentObject = $(this).text();
#Html.ActionLink("GetThis", "Get", new {theName = currentObject} )
});
});
but it says that currentObject doesn't exist in the current context. How to resolve this?

Instead of #Html.ActionLink you should use the jQuery.get function. `#Html.ActionLink is run on the server whereas the javascript is run on the client.
$(document).ready(function () {
$('td.clickableCell').click(function () {
var currentObject = $(this).text();
$.get('#Url.Action("GetThis", "Get")', {theName : currentObject});
});
});
The Url.Action is rendered on the server and will give you the appropriate url. The $.get will run a get request on the client.
Keep in mind, if this javascript is in a .js file, the Url.Action will not be run. In that case you may simply want to replace it with /Get/GetThis or render the url in a hidden field on the page and get the value of the hidden field in your .js file.
You need an action method that looks like this in order to access the parameter:
public ActionResult GetThis(string theName)
{
// manipulate theName
return View();
}

currentObject is a JavaScript String object that you are trying to pass into server side code. If you need to do this on the client side,
$(function () {
$('td.clickableCell').click(function () {
var currentObject = $(this).text();
// find the anchor element that you need to change,
// then change the property on it to the value
// of currentObject
$('a').attr('title', currentObject);
});
});
Alternatively, it's possible that you need to send the value to the server in some way. If the JavaScript above is within a Razor view, then
$(function () {
$('td.clickableCell').click(function () {
var currentObject = $(this).text();
// make a HTTP GET request and pass currentObject as a queryparam
window.location = '#Url.Action("Action", "Controller")' + '?theName=' + encodeURIComponent(currentObject);
});
});
The '#Url.Action("Action", "Controller")' portion will have been evaluated on the server-side and been resolved by the UrlHelper to the URL to route to that controller action. We put this value in single quotes as we need to use it on the client side in a JavaScript variable. Then we add currentObject as a query parameter (and encode it at the same time).

You're mixing client-side code with server-side code. This line is being executed on the server before anything is sent to the client:
#Html.ActionLink("GetThis", "Get", new {theName = currentObject} )
That line, by itself, references something which doesn't exist. currentObject won't exist until it's created in JavaScript on the client. That JavaScript code, from the perspective of the server, is nothing more than text.

Related

How to pass jQuery variable value to c# mvc?

How to pass jQuery variable value to c# mvc ?
I need to fetch the value of the variable btn in mvc code behind.
$('button').click(function () {
var btn = $(this).attr('id');
alert(btn);
$.ajax({
type: 'GET',
url: '#Url.Action("ActionName", "ControllerName")',
data: { id: btn },
success: function (result) {
// do something
}
});
});
Based on the variable value (Submit Button (or) Preview Button), my model will have Required validation on certain fields.
In my controller , i am calling as
[HttpGet]
public ActionResult ActionName(string id)
{
var vm = id;
return View(vm);
}
Though , ActionResult in controller is not invoked.
Jquery : alert(btn); -- is calling. I can see the alert window showing with the id. However, I am not able to retrieve the id in the controller.
You need to use jQuery.ajax() (or its shortened form jQuery.get()/jQuery.post()) with GET/POST method and set up a controller action with an argument to pass button ID:
jQuery (inside $(document).ready())
$('button').click(function () {
var btn = $(this).attr('id');
var url = '#Url.Action("ActionName", "ControllerName")';
var data = { id: btn };
// if controller method marked as POST, you need to use '$.post()'
$.get(url, data, function (result) {
// do something
if (result.status == "success") {
window.location = '#Url.Action("AnotherAction", "AnotherController")';
}
});
});
Controller action
[HttpGet]
public ActionResult ActionName(string id)
{
// do something
return Json(new { status = "success", buttonID = id }, JsonRequestBehavior.AllowGet);
}
[HttpGet]
public ActionResult AnotherAction()
{
// do something
return View(model);
}
If you want to pass retrieved button ID from AJAX into other action method, you can utilize TempData or Session to do that.
It is a nice coincidence that you use the word "fetch" to describe what you want to do.
jQuery runs in the browser as a frontend framework. Meaning that it runs on the client`s computer. Your MVC-C#-Code lies on the server. Therefore, if you want to send data between those two computers, you need to use the http protocol.
1. Ajax and REST:
Using an ajax call using http methods (post or put) to push your variable value as JSON to the backend`s REST api (route).
For this option, you might want to have a look at the fetch function of javascript.
2. HTML Forms
Use a html form where you store the variable value inside one input element. A form submission will perform a http post (by default) request to the backend as well and use all input element values as post parameters.
There are many ways to accomplish what you are looking to do, but I'll stick to using your code sample.
So what you need to do is utilize the .ajax call in jquery to send data from your view to your controller. More on that here: http://api.jquery.com/jquery.ajax/
Using your code, you'd put the .ajax call within your logic flow of what to do based on which button is clicked.
$("button").click(function ()
{
var btn = this.id;
if (btn == "previewButton")
{
$.ajax({
url: "/MyApp/MyAction",
type: "POST",
data: { btnId: btn },
dataType: "json",
async: true,
cache: false
}).success(function(data){
// do something here to validate if your handling worked
}).error(function(){
// Do something here if it doesnt work
});
}
}
You'll see that there is a URL. In my example i've chose MyApp as my controller and MyAction as the method of the controller in which we are posting values to. The ajax call posts 1 parameter with a property of btnId. If you need to pass more data, the property name in the jquery call should correspond with an argument of the actions method signature within the controller.
So my controller looks like
public MyAppController : Controller
{
[HttpPost]
public JsonResult MyAction(string btnId)
{
Debug.WriteLine("btnId: {0}", btnId);
return Json(new{ ButtonId= btnId });
}
}
This would be one way to handle passing values from your view to your controller using .ajax calls with jquery.
My preferred way is to use the Html helpers of Ajax.BeginForm which could be another option for you.
https://www.aspsnippets.com/Articles/ASPNet-MVC-AjaxBeginForm-Tutorial-with-example.aspx

absolute path on call ajax mvc4 c#

i have a project in mvc 4 entity framework and call the controller method with ajax.
My problem is when i am using my app local, url is "Controller/Method" but when i publish i have to change url to "http://domain/appName/Controller/Method"
who can i do to get absolute path on ajax url??? my ajax is on js file and i can't use function like html.actionlink
example:
$("#btnAnswer").click(function () {
$.ajax({
url: "http://domain/appName/Controller/method/",
//url: "/Controller/method/",
data: { answer: $("#answer").val(), question_id: $("#question_id").val(), answer_id: $("#answer_id").val() },
success: function (result) {
alert(result);
}
}).error(function () {
}).fail(function () {
});
});
You don't really need the absolute url. Correct relative url is fine.
You should use the Url.Action helper method to generate the correct relative path to your action method. This will generated the proper path irrespective of your current page/view.
url: "#Url.Action("ActionMethodName","YourControllerName")"
Url.Action helper method will work if your javascript code is inside a razor view. But if your code is inside an external js file, you should build the relative url to your app root using Url.Content("~") helper method and pass that to your js code via a variable as explained in this post . Try to use javascript namespacing when doing so to prevent possible conflict/overwriting from other global variables with same name.
EDIT : Including Marko's comment as an alternate solution. Thank you :)
If it is an anchor tag, you can simply use the href attribute value of the clicked link.
Delete
and in your js code
$("a.ajaxLink").click(function(e){
e.preventDefault();
var url = $(this).attr("href");
//use url variable value for the ajax call now.
});
If it is any other type of html element, you can use html5 data attribute to keep the target url and use the jQuery data method to retrieve it in your js code.
<div data-url="#Url.Action("Delete","Product")" class="ajaxLink">Delete</div>
and in your js code
$(".ajaxLink").click(function(e){
e.preventDefault(); // to be safe
var url = $(this).data("url");
//use url variable value for the ajax call now.
});
As you are using this in a js file you can do something like this:
$("#btnAnswer").click(function () {
var hostString = window.location.protocol + "//" + window.location.host + /";
$.ajax({
url: hostString + "/appName/Controller/method/",
//url: "/Controller/method/",
data: { answer: $("#answer").val(), question_id: $("#question_id").val(), answer_id: $("#answer_id").val() },
success: function (result) {
alert(result);
}
}).error(function () {
}).fail(function () {
});
});

Url.Action and two variables

I have #Html.PagedListPager(Model, page => Url.Action("GetTabData", new { page })
and inside my js file I have ready to use myTab variable which I need to send together with page in above example.
How can I do that?
Update:
I'm using js variable to determine which tab is user click and based on that value I'm quering data. Now I have implemeted pagination which uses above generated link. With this in place my ajax call for sending activeTab is broken, I need to send this value together with page inside above Url.Action.
This is js variable which I use to send over ajax to determine which tab is user click
$(function () {
var activeTab = null;
$('#tabs .tabLink').click(function (event) {
var activeTab = $(this).attr('href').split('-')[1];
GetTabData(activeTab);
});
GetTabData(ommitted on purpse)
});
I don't get the question clearly, but I am taking a guess here. Don't know if this is what you are looking for.
Note - You have GetTabData in both your javascript as well as cshtml code, I am hoping this is just coincidence, because the js function cannot be invoked via #Url.Action in this manner.
If you need to send two values as part of your URL, you could do it either in a RESTful way or have querystrings.
Option 1 -
Url.Action("GetTabData", new { page=2, tab="blah" })
Your corresponding controller action would look like
public ActionResult GetTabData(int page, string tab)
{
...
}
Option 2 -
create a querystring and append it to the URL
/GetTabData?page=2&tab=blah
In this case the controller action would look like this
public ActionResult GetTabData()
{
var params = Request.QueryString;
...
}

Set a javascript variable from mvc controller

Is it possible to set a javascript variable from a c# controller? We have a situation where we override our master page with a dumb downed version that doesn't require login for users. However, our javascript timeout timer still runs. I would like to in the controller method that overrides the master, to override the timeout to something huge.
public dumbDownController()
{
ViewData["MasterPageOverride"] = "~/Views/Shared/_NoLogin.cshtml";
//Somehow reset that timer below from 20 to like 9999. To simulate no timeout.
return View("Cities", model);
}
Then our javascript file has.
tb.sessionTimer = (function () {
var SESSION_TIMEOUT = 20;
var currentTimeoutCounter = SESSION_TIMEOUT * 60;
...
lots more irrelevant to question
...
}
Large app, so looking to barely change the javascript. Would like to handle it from the controller.
Short Answer:
<script>
var xyz = #ViewData["MasterPageOverride"];
</script>
Longer Answer:
You can't directly assign JavaScript variables in the Controller, but in the View you can output JavaScript which can do the same.
You need to pass the variable to the View somehow. For this example I'll use the ViewData object dictionary. You can set an element in the Controller:
public ActionResult SomeAction()
{
ViewData["aNumber"] = 24;
}
Then in the View it is possible to use it as:
<script>
var xyz = #ViewData["aNumber"];
</script>
Which will be sent to the client browser as:
<script>
var xyz = 24;
</script>
Strings need a bit more attention, since you need to enclose them between '' or "":
<script>
var xyz = "#ViewData["aString"]";
</script>
And as #Graham mentioned in the comments, if the string happens to be valid JSON (or any object literal, but it is very easy to create JSON), and you want to use it as a JavaScript object, you can:
<script>
var xyz = #ViewData["aJsonString"];
</script>
Just make sure the output is valid JavaScript.
On a footnote, be careful with special HTML characters, like < as they are automatically HTML-encoded to prevent XSS attacks, and since you are outputting JavaScript not HTML, this can mess things up. To prevent this, you can use Html.Raw() like:
<script>
var xyz = #Html.Raw(ViewData["aJsonString"]);
</script>
If tb is within the scope of your controller, consider just overriding the sessionTimer function:
public dumbDownController(){
...
tb.sessionTimer = function(){return false;}
}
You have two options (as I understand):
Create the variable from viewbag, data, tempdata, like so:
var SESSION_TIMEOUT = #ViewData["MasterPageOverride"];
var SESSION_TIMEOUT = #ViewBag["MasterPageOverride"];
var SESSION_TIMEOUT = #TempData["MasterPageOverride"];
Or, do it via jQuery AJAX:
$.ajax({
url: '/YourController/YourAction',
type: 'post',
data: { id: id },
dataType: 'json',
success: function (result) {
// setVar
}
});

Access a Model property in a javascript file?

Is it possible to access a Model property in an external Javascript file?
e.g. In "somescript.js" file
var currency = '#Model.Currency';
alert(currency);
On my View
<script src="../../Scripts/somescript.js" type="text/javascript">
This doesn't appear to work, however if I put the javascript directly into the view inside script tags then it does work? This means having to put the code in the page all the time instead of loading the external script file like this:
#model MyModel;
<script lang=, type=>
var currency = '#Model.Currency';
alert(currency);
</script>
Is there any way around this?
I tackled this problem using data attributes, along with jQuery. It makes for very readable code, and without the need of partial views or running static javascript through a ViewEngine. The JavaScript file is entirely static and will be cached normally.
Index.cshtml:
#model Namespace.ViewModels.HomeIndexViewModel
<h2>
Index
</h2>
#section scripts
{
<script id="Index.js" src="~/Path/To/Index.js"
data-action-url="#Url.Action("GridData")"
data-relative-url="#Url.Content("~/Content/Images/background.png")"
data-sort-by="#Model.SortBy
data-sort-order="#Model.SortOrder
data-page="#ViewData["Page"]"
data-rows="#ViewData["Rows"]"></script>
}
Index.js:
jQuery(document).ready(function ($) {
// import all the variables from the model
var $vars = $('#Index\\.js').data();
alert($vars.page);
alert($vars.actionUrl); // Note: hyphenated names become camelCased
});
_Layout.cshtml (optional, but good habit):
<body>
<!-- html content here. scripts go to bottom of body -->
#Scripts.Render("~/bundles/js")
#RenderSection("scripts", required: false)
</body>
There is no way to implement MVC / Razor code in JS files.
You should set variable data in your HTML (in the .cshtml files), and this is conceptually OK and does not violate separation of concerns (Server-generated HTML vs. client script code) because if you think about it, these variable values are a server concern.
Take a look at this (partial but nice) workaround: Using Inline C# inside Javascript File in MVC Framework
What you could do is passing the razor tags in as a variable.
In razor File>
var currency = '#Model.Currency';
doAlert(currency);
in JS file >
function doAlert(curr){
alert(curr);
}
Try JavaScriptModel ( http://jsm.codeplex.com ):
Just add the following code to your controller action:
this.AddJavaScriptVariable("Currency", Currency);
Now you can access the variable "Currency" in JavaScript.
If this variable should be available on the hole site, put it in a filter. An example how to use JavaScriptModel from a filter can be found in the documentation.
What i did was create a js object using the Method Invocation pattern, then you can call it from the external js file. As js uses global variables, i encapsulate it to ensure no conflicts from other js libraries.
Example:
In the view
#section scripts{
<script>
var thisPage = {
variableOne: '#Model.One',
someAjaxUrl: function () { return '#Url.Action("ActionName", "ControllerName")'; }
};
</script>
#Scripts.Render("~/Scripts/PathToExternalScriptFile.js")
}
Now inside of the external page you can then get the data with a protected scope to ensure that it does not conflict with other global variables in js.
console.log('VariableOne = ' + thisPage.variableOne);
console.log('Some URL = ' + thisPage.someAjaxUrl());
Also you can wrap it inside of a Module in the external file to even make it more clash proof.
Example:
$(function () {
MyHelperModule.init(thisPage || {});
});
var MyHelperModule = (function () {
var _helperName = 'MyHelperModule';
// default values
var _settings = { debug: false, timeout:10000, intervalRate:60000};
//initialize the module
var _init = function (settings) {
// combine/replace with (thisPage/settings) passed in
_settings = $.extend(_settings, settings);
// will only display if thisPage has a debug var set to true
_write('*** DEBUGGER ENABLED ***');
// do some setup stuff
// Example to set up interval
setInterval(
function () { _someCheck(); }
, _settings.intervalRate
);
return this; // allow for chaining of calls to helper
};
// sends info to console for module
var _write = function (text, always) {
if (always !== undefined && always === true || _settings.debug === true) {
console.log(moment(new Date()).format() + ' ~ ' + _helperName + ': ' + text);
}
};
// makes the request
var _someCheck = function () {
// if needed values are in settings
if (typeof _settings.someAjaxUrl === 'function'
&& _settings.variableOne !== undefined) {
$.ajax({
dataType: 'json'
, url: _settings.someAjaxUrl()
, data: {
varOne: _settings.variableOne
}
, timeout: _settings.timeout
}).done(function (data) {
// do stuff
_write('Done');
}).fail(function (jqxhr, textStatus, error) {
_write('Fail: [' + jqxhr.status + ']', true);
}).always(function () {
_write('Always');
});
} else {// if any of the page settings don't exist
_write('The module settings do not hold all required variables....', true);
}
};
// Public calls
return {
init: _init
};
})();
You could always try RazorJs. It's pretty much solves not being able to use a model in your js files RazorJs
I had the same problem and I did this:
View.
`var model = #Html.Raw(Json.Encode(Model.myModel));
myFunction(model);`
External js.
`function myFunction(model){
//do stuff
}`

Categories

Resources