5

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.

tereško
  • 58,060
  • 25
  • 98
  • 150
Adam
  • 3,615
  • 6
  • 32
  • 51
  • You're not showing us how/where the JS timer is actually initialized, e.g. with `setTimeout`. – Madbreaks Nov 08 '12 at 17:59
  • I'm assuming that your controller is written in JS. Given that, this makes little sense: _"Is it possible to set a javascript variable from a controller?"_ – Madbreaks Nov 08 '12 at 18:01
  • It's written in C#. @Madbreaks thats why I am not sure its possible. – Adam Nov 08 '12 at 18:03

3 Answers3

7

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>
Community
  • 1
  • 1
vinczemarton
  • 7,756
  • 6
  • 54
  • 86
  • Yep, this is the best way. It can't hurt to throw a comment on there like "// mix of Razor and JS here! " to let newer programmers know that you are printing out JS via Razor. Also, you can do this with ViewModel properties too, not just ViewData. Here's a line of JS in a view I'm working on now: var json = @Html.Raw(Model.MemberPACJSONInfo); MemberPACJSONInfo Is a ViewModel string prop that's filled with JSON. By rendering it out this way, my View's JS has access to that same serialized object. – Graham Nov 08 '12 at 18:15
  • 1
    And booleans need a _lot_ more attention, since `@myBoolean` will evaluate to `True` or `False`, which causes a Javascript error because of the capitalization. The simplest method I've found of interpolating a boolean into Javascript is `@(myBoolean ? "true" : "false")` – swinn Sep 20 '22 at 15:16
  • @SpyderScript thats a good point – vinczemarton Sep 20 '22 at 17:55
0

If tb is within the scope of your controller, consider just overriding the sessionTimer function:

public dumbDownController(){
   ...
   tb.sessionTimer = function(){return false;}
}
Madbreaks
  • 19,094
  • 7
  • 58
  • 72
0

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

                }
            });
user1477388
  • 20,790
  • 32
  • 144
  • 264