How do I set Razor variabele in Javascript? - c#

I'm setting Razor variables with data from my controller like this:
#{
var filterData = ((ShipmentController)this.ViewContext.Controller).GetNoCmrs(new List<int>() { 1 });
}
I want to change this data based on the selected option the user selects (within a select).
<script>
var x;
function loadShipmentsByCondition() {
x = document.getElementById("conditionSelect").value;
if (x === "CMR not received") {
#filterData = #newData;
} else if(x === "Not invoiced") {
console.log("INVOICE");
#filterData = #otherData;
}
}
</script>
Is this possible? Or if not, how can I do this efficiently?
I'm using MVC ASP.NET and vue js as front-end.
Thanks

Unfortunately, you cannot get JavaScript to change a value of your backend C# code because JavaScript, once rendered on the frontend, does not know anything about your C# code on the server.
However, you can assign a C# value to a JavaScript variable before it leaves the server. What this is doing is just injecting the value of #filterData into the html page in the script and then is assigned to the real JavaScript variable in the actual JS environment during runtime:
<script>
var x;
var filterData = #filterData;
var otherData = #otherData;
var newData = #newData;
function loadShipmentsByCondition() {
x = document.getElementById("conditionSelect").value;
if (x === "CMR not received") {
filterData = newData;
} else if(x === "Not invoiced") {
console.log("INVOICE");
filterData = otherData;
}
}
</script>
So you are essentially converting those C# variables into JavaScript variables, but if you really need to change the C# variables then you would have to do a postback, or AJAX call to the server.

Related

AngularJs - Assign Value to scope variable inline

It's a fairly simple problem, I am using AngularJS v1.7.2 with C# MVC.
I got my standard setup with Layout pages and Views.
I load my AngularJs controllers/services from external script files so there's nothing on the Views.
My problem is that I want to assign a value from ViewBag to a controller variable, but I obviously can't reference ViewBag in a script as it needs to be done on the cshtml page.
I have tried doing it inside ng-init like so
<div ng-init="City = #ViewBag.City"></div>
Or
<div style="visibility: hidden;">{{CityId = '1'}}</div>
I tried variations with {{City = #ViewBag.City}}, '#ViewBag.City' and couple of others I saw on StackOverflow to no avail.
I load my scripts on the view using:
#section Page_Scripts {
#Scripts.Render("~/angular/ngListing")
}
That obviously is loaded in Layout. My controller works fine so that's not the issue.
My controller is making an ajax call upon initialization, at that point I need the $scope.City to be populated with the right value, however it's always set at 0.
Here's what my controller + service (combined for sake of SO) looks like:
_mainApp.controller("ListingCtrl", function ($scope, $http) {
$scope.City = 0;
$scope.Attractions = [];
$scope.Offset = 0;
$scope.Pages = new Array(10);
var MakeRequest = function (offset) {
$http.post("/City/GetStuff?City=" + $scope.City + "&Offset=" + offset).then(function (resp) {
$scope.Attractions = resp.data;
});
}
MakeRequest($scope.Offset);
$scope.PageUp = function () {
$scope.Offset++;
MakeRequest($scope.Offset);
}
$scope.PageDown = function () {
$scope.Offset--;
MakeRequest($scope.Offset);
}
$scope.GoTo = function (offset) {
$scope.Offset = offset;
MakeRequest(offset);
}
});
Any solution that is not hacky-ish would be appreciated. It can include directives or a way to assign a value to $scope.City but inline, or at least get my ViewBag.City value passed to the controller somehow.
Use a function in the ng-init directive:
<div ng-init="initCity(#ViewBag.City)"></div>
Define the function in the controller:
$scope.initCity = function(city) {
$scope.city = city;
MakeRequest($scope.offset, $scope.city);
};
function MakeRequest(offset,city) {
var url = "/City/GetStuff";
var params = {city:city, offset:offset};
var config = {params: params};
$http.get(url,config).then(function (resp) {
$scope.Attractions = resp.data;
});
}
This way the controller will wait for the ng-init directive.

Populate variable from a JSON Result in ASP.NET MVC

I don't know if this is a basic stuff but I'm a having a hard time on populating a variable from a JSON result. I can't just find a right keyword on it.
What I want to do is populate this variable.
Js File
var opts = [
{ key: 1, label: 'High' },
{ key: 2, label: 'Normal' },
{ key: 3, label: 'Low' }
];
Layer
public IEnumerable<DropdownModel> ToLayerLevel()
{
List<DropdownModel> data = new List<DropdownModel>();
using (SqlConnection con = new SqlConnection(Conn.MyConn()))
{
SqlCommand com = new SqlCommand("SELECT id, desc FROM PriorityLevel", con);
con.Open();
SqlDataReader reader = com.ExecuteReader();
while (reader.Read())
{
DropdownModel value = new DropdownModel();
value.key = reader.GetInt32(0);
value.label = reader.GetString(1);
data.Add(value);
}
}
return data;
}
Controller
public JsonResult ddlToLayerLevel()
{
DropdownLayers ddl = new DropdownLayers();
var data = ddl.ToLayerLevel();
return Json(data, JsonRequestBehavior.AllowGet);
}
You can make an ajax call to the server action method where it will return the data you need
public JsonResult ddlToLayerLevel()
{
var ddl = new DropdownLayers();
var data = ddl.ToLayerLevel().ToList();
return Json(data, JsonRequestBehavior.AllowGet);
}
This will return an array of items with key and label properties, in JSON format
[{"key":1,"label":"High"},{"key":2,"label":"Normal"},{"key":3,"label":"Low"}]
Now you can call this action method using ajax . Here is a sample using jQuery $.get method.
var url="/YourControllerName/ddlToLayerLevel";
$.get(url).done(function(resultArray) {
// resultArray is an array of items.
// Use it inside this callback method scope
var opts=resultArray;
console.log(opts);
});
To avoid 404 Not found errors, when making ajax call's from external js files, you may use the Url.Action method to generate the correct relative path in your view file(where you can execute C# methods like Url.Action) and use that in your external js file.
For example, you can do like this in your razor view file
<script>
var myProject= myProject|| {};
myProject.layerLevelUrl ="#Url.Action("ddlToLayerLevel","YourControllerName")";
</script>
<script src="pathToYourExternalJsFile.js"></script>
Now in your external js file you can use it like
$.get(myProject.layerLevelUrl)
.done(function(resultArray) {
// resultArray is an array of items. Use it inside this callback method
var opts=resultArray;
console.log(JSON.stringify(opts));
});
Getting data using jQuery:
var opts = [];
$.getJSON("<your url here>", function(res){
opts = res;
});
There is an alternate simplified way I use when I need to get objects created in c# directly into a js variable. It does come with pros and cons though
pros
Much quicker to code rather than having to create a controller and call a js ajax function every time.
Loads the entire page in one go and overall loads the data into js faster.
cons
The code doesn't go into your js file but instead into a cshtml file.
The information is only fetched in load time and the code can't be reused in real time when the page is still open.
If you don't need the js variable on page load, not using this would speed up the initial page load speed and will load the js information later.
First I create an extension function in static class as follows:
public static IHtmlContent ToJS(this IHtmlHelper htmlHelper, object obj)
{
return htmlHelper.Raw(JsonConvert.SerializeObject(obj));
}
Now in any cshtml file I can define the js variable by simply using the following:
#{
DropdownLayers ddl = new DropdownLayers();
var data = ddl.ToLayerLevel();
}
<script>
var opts = #Html.ToJS(data);
</script>

How can i use model in Javascript?

Example :
<script type="text/javascript">
function abc() {
var t = document.getElementById("name").value;
#foreach(Player pl in Model){
if (t == pl.Name) {
alert("This name is already use!");
}
}
</script>
Error : t - cannot resolve symbol
How can i use JavaScript variable in C# code? Is it possible in this example?
You cannot use JS variables in C# code , but you can use C# variables in the code.
In most cases C# is used to render HTML or JS.
In your case it would be best if you render your C# serverside model as a JS array , which you can later on iterate.
make an action that returns your list (assuming it's a list) as
a JSON
fetch the data with an AJAX get call to your action.
Cheers!
You may do something like this.
<script type="text/javascript">
function abc(players) {
var t = document.getElementById("name").value;
for(p in players) {
if (t == p.Name) {
alert("This name is already use!");
}
}
abc(#Html.Raw(Json.Encode( Model )));
</script>

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