I am trying to call a function from a Silverlight application. It should be a very simple task to do but so far I am not getting the result that I am looking for.
This is my Silverlight code:
private void button2_Click(object sender, RoutedEventArgs e)
{
HtmlPage.Window.Invoke("SayHello", new string[] { "Salut!" });
}
And this is the JavaScript code :
function SayHello(theid) {
alert(eval(theid));
var divStatusDiv = document.getElementById("divStatus");
divStatusDiv.style.backgroundColor = "Red";
}
The alert message always show "undefined" but when I press "OK" the colour of that DIV gets changed to Red as it should be.
Why am I getting "Undefined" all the time ?
You need to create the json that can be passed properly instead of just passing along an array like that. You can simply return "Salut!" instead of new string[] { "Salut!" } or you can create the json array for the string array you have.
I'm not familiar with Silverlight, but if theid has value "Salut!" inside of SayHello, then you cannot eval it, since it is a string of text, not code. You should change the line alert(eval(theid)); to just alert(theid);.
Use
alert(eval(theid.value));
Related
I'm trying to get a json data and a callback from javascript using webview.
I can get the json data but the problem is I cannot get the callback.
I need to fire the callback after a condition is met.
Android Code:
--------
// Adding the interface
webView.addJavascriptInterface(new WebAppInterface(this), "code");
--------
#JavascriptInterface
public void execute(String JsonData, String callback) {
String d = data; <---HAS JSON DATA RETURNED TO ANDROID
Log.d("jSon Data", d);
mCallback = callback; <---RETURNS "undefined"
}
Javascript code (I can't edit this.):
code.execute(JsonData, function(callback){
console.log(callback);
});
Android on button click
#OnClick(R.id.callback)
void onButtonCallback() {
String s = "Hello World";
// pass Hello World back to javascript. But I'm getting "undefined"
// for the callback
mCallback.passdata(s);
}
What I'm trying to achieve is:
1) Get data from Javascript to Android -> OKAY
2) Get the Callback from Javascript to Android -> Here's my problem
3) Fire the callback along with "hello world" string on button click
Note: I can't edit the javascript code. How am I going to achieve this? Do I need to inject Js from Android? If yes, how?
I just need to solve item number 2 to move forward. Thanks!
You can't do that. At least, based on my tests addJavascriptInterface() only works with primitive types and Strings, and so you cannot pass Javascript objects like functions.
I've created an ASP.NET MVC5 app with SignalR for the backend and using javascript for the front end. My web service returns a C# object defined like this:
public class MarkableItemList
{
public SortedList<string, MarkableItem> Items { get; set; }
public bool ItemsSelectable { get; set; }
public MarkableItemList()
{
Items = new SortedList<string, MarkableItem>();
}
}
My JavaScript function on the web page looks like this:
var updateState = function (state) {
//console.log("Item count: " + state.Items.Count());
console.log("ItemsSelectable: " + state.ItemsSelectable);
};
When I run the page, it correctly returns the state of ItemsSelectable but I cannot work out how to obtain the value from the SortedList. I'd like to get the count and then iterate over the list.
I've commented out the Count console log but I've tried all variants of:
length
count
camel casing/pascal casing
with and without brackets
In the console I either get
"Item null: undefined"
or I get
"Object doesn't support property or method 'Count'"
Any suggestions on how I can do this? Thanks in advance
It turns out that a SoredtList has a very obscure Json state so you cannot parse it so easily. I temporarily changed it to a List and it appears to produce normal Json that could be parsed. Thus I've now changed my code to use a List.
I'm trying to populate the array in my script (it's going to be used for charting with D3.JS later on). According to this post, I'm supposed to use the syntax below. However, it doesn't work, bacause I get the error on the pushy line saying Uncaught ReferenceError: WebSite is not defined, where WebSite is the name of the namespace of the data (I'm guessing that, as it's the name of my project).
<script>
var data = new Array();
#foreach (var piece in #Model.DataPieces)
{
#:data.push(#piece);
}
</script>
I'm pretty sure it has to do with the data type of piece, because the following change makes it work (at least not producing a bunch of errors). I'm picking out the individual fields from piece object and push those into the array, as a new object.
<script>
var data = new Array();
#foreach (var piece in #Model.DataPieces)
{
#:data.push({'cat': '#piece.Category', 'key': '#piece.Key', 'val': '#piece.Value'});
}
</script>
It's inconvenient, prone to mistakes and requires a refactoring of the assignment each time the model changes. How can I avoid this approach and be able to automagically create JSON objects upon assignment, as shown in the first sample?
The viewmodel for the Razor page is declared as folows.
namespace WebSite.Models
{
public class DrillDataViewModel
{
public List<DataPiece> DataPieces { get; set; }
public class DataPiece
{
public string Category { get; set; }
public string Key { get; set; }
public int Value { get; set; }
}
}
}
The line #:data.push(#piece); will be written to the output HTML as
data.push(<the result of calling ToString() on #piece>);
You need to replace #piece with something that will be evaluated to the JSON you want. This should work:
#:data.push(#Html.Raw(Json.Encode(piece)));
Or you can just output the whole array at once:
var data = #Html.Raw(Json.Encode(Model.DataPieces));
Try to pass this from Razor page to JavaScript.
#Html.Raw(#JsonConvert.SerializeObject(Model.DataPieces)
.Replace("{\"", "{")
.Replace(",\"", ",")
.Replace("\":", ":"))
The replaces serve to get rid of the invalid characters produced by default in the converter without you needing to play with streams or applying other libraries. Ugly but working.
Sometimes, I also add one more replace: .Replace("\"","'") to get a more JS like look. The outer method is needed so you don't get problems with & in the "e;.
This is a hand-on solution so if anybody knows a better way, I'd love to get some feedback.
Try
var yourJavascriptArray=#Html.Raw(Json.Encode(YouModel));
I want to make a class of mine accessible in JavaScript via a C# WebView-Control.
Therefore I am using the WebView.AddWebAllowedObject method. However if I assign an attribute, it works fine, but if I assign the whole class to get all attributes in js, all of the attributes(and methods btw) are "undefined". I tried everything I found in the www. See the attached code:
//The class I want to make accessible
[AllowForWeb, ComVisible(true)]
[MarshalingBehavior(MarshalingType.Agile)]
public class DeviceInformation
{
public string IPAdress { get; private set; }
public DeviceInformation()
{
IPAdress = GetIPAdress();
}
public string GetDeviceUUID()
{
EasClientDeviceInformation deviceinfo = new EasClientDeviceInformation();
return deviceinfo.Id.ToString();
}
public string GetIPAdress()
{
List<string> ipAddresses = new List<string>();
var hostnames = NetworkInformation.GetHostNames();
foreach (var hn in hostnames)
{
if (hn?.IPInformation != null && (hn.IPInformation.NetworkAdapter.IanaInterfaceType == 71 ||
hn.IPInformation.NetworkAdapter.IanaInterfaceType == 6))
{
string ipadress = hn.DisplayName;
return ipadress;
}
}
return string.Empty;
}
}
Here the objects are initialized.
DeviceInformation devinf = new DeviceInformation();
private void View_NavigationStarting(WebView sender, WebViewNavigationStartingEventArgs args)
{
if (args.Uri.Host == "")
{
//win_ipadress has an ipadress as value
view.AddWebAllowedObject("win_ipadress", devinf.IPAdress);
//deviceInformation is initialized as well but I have no access to its attributes
view.AddWebAllowedObject("deviceInformation", devinf);
}
}
That's the way i call it in js:
else if ($.os.ie) {
myIpAdr = window.win_ipadress;
//Throws an exception because GetIPAdress() is "undefined"
myIpAdr = window.deviceInformation.GetIPAdress();
}
I am using this in a Windows Universal App. The Javascript and in the WebView displayed HTML-Code is already in use for Android an iOS.
I believe you need to define the method name starting with a lower case character.
For example: change GetIPAddress to getIPAddress.
I tested it on my side and found if I use the upper case name 'GetIPAddress', it won't work. But if I use getIPAddress, it works.
And after I read kangax's explanation in this thread, I think it makes sense.
[Update]
Since it still doesn't work after you make the change on method name, I think the issue should be related to how you expose the windows runtime object. I guess you simply defined the DeviceInformation class and tried to use it in the same project.
First, we need to create a separate windows universal windows runtime component project.
The c# class DeviceInformation should be put into this project. Keep the same code.
Then, in your universal app project, add reference to the windows runtime component and keep rest code to consume the windows runtime object.
[Update 2]
Just noticed an interesting behavior in VS. No matter if the Method name we defined in C# is starting with uppercase or lowercase, the visual studio intellisense shows the lowercase, so the method name will be automatically converted when we try to use it in js.
I am trying to figure out the correct javascript syntax for a DevExpress datagrid callback to pass data back to the client.
In the .aspx I installed an onclick event in the DataGrid row with a CustomCallback event using the js call: dg.PerformCallback(key); and in the aspx.cs file this function is correctly reached, however I cannot pass data back to the client:
protected void dg_CustomCallback(
object sender,
DevExpress.Web.ASPxGridView.ASPxGridViewCustomCallbackEventArgs e)
{
string key = e.Parameters; // works
e.Results = "something"; // .Results does not exist
return;
}
Then I switched from a CustomCallback to a DataCallback because the DevExpress.Web.ASPxGridView.ASPxGridViewCustomDataCallbackEventArgs does have a .Results property. However, I cannot figure out the corresponding javascript call. I tried in vain: dg.PerformCallback(key); , dg.PerformDataCallback(key); and dg.SendCallback(key);
Also I am wondering, when the above problem is fixed, which js function I need to program to receive the return data from the server after the callback.
What you are trying to achieve can be done using the JSProperties on callback and the OnEndCallback client side event of the ASPxGridview. This aspx tag can be placed exactly after the </Columns> closing tag of the ASPxGridview.
<ClientSideEvents EndCallback="function(s,e)
{
var errText = s.cpError;
if (errText != "")
{
alert(errText);
}
}" />
On the server side you set the JSProperties like this
gridOfApp.JSProperties["cpError"] = "The error was major!";
Important. Bear in mind that your JSProperties MUST ALWAYS start with the cp prefix.