Assign Viewbag to js variable throws an exception - c#

I want to assign viewbag to my javascript variable to compare some value from model
<script>
var uid = "..."; // this retrieves some variable from external server
#ViewBag.someId = uid;
</script>
...
#If(Model.AppDataFbId == ViewBag.someId){ ... }
But this throws an exception:
Uncaught SyntaxError: Unexpected token =
What can I do?

As the comment said , ViewBag is server side code, you can't set ViewBag with js variables in C# code block but you can set js variables with ViewBag value. Like:
<script>
var uid ='#ViewBag.someId';
</script>
If you just want compare Model.AppDataFbId with js variable(uid), add the logic in js code.
<script>
function compare(){
if('#Model.AppDataFbId'==uid){
//other code
}
}
</script>

The variable #ViewBag.someId is used by the server to generate the static HTML page it sends to the browser. It doesn't make sense for the browser to be able to directly change that variable on the server after it receives the HTML.
It looks like you want the value of uid to decide the page contents. If you want these changes to be made server-side (i.e. before the page is sent to browser) then you will have to get your MVC controller to grab this value from the external server before it returns its view. A more conventional way to solve the same problem is to transform the page in the browser with Javascript.

Related

JavaScript not posting to the right action in ASP.NET MVC with implicit Index

When I surf to the address like this:
server:port/Controller
it automatically assumes that the action requested is Index, so the displayed page is equivalent to this:
server:port/Controller/Index
My problem is that when I execute something like this on a button click:
$(function () {
$("#clickaroo").click(function (event) {
event.preventDefault();
$.post("Action", null, function () { ... });
});
});
it fails when I'm at Index implicitly (i.e. page for that action is shown but the URL doesn't contain its name), while working when accessing it explicitly (i.e. URL says .../Controller/Index). If I then change the post into this:
$.post("Controller/Action", null, function () { ... });
it works for the former but starts to fail for the latter. Of course, I do understand why - location.href is suffixed by /Action and without the controller's name or with the name repeated, it gets confused. What's a best-practice way to handle that?
Horse around with RouteConfig.cs file? (sounds overkill)
Adding a condition in the JS? (feels as a baaad design)
Force the URL to be explicitly suffixed? (unsure how to)
The best solution is to use the Url.Action or Url.RouteUrl html helper method(s) to build the correct relative url to the action method. This will take care of building the correct url irrespective of the current page/view you are in.
var url1="#Url.Action("Create","Home")";
//use url1 now.
The above code will work if you have your javascript inside the razor views. If your script is inside an external file, You can build the relative url to the root and pass that to your js file and use that to build the url's as needed. Make sure to use javascript namespacing when doing so to avoid possible issues with global javascript variables.
So in your razor view (Layout file or specific view), you may do this.
<script>
var myApp = myApp || {};
myApp.Urls = myApp.Urls || {};
myApp.Urls.baseUrl = '#Url.Content("~")';
myApp.Urls.jobListUrl= '#Url.Action("Index","jobs")';
</script>
<script src="~/Scripts/YourExternalJsFile.js"></script>
And in your YourExternalJsFile.js file, you can read it like
var urlToJobIndex= myApp.Urls.jobListUrl;
// Or With the base url, you may safely add the remaining url route.
var createUrl= myApp.Urls.baseUrl+"home/create";
Edit : If you simply care about getting the root/base url of the site so you can append that to get the other url you are after, you may simply use / as the first character of your url.
var createUrl= "/home/create";
For your specific click event on an anchor tag use case, you can simply read the href attribute value of your link and use that.
If you want to make the ajax call to the same action method as the href attribute value of the link.
<a id="clickaroo" href="#Url.Action("Create","Customer")">Create<a/>
And in your click event get the href attribute value
$(function(){
$("#clickaroo").click(function(e){
e.preventDefault();
var u = $(this).attr("href");
$.post(u,function(response){
});
});
});
If you want to make the ajax call to the some other action method than the one in href attribute value of the link.
Here you can use data attribute to keep the other url in the link tag markup.
<a id="clickaroo" href="#" data-targurl="#Url.Action("Create","Customer")">Create<a/>
And in your click event get the data attribute value for "targurl"
$(function(){
$("#clickaroo").click(function(e){
e.preventDefault();
var u = $(this).data("targurl");
$.post(u,function(response){
});
});
});
You can use html5 attirbute as you have extetnal js files so razor will not be accessible there, use data- attribute on your button and then pick the url via jquery in the click handle like:
<button id="clickaroo" data-url="#Url.Action("Action","Controller")">Click me</button>
and then in js file:
$("#clickaroo").click(function (event) {
event.preventDefault();
var button = $(this);
$.post(button.data("url"), null, function () { ... });
});

Access global static variable from code behind through Javascript

I'm having some issues accessing a static variable in a class when getting it from a code behind function called from javascript.
My aspx page:
<script type="text/javascript">
function AlertMsg(msg) {
var msg213 = "<%= GetValue(" msg ") %>";
alert(msg + '::' + msg213);
}
</script>
Code behind:
public string GetValue(string sString)
{
return MyNamespace.MyClass.MyStaticVariable;
}
I set this variable in a page_load in another page. I'm accessing the javascript function by invoking it from a C# WebBrowser application. It's always empty.
Any ideas?
I think you just need to add '+' around your reference to 'msg'
var msg213 = "<%= GetValue(" + msg + ") %>";
ASP.NET isn't like a desktop application, any variables written on another page will be lost when moving to another page. You need to save the value to somewhere persistent.
Session
Cache
Database
App or Web Config files.
Variable needs to be a const or static
Try this
'<%= GetValue("Some Value") %>';
This means when page rendering, GetValue method calls and return string will be write in the document body, like Respose.Write
This will only happend when when page rendering and no further call will happend.
I think part of the confusion is coming from the formatting in the code. If you look at just the server tag: <%= GetValue(" msg ") %>, you will see that the GetValue method is being invoked, and the literal string msg is being passed in. There are quotes around the server tag itself, but those do not affect what is inside the server tag. You are not passing in the value of the msg parameter of the JavaScript function.
Server methods cannot be invoked from JavaScript in such a simple manner, it requires using something like AJAX to accomplish.

passing javascript parameters and using them in unity C# files

I want to pass some javascript parameters at runtime (webplayer) to unity and using them in my network.cs script.
<html>
<script type="text/JavaScript">
//<![CDATA[
PlayerName = "Adam";
playerID = "56";
//]]>
</script>
</html>
Just consider I am using the above parameters to log in users.
You need to send the data from the webpage to the Unity3d container. You can do something like this:
u.getUnity().SendMessage(GameObjectName,MethodName,stringParam);
where:
u is the Unity3d container object created by unity if you use their template.
GameObjectName is the name of a game object that you placed somewhere on the stage
MethodName is the name of a method that's available for that GameObject, that means that it will be a method defined in one of the components (MonoBehaviour) that you attached the the GameObject
stringParam si the parameter that you pass to MethodName, the method can only accept one string param, so you need to serialize your data, you can use JSON.parse( {"playerName":PlayerName,"playerId":playerID} )
On the C#/Unity side you need to implement a MonoBheviour that has a
void MethodName(string param);
defined that reads the string and with a JSON parser gets the data out.
You would need to post that data back to your server. Using AJAX is probably want you want if you don't want your whole page to reload.
A commonly used framework, facilitating ajax is jQuery.
You would need an endpoint, writting in your c# (guessing from your fileending on network.cs) to read what your clientside javascript is posting. I don't know what version of .net you are on, but look into WebAPI - it is very easy to implement.
TL;DR
Use javascript/jquery to post your data from the client to the server.
Read the posted data on your serverside, though either WebAPI or just a normal .aspx page reading querystring/form values
If you just want to send data from the client, and not worry about any response, you can use
$.ajax({
type: "POST",
url: url,
data: {PlayerName: PlayerName, PlayerId: playerID},
});
You can change POST to GET if you want the make a get request instead. The data will be readable through Request.Form or Request.QueryString if you use a normal .aspx page for url. If you use WebAPI, it will be injected into your methods parameters.

What is a good way of getting a class object from the server and into a js object on initial page load?

Currently, I'm doing something like this in my application:
// Foo Controller
public ActionResult Details(int id)
{
ViewBag.id = id;
return View();
}
// Foo Details View
<script type="text/javascript">
var viewBag = {
'id': #ViewBag.id
};// *Note: MVC will cry about a syntax error here, everything's ok though
</script>
<script type="text/javascript" src="#Url.Content("~/Views/Foo/details.js")"></script>
// details.js
$(function(){
var jqXHR = $.ajax({
'url': '/api/foo/getData/' + viewBag.id,
'type': 'GET'
});
jqXHR.done(function(data){
...do stuff with data object...
});
});
// Foo Api Controller
// Instantiates the data class object to be serialized and returned
I do this because in the <javascript> element, I don't want a huge JSON string of the object just hanging out in here. Ideally, I would like to just make a single call to the Foo Controller and have it instantiate the data class object, serialize it to a JSON string, and assign it to ViewBag.dataModel or something of the sort.
And of course I can't access #ViewBag inside a .js file since it's a server side object. Does anyone know of a neater way of doing this rather than having this somewhat unnecessary back and forth?
One thought was to parse the URL for the parameters but that could potentially get ugly depending on the route structure and I would still need to wait for the initial get of the view to get the js scripts to do all that, and still end up having to make that second call anyways.
I don't know if it's possible or not but is there a way I could dynamically generate a .js file during the view creation that could serve as a js ViewBag, add it to the page before the details.js file loads, and then be able to access it that way? Or maybe modify the details.js file on the fly (which might not be ideal if minifying/bundling is desired)?
The desired outcome is, I'm using knockoutJS and the initial object I'm trying to pass over is the ViewModel I want to bind to the page that contains all of the initial data from the server that I want to use. The data object I'm getting from the server is the ViewModel which I map to an observable and bind to the DOM. The current method I'm using seems to work fine and doesn't seem to have much overhead, but if I can avoid the second call to the server on the page's initial load, that would be ideal.
Firstly, I wouldn't write dynamic information to the script tag. Instead encode your data as JSON and then write it to a hidden field.
As you are using MVC4 you will already have a reference to JSON.NET so you should be able to do this:
In the controller
public ActionResult Details(int id)
{
var myModel = GetMyModelData(id);
string modelJson = JsonConvert.SerializeObject(product);
return View(modelJson);
}
In the view
<input type="hidden" id="model" value="#Model" />
In Javascript
var modelJson = $('#model').val();
var modelObj = JSON.parse(modelJson);

Using Server side method from Javascript without AJAX

I have a tricky problem. I am in a situation where I need to use a method defined in a .cs file from a javascript function. The problem is we are using .NET 1.1 and AJAX cannot be used for the application.
Also, I will need to pass a string from the javascript to the server side method. The page where I am implementing the javascript is a .as Any ideas?
I have tried doing a post back and creating a RaisePostBack event handler method (both in the .aspx page and the .ascx user control) but no luck.
It will be greatly appreciated if someone could help me out with the problem.
To be more precise. I have a class Attachment.cs which has a method Delete().
The javascript is called from a span's onclick event. The javascript function's input parameter would be a string which I will need to use to instantiate an Attachment.
I created a method which instantiates an Attachment using a string and calls the corresponding Delete() method for the Attachment object.
Now, I will need to pass the string from javascript function to the method I have created. I cannot use PageMethods.
The Javascript function is like:
// File ID is a string
function DeleteAtt(fileID)
{
//I tried PageMethods here, tried posting the page and getting the value through
// a RaisePostBack event etc. No luck.
}
The cs method I created is like:
public void DeleteAttachment(string ID)
{
Attachment obj = new Attachment(ID);
obj.Delete();
}
Do you mean that Microsoft's "ASP AJAX" is not an option, or do you mean that any jquery/any other library, or your own hand written javascript ajax won't work? ASP AJAX may not be supported by you version of .net, but surely simple javascript will still work, as you want to access the page from javascript.
If this is the case, something as simple as this, using jquery, would work:
function submit() {
$.post(
"pagename.aspx?string=" + variable,
function (data) {
alert("Response: " + data);
});
}
How about adding a callback-url as a query string to the url that you need to submit data to? Example:
Initial Page:(javascript)
function send(){
window.location = "submiturl.aspx?str=var&
callbackurl=http://www.myurl.com/page.aspx";
}
submiturl.aspx then catches both query strings [str] and [callbackurl], performs the action/function and then sends a response back to the [callbackurl]
response.redirect(callbackurl + "?response=" + data);
Initial Page now uses response.querystring to determine if it was succesful/whatever else you want and continues its business.
This definitely does not use ajax, and would be, by no means, asynchronous, but is based on a pretty lengthy history of API/callback & response design.
You can inject an invisible Iframe into the page and the SRC of the iframe can be used to pass data back to the server.
This is a very old technique back before jQuery and Prototype were invented.
See: http://www.ashleyit.com/rs/ for other alternatives.

Categories

Resources