IE Automation - Calling a client JavaScript **method** from server-side C# - c#

Given the following C# code:
public object CallJavaScriptFunction(string functionName, params object[] args)
{
object script = Document.Script;
var result = script.GetType().InvokeMember(functionName, BindingFlags.InvokeMethod, null, script, args);
return result;
}
And the following client-side JavaScript block:
function someFunction() {
alert('This is only a test!');
}
var someObj = {
someMethod: function() {
alert('This is another test!');
}
}
The following server-side block executes successfully:
CallJavaScriptFunction("someFunction");
But this will throw a DISP_E_UNKNOWNNAME:
CallJavaScriptFunction("someOBj.someMethod");
Obviously I'm doing something wrong here - probably there is another way of calling InvokeMember on JavaScript instance methods, but I was not able to find out how.
Any thoughts? Any help will be appreciated.

You need to invoke the someObj property, then invoke the someMethod method on the value of the property

Related

How does a lambda expression working in the given code snippet

I have the below code snippet in my project. I am new to lambda expressions. I have some idea about it and also
started using it. But I do not understand how the below code is working. Specially,
NotifyIntrenal( notification, callback, changedTypes => ..
Now here changedTypes is one of the parameter for method NotifyIntrenal. We derive its value using an anomymous method.
If I see the code, since I do not assign any value to changedTypes, so as per my understanding the code if (changedTypes == null) should
always be true. But this is not the case when I debug.
Can someone explain me how does this works here?
private void Notify( Notification notification )
{
var nameDto = GetNameDto();
foreach (var subscription in _subscriptionsDictionary)
{
var callback = subscription.Key;
var subscribedTypes = subscription.Value;
NotifyIntrenal( notification, callback, changedTypes =>
{
if (changedTypes == null)
return subscribedTypes;
if (!changedTypes.Any())
return subscribedTypes;
return changedTypes.Intersect(subscribedTypes);
}, nameDto);
}
}
Thanks & Regards
changedTypes is not an argument to NotifyInternal. It is the parameter for the anonymous method.
This whole method is the argument for NotifyInternal.
The code inside that lambda is not executed at this point. It will only be executed if some line in NotifyInternal calls it. So there has to be code line in NotifyInternal executing the anonymous method:
void NotifyInternal(Notification notification, Callback callback, Func<IEnumerable<Type>, IEnumerable<Type>> function, string nameDto)
{
// ... some code
// execute the lambda
var result = function(mychangedtypesvariable);
// ... more code
}
Only then the code inside the lambda is executed, using the pass argument (mychangedtypesvariable in that example). So if this will be null you cannot decide from the snippet you see.
changedTypes is just a paremeter for your anonymous method, not for NotifyIntrenal. The latter however calls that anonymous method and fills the parameter (if required) appropriately. In your case the anonymous method expects an IEnumerable<MyType> and returns an IEnumerable<MyType>.
NotifyIntrenal(string arg1, string arg2, Func<IEnumerable<MyType>, IEnumerable<MyType>> func) {
// do something
var list = new List<MyType> { ...}
// execute the delegate with the list
IEnumerable<MyType> result = func(list);
}
So actually changedTypes is provided by NotifyIntrenal, not given to it. How you create that argument within the method is up to you.

can a value be stored in variable returned by a function called as a parameter

Hi I was integrating facebook SDK in unity and basically I worked in java earlier and I am new to c# script and a question came to my mind.
I have searched a lot found nothing, may be my searching query is good enough or not but my question is ...
as a function FB.init called here
void Awake ()
{
FB.Init(InitCallback, OnHideUnity);
}
here when init function will be called it will call InitCallBack and OnHideUnity functions and both are returning void these are used form facebook-unity-sdk docs
private void InitCallback ()
{
if (FB.IsInitialized) {
// Signal an app activation App Event
FB.ActivateApp();
// Continue with Facebook SDK
// ...
} else {
Debug.Log("Failed to Initialize the Facebook SDK");
}
}
private void OnHideUnity (bool isGameShown)
{
if (!isGameShown) {
// Pause the game - we will need to hide
Time.timeScale = 0;
} else {
// Resume the game - we're getting focus again
Time.timeScale = 1;
}
}
My question is if I call a function like this and that function return something e.g String and I want wanted to store it something like this
String result="";
SomeFunctions(FunctionOne,result=FunctionTwo);
String FunctionTwo()
{
return "a String";
}
Is this possible?
Is there any way to get value returned by such function call?
Or is this possible that a function that returns value can be called in this way?
It seems like you are confusing a delegate for a function expression. The delegate will have no return value until it is invoked as a function.
void SomeFunction(Func<string> func) {
var result = func(); // only here will the function return value be accessible
Console.WriteLine(result);
}
SomeFunction(() => "test");
Although you do not have access to the return value of the function, the delegate could assign a variable you choose inside it's method body, instead of using it's return value:
string result;
SomeFunction(() => {
result = "test";
return result;
});
// result would now contain "test"
I am not sure what you want to achieve here, but you could use out to change the reference of the parameter.
string result="";
MyMethod(out result);
Debug.Log(string.Format("Result: {0}", result));
void MyMethod(out string pValue)
{
pValue = "my changed value";
}
The out keyword causes arguments to be passed by reference. This is like the ref keyword, except that ref requires that the variable be initialized before it is passed. To use an out parameter, both the method definition and the calling method must explicitly use the out keyword.
https://msdn.microsoft.com/en-us/library/t3c3bfhx.aspx
But in a case like this, you could just return the correct value. In the example below its not even worth passing the parameter since we are not using it.
string result = MyMethod(result);
string MyMethod(string pValue)
{
pValue = "My changed value";
return pValue;
}

WPF Browser throws error

I am calling javascript functions from C# using the WPF variant of the browser control via InvokeScript.
I can call my function once without any problems. But when I call it a second time, it throws the following error :
Unknown name. (Exception from HRESULT: 0x80020006
(DISP_E_UNKNOWNNAME))
The Code I am using is the following :
this.browser.LoadCompleted += (sender, args) =>
{
this.browser.InvokeScript("WriteFromExternal", new object[] { "firstCall" }); // works
this.browser.InvokeScript("WriteFromExternal", new object[] { "secondCall" }); // throws error
};
The javascript function is :
function WriteFromExternal(message) {
document.write("Message : " + message);
}
I can call C# functions from the page via javascript just fine and invoke from C#, just can't invoke a second time. Regardless of what function I call.
I do not understand why it would fail the second time.
Thank you
Edit :
Did the following test (javascript) :
function pageLoaded() {
window.external.tick();
window.external.tick();
window.external.tick();
}
window.onload = pageLoaded;
function WriteFromExternal(message) {
document.write("Message : " + message);
}
And this is the C# side :
private int i = 0;
public void tick()
{
invoke("WriteFromExternal", new object[] { "ticked"+ i++ });
}
public static void invoke(string method, object[] parameters)
{
mainInterface.browser.InvokeScript(method, parameters);
}
And still throws the same error (after the first call), this suggests that it does not matter from where it is called, invoking the function from C# will throw this error if done more than once.
I assume you did the same as me and put your scripts in the body. For some reason when you call document.write from wpf it completely overwrites the document. If instead of using document.write you append a child it works fine. So change your JavaScript function to be:
window.WriteFromExternal = function (message) {
var d = document.createElement("div")
d.innerHTML= "Message : " + message;
document.body.appendChild(d);
}
// call from c#
WriteFromExternal("test")
It's been a while since I did something similar, but from what I remember your code looks correct. However, I do remember using a slightly different pattern in my project. Instead of delegating back to a JS method on the page I would make my ScriptingHost methods return values
EX:
C#:
public string tick()
{
return "some stuff";
}
var msg = window.external.tick();
document.write(msg);
If you have more complex objects than simple strings you can serialize them to JSON and parse them into an object on the JS side.
var jsonObj = JSON.parse(window.external.someMethod());
Not sure if you have the luxury of being able to change your method signatures in your scripting object, but it's at least an alternative approach.
Also, in your current implementation, have you tried to do something other than document.write? Do you get the same error if you display an alert box?

IronPython calls TryGetMember instead of TryInvokeMember

i'm trying to hand over a Dynamic object to Ironpython, but it seems Ironpython is not calling TryInvokeMember. Instead it calls TryGetMember and gives an Error that it cant call the result.
I have tried it with IronPython 2.7 and 2.6.10920
ExampleCode:
DynamicObject:
class ExampleDynamicObject: DynamicObject {
public override bool TryGetMember(GetMemberBinder binder,
out object result) {
result = "TryGetMember";
return true;
}
public override bool TryInvokeMember(InvokeMemberBinder binder,
object[] args,
out object result) {
result = "TryInvokeMember";
return true;
}
}
calling Mathode
static void Main(string[] args) {
dynamic example = new ExampleDynamicObject();
var program = #"test = example.Call2(2)";
var engine = Python.CreateEngine();
var scope = engine.CreateScope();
scope.SetVariable("example", example);
var source = engine.CreateScriptSourceFromString(program,
SourceCodeKind.Statements);
source.Execute(scope);
Console.ReadKey();
}
This calls the TryGetMember method and then throws a Microsoft.Scripting.ArgumentTypeException "str is not callable"
This is thrown when u code something like 'test'(1)
So it seems that Python doesn't get that this is a Function call and instead just calls a Property.
But when i try to call it from C#
Console.WriteLine(example.Call);
Console.WriteLine("----------------------------");
Console.WriteLine(example.Call(1));
This will work:
TryGetMember
-------------------
TryInvokeMember
Has anyone a suggestion how to fix this?
Solution: (edit: calledMethodeName has to be a List, otherwise nested methods wouldn't work)
So thanks to Jeff.
When i design the Dynamic like that:
List<string> calledMethodeNames = new List<string>();
public override bool TryGetMember(GetMemberBinder binder,
out object result)
{
calledMethodeNames.Add(binder.Name);
result = this;
return true;
}
public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
{
//calledMethodeNames last Element has stored the Name of the called methode (remeber to remove it)
result = "TryInvoke";
return true;
}
everything is working fine.
The clue is to return the Object itself as Member, than the object is callable and python calls the TryInvoke (not TryInvokeMember)
But TryInvoke ist called because after returning the object, the object itself is called. So InvokeBinder dont knows the Name of the called methode. So i store it into a variable.
That's the expected behaviour. IronPython uses TryGetMember followed by TryInvoke since the Python language has no concept of invoking a member: Python method calls are always an attribute lookup followed by a call.
The error you're getting is because you're setting result to a string (type str) and strings are not callable. You'll have to set result to either another dynamic object that implements TryInvoke or a delegate.
Based on the Python exception (str is not callable) it looks like IronPython first calls TryGetMember and since that function returns true it will use that object.
The TryGetMember/TryInvokeMember should only return true if they succeeded. For example that means TryGetMember should return true if and only if there actually is a member that matches the binder parameter.
Update: in C# Call(2) is always a method call (I can't think of anything else it could be, please let me know if I'm wrong), so the C# compiler will use TryInvokeMethod. In Python however any object is callable if it has a __call__ method, so Call(2) could either mean execute the method Call or get the member Call and execute __call__ on it.

What is a callback?

What's a callback and how is it implemented in C#?
I just met you,
And this is crazy,
But here's my number (delegate),
So if something happens (event),
Call me, maybe (callback)?
In computer programming, a callback is executable code that is passed as an argument to other code.
—Wikipedia: Callback (computer science)
C# has delegates for that purpose. They are heavily used with events, as an event can automatically invoke a number of attached delegates (event handlers).
A callback is a function that will be called when a process is done executing a specific task.
The usage of a callback is usually in asynchronous logic.
To create a callback in C#, you need to store a function address inside a variable. This is achieved using a delegate or the new lambda semantic Func or Action.
public delegate void WorkCompletedCallBack(string result);
public void DoWork(WorkCompletedCallBack callback)
{
callback("Hello world");
}
public void Test()
{
WorkCompletedCallBack callback = TestCallBack; // Notice that I am referencing a method without its parameter
DoWork(callback);
}
public void TestCallBack(string result)
{
Console.WriteLine(result);
}
In today C#, this could be done using lambda like:
public void DoWork(Action<string> callback)
{
callback("Hello world");
}
public void Test()
{
DoWork((result) => Console.WriteLine(result));
DoWork(Console.WriteLine); // This also works
}
Definition
A callback is executable code that
is passed as an argument to other code.
Implementation
// Parent can Read
public class Parent
{
public string Read(){ /*reads here*/ };
}
// Child need Info
public class Child
{
private string information;
// declare a Delegate
delegate string GetInfo();
// use an instance of the declared Delegate
public GetInfo GetMeInformation;
public void ObtainInfo()
{
// Child will use the Parent capabilities via the Delegate
information = GetMeInformation();
}
}
Usage
Parent Peter = new Parent();
Child Johny = new Child();
// Tell Johny from where to obtain info
Johny.GetMeInformation = Peter.Read;
Johny.ObtainInfo(); // here Johny 'asks' Peter to read
Links
more details for C#.
A callback is a function pointer that you pass in to another function. The function you are calling will 'callback' (execute) the other function when it has completed.
Check out this link.
If you referring to ASP.Net callbacks:
In the default model for ASP.NET Web
pages, the user interacts with a page
and clicks a button or performs some
other action that results in a
postback. The page and its controls
are re-created, the page code runs on
the server, and a new version of the
page is rendered to the browser.
However, in some situations, it is
useful to run server code from the
client without performing a postback.
If the client script in the page is
maintaining some state information
(for example, local variable values),
posting the page and getting a new
copy of it destroys that state.
Additionally, page postbacks introduce
processing overhead that can decrease
performance and force the user to wait
for the page to be processed and
re-created.
To avoid losing client state and not
incur the processing overhead of a
server roundtrip, you can code an
ASP.NET Web page so that it can
perform client callbacks. In a client
callback, a client-script function
sends a request to an ASP.NET Web
page. The Web page runs a modified
version of its normal life cycle. The
page is initiated and its controls and
other members are created, and then a
specially marked method is invoked.
The method performs the processing
that you have coded and then returns a
value to the browser that can be read
by another client script function.
Throughout this process, the page is
live in the browser.
Source: http://msdn.microsoft.com/en-us/library/ms178208.aspx
If you are referring to callbacks in code:
Callbacks are often delegates to methods that are called when the specific operation has completed or performs a sub-action. You'll often find them in asynchronous operations. It is a programming principle that you can find in almost every coding language.
More info here: http://msdn.microsoft.com/en-us/library/ms173172.aspx
Dedication to LightStriker:
Sample Code:
class CallBackExample
{
public delegate void MyNumber();
public static void CallMeBack()
{
Console.WriteLine("He/She is calling you. Pick your phone!:)");
Console.Read();
}
public static void MetYourCrush(MyNumber number)
{
int j;
Console.WriteLine("is she/he interested 0/1?:");
var i = Console.ReadLine();
if (int.TryParse(i, out j))
{
var interested = (j == 0) ? false : true;
if (interested)//event
{
//call his/her number
number();
}
else
{
Console.WriteLine("Nothing happened! :(");
Console.Read();
}
}
}
static void Main(string[] args)
{
MyNumber number = Program.CallMeBack;
Console.WriteLine("You have just met your crush and given your number");
MetYourCrush(number);
Console.Read();
Console.Read();
}
}
Code Explanation:
I created the code to implement the funny explanation provided by LightStriker in the above one of the replies. We are passing delegate (number) to a method (MetYourCrush). If the Interested (event) occurs in the method (MetYourCrush) then it will call the delegate (number) which was holding the reference of CallMeBack method. So, the CallMeBack method will be called. Basically, we are passing delegate to call the callback method.
Please let me know if you have any questions.
Probably not the dictionary definition, but a callback usually refers to a function, which is external to a particular object, being stored and then called upon a specific event.
An example might be when a UI button is created, it stores a reference to a function which performs an action. The action is handled by a different part of the code but when the button is pressed, the callback is called and this invokes the action to perform.
C#, rather than use the term 'callback' uses 'events' and 'delegates' and you can find out more about delegates here.
callback work steps:
1) we have to implement ICallbackEventHandler Interface
2) Register the client script :
String cbReference = Page.ClientScript.GetCallbackEventReference(this, "arg", "ReceiveServerData", "context");
String callbackScript = "function UseCallBack(arg, context)" + "{ " + cbReference + ";}";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "UseCallBack", callbackScript, true);
1) from UI call Onclient click call javascript function for EX:- builpopup(p1,p2,p3...)
var finalfield= p1,p2,p3;
UseCallBack(finalfield, ""); data from the client passed to server side by using UseCallBack
2) public void RaiseCallbackEvent(string eventArgument) In eventArgument we get the passed data
//do some server side operation and passed to "callbackResult"
3) GetCallbackResult() // using this method data will be passed to client(ReceiveServerData() function) side
callbackResult
4) Get the data at client side:
ReceiveServerData(text) , in text server response , we wil get.
A callback is a function passed as an argument to another function. This technique allows a function to invoke the parameter function argument and even to pass a value back to the caller. A callback function can be designed to run before/after the function has finished and can pass a value.
It is a kind of construct where you call a long running function and ask him to call you back once it has finished with can return a parameter result to the caller.
It's like someone calls you in the middle of your work asking for status and you say "you know what give me 5 min and i will call you back" and at the end you call him to update. If you are a function the caller just added and passed another function that you invoked at the end. This can simpley be written in C# as:
public void VinodSrivastav(Action statusUpdate){
//i am still here working..working
//i have finished, calling you
statusUpdate();
}
//invokes
stackoverflow.VinodSrivastav((cam) => {
Console.Write("Is it finished");
});
The one simple example is the iterator function where the return will be multiple times, one can argue that we have yield for it:
public void IntreationLoop(int min, int max,Action<int> Callback)
{
for(int i = min;i<= max;i++)
Callback(i);
}
//call
IntreationLoop(5,50,(x) => { Console.Write(x); }); //will print 5-50 numbers
In the code above the function return type is void but it has an Action<int> callback which is called and sends each item from the loop to the caller.
The same thing can be done with if..else or try..catch block as:
public void TryCatch(Action tryFor,Action catchIt)
{
try{
tryFor();
}
catch(Exception ex)
{
Console.WriteLine($"[{ex.HResult}] {ex.Message}");
catchIt();
}
}
And call it as:
TryCatch(()=>{
int r = 44;
Console.WriteLine("Throwing Exception");
throw new Exception("something is wrong here");
}, ()=>{
Console.WriteLine("It was a mistake, will not try again");
});
In 2022 we have Func & Action doing the same, please see the demo code below which shows how this can be be used:
void Main()
{
var demo = new CallbackDemo();
demo.DoWork(()=> { Console.WriteLine("I have finished the work"); });
demo.DoWork((r)=> { Console.WriteLine($"I have finished the work here is the result {r}"); });
demo.DoWork(()=> { Console.WriteLine($"This is passed with func"); return 5;});
demo.DoWork((f)=> { Console.WriteLine($"This is passed with func and result is {f}"); return 10;});
}
// Define other methods and classes here
public class CallbackDemo
{
public void DoWork(Action actionNoParameter)
{
int a = 5;
int b = 10;
//i will do th maths and call you back
int result = a + b;
//callback
actionNoParameter(); //execute
Console.WriteLine($"[The Actual Result is {result}]");
}
public void DoWork(Action<int> actionWithParameter)
{
int a = 5;
int b = 10;
//i will do th maths and call you back
int result = a + b;
//callback
actionWithParameter(result); //execute
Console.WriteLine($"[The Actual Result is {result}]");
}
public void DoWork(Func<int> funcWithReturn)
{
int a = 5;
int b = 10;
//i will do th maths and call you back
int result = a + b;
//callback
int c = funcWithReturn(); //execute
result += c;
Console.WriteLine($"[The Actual Result is {result}]");
}
public void DoWork(Func<int,int> funcWithParameter)
{
int a = 5;
int b = 10;
//i will do th maths and call you back
int result = a + b;
//callback
result += funcWithParameter(result); //execute
Console.WriteLine($"[The Actual Result is {result}]");
}
}

Categories