I have web page which is using AjaxControlToolkit:AutoCompleteExtener on some TextBox.
This extender requires service method, from which it will get data to display:
[System.Web.Services.WebMethodAttribute(), System.Web.Script.Services.ScriptMethodAttribute()]
public static string[] GetCompletionList2(string prefixText, int count, string contextKey)
{
return DatabaseSearch.GetUnits().GetSymbolCompletion(prefixText, organizationToSearch);
}
In this method I use some argument = organizationToSearch. But I don't want this argument to be static ! And since the method is static I don't know what to do. If I remove the 'static' keyword from method definition it won't work... And I really don't want change organizationToSearch to static either!
Please help.
It must be static 'cause you're not in the execution of your page. When you're calling an AjaxMethod, your page (webforms) doesn't exists.
As already mentioned, you are in a completly new request and not in the execution of your page anymore (your page has already rendered by this stage)..
You will need to transfer and parameters out and pass them back into the static method..
Related
Could somebody please let me know how static methods work in regard to calling C# methods from JavaScript using JS interop?
If I have a static method in the code section of a component that references objects in that component, and there are multiple instances of that component on a page, will all instances be affected by the method call?
Or even worse, will this act as a Singleton on my server causing updates to every single client instance of that component?
I'm currently developing an audio recording system that cycles through phrases marked in text, and whenever JavaScript detects 5 frames of silence in the media stream, I want to call a C# method that will highlight the next section of text by changing its CSS class.
If you want to change some styles in your component, you definitely not want to use a static method. Because a static method could not interact with the instance of the component - as you cannot use the this keyword in a static method.
What I think you want to do is first, in C# side, create a classic method in your component C# code. For example create:
public void ChangeStyle()
{
this.ClassToDisplay = DoSomeManipulation();
}
Then, JS will need the instance of the the component. So you can do something like that: (I use the OnAfterRenderAsync because it is shown in Microsoft documentation, but the goal is to do it once)
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
DotNetObjectReference<MyComponent>? dotNetHelper = DotNetObjectReference.Create(this);
await JS.InvokeVoidAsync("JSFile.setDotNetHelper", dotNetHelper);
}
}
Then in JS side, you will need the setDotNetHelper method, with the following content:
class JSFile
{
static dotNetHelper;
static setDotNetHelper(value)
{
JSFile.dotNetHelper = value;
}
}
Now you are ready, you can call whenever you want the ChangeStyle method of your component. To do so, use this instruction in JS:
await dotNetHelper.invokeMethodAsync('ChangeStyle');
Et voilĂ . I am available for clarifications or questions, have a good one!
// Dylan
I am in need of calling a non-static method in the active(current) asp page that the user is on by using a static WebMethod. How can I do this?
Both of these methods are within the ASP page's cs file.
public void NormalMethod()
{
txtFindingNum.Text = "Ajax is da bomb";
}
[WebMethod]
public static void MyWebMethod()
{
// This is the part I need help with...
DoIt();
}
You can't do it. It doesn't even make sense.
The instance methods of the page are about a specific instance of the page. When you're in the static web method (page method), there is no instance of the page.
If you could call the instance method from the web method, that would mean that the instance method should be a static method. Can you just add static to that method and have it still work? If not, then it depends on the particular instance of the page, and you simply can't call it when there is no instance.
Note that a page instance exists only during the HTTP request that it is serving. By the time your client-side code is calling the web service, that HTTP request is already over, and the page instance is gone.
You can't do it, but the txtFindingNum.Text field is input, and you can change it in client side (it also keep the change in the server after postback), with js or jq, like this:
$("#<%=txtFindingNum.ClientID%>").val("Ajax is da bomb");
Sorry for stupid question,
I just want to pass a JOSN string to the webpage in the webbrowser from my VB/C# code,
and can the javascript in webpage call the VB/C# method through some interface ?
Just like android javascript interface, many thanks
If I understand you correctly,
webBrowser2.ObjectForScripting = new ScriptClass();
webBrowser2.DocumentText = "<html><script>window.external.Test('hello')</script></html>";
[System.Runtime.InteropServices.ComVisibleAttribute(true)]
public class ScriptClass
{
public void Test(string msg)
{
MessageBox.Show(msg);
}
}
So you're using a WebBrowser control and need to call a JavaScript method within the page it shows? Yeah, you can do this. It's not on the WebBrowser itself, but the HtmlDocument object, exposed by the WebBrowser's Document property, has an InvokeScript() method group, which will allow you to programatically invoke any ECMAScript-compliant method within the DOM of the page, optionally passing a series of parameters as an Object array.
That, in turn, can be used to trigger a call from JavaScript to a JSON web service (which you expose in your main CLR program, and told the page about by passing it the info via InvokeScript()). This is basic JSON/AJAX client-server scripting, all wrapped up into a single program talking to itself. It's not the most efficient way to get things done, but if you already have these layers that get the job done, and just want to release a self-contained app, it works.
I'm trying to do something that I thought would be easy but can't figure out how to write to a label inside my stating function.
public static void StartProcessing(object data)
{
lblError.Text = "Blah Blah"
}
I get the error "An object reference is required for the non-static field, method, or property..."
So I tried creating a new instance of the label and adding it to a new instance of a control (Panel) but the lblError isn't getting displayed
public static void StartProcessing(object data)
{
Panel Panel1 = new Panel();
Label lblError= new Label();
Panel1.Controls.Add(lblError);
lblError.Visible = true;
lblError.Text = "Blah Blah";
}
there must be an easy way to do this? Which i've overlooked..
The function is getting called as follows: If I change the above to not be static I get an error message on the second line below saying the same "An object reference is required for the non-static field, method, or property..." When this function isn't static?
public object LaunchNewProcess(object data)
{
ThreadPool.QueueUserWorkItem(
new WaitCallback(ProcessStatuses.StartProcessing),
new object[] {newProcess, allProcesses}
);
Pass the label to your static function when you call it:
public static void StartProcessing(object data, Label lblError)
{
lblError.Text = "Blah Blah"
}
Static functions don't have access to controls because the controls belong to the instance of the page (class).
Static means that all instances of a class share the same function or variable. So, an instance of a class has access to a static variable or function. However, since a static is not "aware" of any instances of the class, it cannot access the members of an instance. In fact, a static method or variable does not even require any instance of the class to exist, so how could it?
Removing the static key word from your function will also work, as others have mentioned, but I'm assuming you made it static for a reason.
EDIT
Alright, this is more complex.
So, you have some class that launches a bunch of threads, and you want it to display to the user if something went wrong? Well, your current approach is flawed because you cannot access controls of a page without the instance of the page. Also, I am not sure how this approach would fit within the page lifecycle.
Your best approach (sorry for lack of code, it's going to depend a lot on your implementation) could be something like this:
//do this before you start spawning threads
List<bool> successes = new List<bool>();
ThreadPool.QueueUserWorkItem(
new WaitCallback(ProcessStatuses.StartProcessing),
new object[] {newProcess, allProcesses, successes}
);
//you MUST wait for all your threads to complete before proceeding!
if(successes.Any(s => !s))
{
//update your error label
}
public static void StartProcessing(object data, Label lblError)
{
var dataArray = (object[3]) data;
//if there is an error
dataArray[2] = false;
}
What you want to do is actually quite difficult.
You want to create a page, start an asynchronous task, send the page to the user, and then update content on the page after the asynchronous job finishes.
The problem is that by the time the asynchronous task finishes the page has already been sent, and based on the way HTTP works once you've sent your response you're done; there's not more communicating with the client for you. You need to wait for the client to send another request if you want to update them.
This means that you need to have JavaScript code that is constantly polling the server basically asking, "Are you done yet, are you done yet, are you done yet?" until eventually the server says, "Yes, here's something to display on the page".
Fortunately, you don't need to start from scratch. Here you'll find an example by Microsoft that does all of this; you can modify it to suit your needs. It's also worth mentioning that in addition to being non-trivial to program, it also consumes a lot of resources to constantly poll the server, so be sure you really need to do this.
Option 2 is to just not start the other tasks in new threads, and execute the code serially before the page is ever returned to the user. They'll be staring at a blank screen for a while, but it'll be MUCH easier to program. The one downsize to keep an eye on here is on timeouts if the task is REALLY long running.
Say that I have an ASP.NET page with a Label control and the following static class which executes a scheduled job:
public static class Job
{
// The Execute method is called by a scheduler and must therefore
// have this exact signature (i.e. it cannot take any paramters).
public static string Execute()
{
// Do work
}
}
When the job is done, the execute method should update the value of the Label control on the page.
I've done some research and the only way seems to be to use HttpContext.Current.CurrentHandler. However, this is undesirable for me since it can potentially return null.
Since the Execute method cannot take any parameters (see comment), passing the Page instance as an argument is not an option.
Is there any other way to update the control from the static class?
NOTE: the Execute method must be static because I'm creating an EPiServer scheduled job, which requires a static Execute method (that doesn't take any parameters).
If the job is not executed synchronously (or even if it is), I think that you may want to consider the order of control.
What I suggest in a case like this is a structure similar to the following:
1) The web page issues the request for the job
2) Somewhere, a unique reference to the job is created and stored (such as GUID or an identity column in a database table)
3) The job is executed asynchronously by code-behind and then the unique identifier is returned to the web page.
4) The web page, on startup, initiates a javascript method (using window.timeout, for example) that on a regular basis, issues an ajax query to the web server to check on the status of the job.
5) When the job is complete, it updates the global reference with the appropriate information.
6) When the javascript sees that the job is complete, it updates the label.
This process allows the user to carry on with other work if necessary and not have to worry about timeouts due to long postback times, etc.
For your specific scenario, you could add a GUID property to the Job class (which would be passed back to the client).
When Execute is complete, you could add this GUID to a static collection (i.e. Dictionary<Guid, string>) which the ajax request would check (the string value could store status or completion information).
When the ajax request fires, it would check this static collection and, when it finds its job, remove it and return the value to the caller.
You can create a static property that is updated by your Execute method and bind the Text property of the Label to the static property in the aspx's OnInit method, Label.Text = Job.StaticProperty, if you need a somewhat dynamic response you could use the Ajax Timer Control to call a method on the aspx page to return the same static value from the aspx Page.
public static class Job
{
public static string UpdatedValue { get; private set; } // Or whatever the property is you wish to expose.
// The Execute method is called by a scheduler and must therefore
// have this exact signature (i.e. it cannot take any paramters).
public static string Execute()
{
// Do work
Job.UpdatedValue = "Execute Completed";
}
}
protected override OnInit(EventArgs e)
{
base.OnInit(e);
this.TextLabel.Text = Job.UpdatedValue;
}
// Using MSDN basic sample
protected void Timer1_Tick(object sender, EventArgs e)
{
this.TextLabel.Text = Job.UpdatedValue;
}
Try with a global variable (static) or raise an event from Execute() method.