WPF Browser throws error - c#

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?

Related

Access to modified closure: ReSharper

I created a library that handles database access. I recently added transaction handling; however, I came across a small issue. To outline this, I wrote this sample for demonstration purposes:
class Program
{
static void Main(string[] args)
{
String data = null;
DoAction(ref data, () =>
{
Console.WriteLine(data);
});
Console.ReadLine();
}
private static void DoAction(ref String data, Action action)
{
if (data == null)
data = "Initialized Data";
action();
}
}
I get "Access to modified closure" underline on the following code line for the 'data' variable:
Console.WriteLine(data);
I understand that the modification of the ref data variable can cause issues (e.g. when running foreach loops). However, in the following case, I don't see this to happen.
Here is another version with a loop changing the variable further - the output is as expected:
class Program
{
static void Main(string[] args)
{
String data = null;
for (var i = 0; i < 10; i++)
DoAction(ref data, () =>
{
Console.WriteLine(data);
});
Console.ReadLine();
}
private static void DoAction(ref String data, Action action)
{
if (data == null)
data = "Initialized Data";
else
data += "|";
action();
}
}
ReSharper offers me to create a local variable, but I explicitly want to use the created string from the DoAction() method. If I would accept ReSharpers approach, it actually would break the code. Is there any other way to solve this problem? I'd like to use this Action approach, but I don't want ReSharper to complain about it either (and possibly not disable ReSharpers inspection).
Any suggestions?
I would suggest avoid using a ref parameter for this in the first place - it seems needlessly complicated to me. I'd rewrite DoAction as:
static string DoAction(string data, Action<string> action)
{
data = data == null ? "Initialized Data" : data + "|";
action(data);
return data;
}
Then you can have:
data = DoAction(data, Console.WriteLine);
or if you want to use a lambda expression:
data = DoAction(data, txt => Console.WriteLine(txt));
You can make DoAction a void method if you don't actually need the result afterwards. (It's not clear why you need the result to be returned and a delegate to execute in DoAction, but presumably that makes more sense in your wider context.)
In case you feel certain that the warning is not appropriate, there is the InstantHandleAttribute which is documented as:
Tells code analysis engine if the parameter is completely handled
when the invoked method is on stack. If the parameter is a delegate,
indicates that delegate is executed while the method is executed.
If the parameter is an enumerable, indicates that it is enumerated
while the method is executed.
I think is exactly what you want.
You can get the attribute from the JetBrains.Annotations package or alternatively as copy-paste from ReSharper options.

Asp.net Ajax pageMethods not triggering success event handler

I have asp.net ajax page method like following,
[WebMethod]
public static string UnAuthVote(string vf)
{
return "";
}
and I am calling it like this,
PageMethods.UnAuthVote("alikhan", success1, error);
And my success1 and error method written like following,
function success1(response) {alert("");
return false;
}
function error(error) {alert("error");return false; }
The problem is it's invoking error event. Why my code is not calling pagemethod's success event.
help
Thanks
Well, I was using url rewriting. So that's why my pagemethods was not working.
Well
I set set_Path property like following
PageMethods.set_path("Auth/profile.aspx")
Now it's working as it should
It helps if you show the actual error, for example:
function success1(response)
{
alert(response);
}
function error(error)
{
alert(error);
}
You can also use a debugger or developer tools to identify the problem. The error may show on the Console tab. The debugger will allow you to troubleshoot more efficiently than editing code to show alerts but I understand that in some cases this is preferable. You can also write to the console by doing:
function success1(response)
{
if(window.console) console.log(response);
}
function error(error)
{
if(window.console) console.log(error);
}
The benefit of this is it doesn't get in the user's way, and is only visible if the console is open. Checking for window.console avoids exceptions thrown from logging to console if it is unavailable.
If you don't know the properties of the return objects you can iterate through them like this:
function error(error)
{
var output = [];
for(key in error)
{
output[output.length] = key.toString() + " = " + error[key];
}
alert(output.join('\n'));
}

Is it possible to mark a C# or VB function for output as Javascript in ASP.NET MVC4?

I have an HtmlHelper extension method that takes javascript callback functions as parameters.. for example:
#Html.SomethingCool("containerName", "jsCallbackFunction")
<script type="javascript">
function jsCallbackFunction(e, i) {
alert(e.target.name + ' / ' + i);
}
</script>
As you can see, the javascript callback function name is passed to the HtmlHelper extension method. This causes the developer to have to refer back to the documentation to figure out what parameters the jsCallbackFunction function needs.
I would much rather prefer something like this:
#Html.SomethingCool("containerName", New SomethingCoolCallbackDelegate(Address Of jsCallbackFunction))
<OutputAsJavascript>
Private Sub jsCallbackFunction(e, i)
' SOMETHING goes here. some kind of html dom calls or ???
End Sub
The SomethingCoolCallbackDelegate would provide the code contract for the target function.
Then the compiler would compile the jsCallbackFunction as javascript on the MVC page.
Is there anything like this built into .NET 4 / ASP.NET MVC 4 / Razor 2 ? Or any other technology that can achieve something similar?
Examples are in VB, but solutions in C# are quite acceptable as well.
Clarification:
#gideon: notice that jsCallbackFunction takes two parameters e, and i. However, the HtmlHelper extension method simply asks for a string (the name of the javascript callback function) and does not indicate what parameters this function might take. The problem I am trying to solve is two-fold.
First, the missing parameter hints. A .NET delegate type passed in place of the "javascript callback name" string would accomplish this. I am open to other solutions to accomplish this. I am aware of XML comments. They are not really a solution.
Second, trying to keep the page programmer working in a single language. Switching between javascript and VB (or js and C#) requires (for me at least) an expensive context switch. My brain doesn't make the transition quickly. Keeping me working in VB or C# is more productive and cost effective. So being able to write a function in a .NET language and have it compiled to javascript, in the context of an ASP.NET MVC/razor view, is what I am after here.
#TyreeJackson: SomethingCool is an HtmlHelper extension method that I would write that outputs html and javascript. Part of the javascript output needs to call into a user(programmer)-supplied function to make some decisions. Think of it similar to the success or failure function you supply to an ajax call.
While I can't give you a full transpiler/compiler option since that would be an enormous amount of work, I can suggest the following to assist with the intellisense support and emitting of the functions and calls.
Here is the infrastructure code. You would need to complete the getArgumentLiteral and getConstantFromArgument functions to handle other cases you come up with, but this is a decent starting point.
public abstract class JavascriptFunction<TFunction, TDelegate> where TFunction : JavascriptFunction<TFunction, TDelegate>, new()
{
private static TFunction instance = new TFunction();
private static string name = typeof(TFunction).Name;
private string functionBody;
protected JavascriptFunction(string functionBody) { this.functionBody = functionBody; }
public static string Call(Expression<Action<TDelegate>> func)
{
return instance.EmitFunctionCall(func);
}
public static string EmitFunction()
{
return "function " + name + "(" + extractParameterNames() + ")\r\n{\r\n " + instance.functionBody.Replace("\n", "\n ") + "\r\n}\r\n";
}
private string EmitFunctionCall(Expression<Action<TDelegate>> func)
{
return name + "(" + this.extractArgumentValues(((InvocationExpression) func.Body).Arguments) + ");";
}
private string extractArgumentValues(System.Collections.ObjectModel.ReadOnlyCollection<Expression> arguments)
{
System.Text.StringBuilder returnString = new System.Text.StringBuilder();
string commaOrBlank = "";
foreach(var argument in arguments)
{
returnString.Append(commaOrBlank + this.getArgumentLiteral(argument));
commaOrBlank = ", ";
}
return returnString.ToString();
}
private string getArgumentLiteral(Expression argument)
{
if (argument.NodeType == ExpressionType.Constant) return this.getConstantFromArgument((ConstantExpression) argument);
else return argument.ToString();
}
private string getConstantFromArgument(ConstantExpression constantExpression)
{
if (constantExpression.Type == typeof(String)) return "'" + constantExpression.Value.ToString().Replace("'", "\\'") + "'";
if (constantExpression.Type == typeof(Boolean)) return constantExpression.Value.ToString().ToLower();
return constantExpression.Value.ToString();
}
private static string extractParameterNames()
{
System.Text.StringBuilder returnString = new System.Text.StringBuilder();
string commaOrBlank = "";
MethodInfo method = typeof(TDelegate).GetMethod("Invoke");
foreach (ParameterInfo param in method.GetParameters())
{
returnString.Append(commaOrBlank + param.Name);
commaOrBlank = ", ";
}
return returnString.ToString();
}
}
public abstract class CoreJSFunction<TFunction, TDelegate> : JavascriptFunction<TFunction, TDelegate>
where TFunction : CoreJSFunction<TFunction, TDelegate>, new()
{
protected CoreJSFunction() : base(null) {}
}
Here is an example of a standard function support wrapper:
public class alert : CoreJSFunction<alert, alert.signature>
{
public delegate void signature(string message);
}
Here are a couple of example Javascript function support wrappers:
public class hello : JavascriptFunction<hello, hello.signature>
{
public delegate void signature(string world, bool goodByeToo);
public hello() : base(#"return 'Hello ' + world + (goodByeToo ? '. And good bye too!' : ''") {}
}
public class bye : JavascriptFunction<bye, bye.signature>
{
public delegate void signature(string friends, bool bestOfLuck);
public bye() : base(#"return 'Bye ' + friends + (bestOfLuck ? '. And best of luck!' : ''") {}
}
And here is a console app demonstrating its use:
public class TestJavascriptFunctions
{
static void Main()
{
// TODO: Get javascript functions to emit to the client side somehow instead of writing them to the console
Console.WriteLine(hello.EmitFunction() + bye.EmitFunction());
// TODO: output calls to javascript function to the client side somehow instead of writing them to the console
Console.WriteLine(hello.Call(func=>func("Earth", false)));
Console.WriteLine(bye.Call(func=>func("Jane and John", true)));
Console.WriteLine(alert.Call(func=>func("Hello World!")));
Console.ReadKey();
}
}
And here is the output from the console app:
function hello(world, goodByeToo)
{
return 'Hello ' + world + (goodByeToo ? '. And good bye too!' : ''
}
function bye(friends, bestOfLuck)
{
return 'Bye ' + friends + (bestOfLuck ? '. And best of luck!' : ''
}
hello('Earth', false);
bye('Jane and John', true);
alert('Hello World!');
UPDATE:
You may also want to check out the JSIL. I'm not affiliated with the project and cannot speak to it's stability, accuracy nor efficacy, but it sounds interesting, and may be able to help you.
Here is my SignalR implementation test(please read the comments in the question):
ChatHub Class:
Public Class ChatHub : Inherits Hub
Public Sub MyTest(ByVal message As String)
Clients.All.clientFuncTest("Hello from here, your message is: " + message)
End Sub
End Class
Client Side:
$(function () {
// Reference the auto-generated proxy for the hub.
var chat = $.connection.chatHub;
//reference to Clients.All.clientFuncTest
chat.client.clientFuncTest = function(messageFromServer){
alert(messageFromServer);
}
// Start the connection.
$.connection.hub.start().done(function () {
//Reference to Public Sub MyTest
chat.server.myTest("this is a test");
});
});
This produce the following output in my site:
It's not quite the same thing but WebMethod and PageMethod attributes can help this become much more manageable IMHO.
See also how to call an ASP.NET c# method using javascript
You could also use a WebBrowser control to create your object implementations, then this becomes just like Node.js for the most part.
See also Read Javascript variable from Web Browser control

IE Automation - Calling a client JavaScript **method** from server-side 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

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