I understand this may be an elementary question, but I'm new to Asp.net webforms, so please bear with me.
I have a lengthy form on a page that I would like to autosave when users type in a field, or make a selection. The problem is, all I've been able to find online is autosaves that work on a timer. I'd prefer that it saves as the user makes their edits. Also I would like just the individual form element being edited to be sent to the server to avoid sending the entire page back each time.
I've read that I should use a webservice to accomplish this, but since I want to autosave individual items and not the whole form on a timer, how would I set up a webservice to accomplish this? I'm new to webservices I'd like to know what to read up on. Any links are appreciated.
Also, how is the autosave functionality effected when using asp.net validation controls? I've looked around but can't tell if the entire page needs to be valid to make a trip to the server, or if just a single valid item can be sent itself.
Thanks for any help!
If you set AutoPostBack=True on the field, and you add an OnChange event for it (this will vary depending on the type of field the user is interacting with), you can execute a save. Don't call Page.Validate in the methods where you're doing these updates. Call it when you hit the Submit button.
This could cause a LOT of round trips to the server, and it's a lot of code to write and debug.
The Timer approach is one call to one method on a repetitive basis. If you can I'd recommend going with a timer, but sometimes that's not an option.
Generally speaking this is what you'll want to setup on the client-side. Ideally, you will end up with lots of tiny requests which do not require much power on the back-end. This however depends on lots of variables including the database engine you're using.
$(document).ready(function () {
$("input").blur(OnFieldChanged);
});
function OnFieldChanged()
{
var $this = $(this);
var isValid = ValidateField($this);
if (isValid)
{
SaveField($this);
}
}
function SaveField($field)
{
if ($this.val() === $this.prop("oldVal")) return;
var data = {
id: $("idfield").val()
};
data[$field.attr("id")] = $field.val();
$.post({..}).done(function() {
NotifySaved($this);
$this.prop("oldVal", $this.val());
});
}
function ValidateField($field)
{
// Validate the field with your method of choice, manually call Microsoft's client-side validate function or switch to jquery validate.
return true;
}
I have an asp form in which on_button_click a thread a being executed following a finite number of loops. So I want after every single loop completion a postback should occur. So would you please help me out to find the way of doing post back by coding after single loop completion.
Thread tt = new Thread (mainProcess);
Button1_Click() {
tt.start();
}
void mainprocess()
{
while(true)
{
//do this
if(Condition)
break;
//do postback
}
}
From the moment you fire a thread on code behind, the thread did not have any control/connection with the page to make some how a postback or refresh.
You need to redesign your page some other way. One possible is to use ajax to make your call to the page and get the results when they are ready, or to make using ajax time to time call to code behind and see if the data are ready to gets them. Or make every 20 seconds a page refresh and again check if the loop has ended and get and show the data.
A common task I have to do for a site I work on is the following:
Download data from some third-party API
Process the data in some fashion
Display the results on the page
I was initially using WebClient.DownloadStringAsync and doing my processing on the result. However I was finding that DownloadStringAsync was not respecting the AsyncTimeout parameter, which I sort of expected once I did a little reading about how this works.
I ended up adapting the code from the example on how to use PageAsyncTask to use DownloadString() there - please note, it's the synchronous version. This is probably okay, because the task is now asynchronous. The tasks now properly time out and I can get the data by PreRender() time - and I can easily genericize this and put it on any page I need this functionality.
However I'm just worried it's not 'clean'. The page isn't notified when the task is done like the DownloadStringAsync method would do - I just have to scoop the results (stored in a field in the class) up at the end in my PreRender event.
Is there any way to get the Webclient's Async methods to work with RegisterPageTask, or is a helper class the best I can do?
Notes: No MVC - this is vanilla asp.net 4.0.
If you want an event handler on your Page called when the async task completes, you need only hook one up. To expand on the MSDN "how to" article you linked:
Modify the "SlowTask" class to include an event, like - public event EventHandler Finished;
Call that EventHandler in the "OnEnd" method, like - if (Finished != null)
{
Finished(this, EventArgs.Empty);
}
Register an event handler in your page for SlowTask.Finished, like - mytask.Finished += new EventHandler(mytask_Finished);
Regarding ExecuteRegisteredAsyncTasks() being a blocking call, that's based only on my experience. It's not documented explicitly as such in the MSDN - http://msdn.microsoft.com/en-us/library/system.web.ui.page.executeregisteredasynctasks.aspx
That said, it wouldn't be all that practical for it be anything BUT a blocking call, given that it doesn't return a WaitHandle or similar. If it didn't block the pipeline, the Page would render and be returned to the client before the async task(s) completed, making it a little difficult to get the results of the task back to the client.
I am using Flex and Actionscript 3, along with Webservices, rpc and a callResponder. I want to be able to, for example, say:
loadData1(); // Loads webservice data 1
loadData2(); // Loads webservice data 2
loadData3(); // Loads webservice data 3
However, Actionscript 3 works with async events, so for every call you need to wait for the ResultEvent to trigger when it is done. So, I might want to do the next request every time an event is done. However, I am afraid that threading issues might arise, and some events might not happen at all. I don't think I'm doing a good job of explaining, so I will try to show some code:
private var service:Service1;
var cp:CallResponder = new CallResponder();
public function Webservice()
{
cp.addEventListener(ResultEvent.RESULT, webcalldone);
service = new Service1();
}
public function doWebserviceCall()
{
// Check if already doing call, otherwise do this:
cp.token = service.WebserviceTest_1("test");
}
protected function webcalldone(event:ResultEvent):void
{
// Get the result
var result:String = cp.lastResult as String;
// Check if other calls need to be done, do those
}
Now, I could ofcourse save the actions in an arraylist, but whose to say that the addToArrayList and the check if other calls are available do not mess eachother up, or just miss each other, thereby halting execution? Is there something like a volatile Arraylist? Or is there a completely different, but better solution for this problem?
Use an AsyncToken to keep track of which call the returned data was for http://flexdiary.blogspot.com/2008/11/more-thoughts-on-remoting.html
When I want to store data in an async manor I put it in an array and make a function that will "pop" the element as I send it off.
This function will be called on complete and on error events.
Yes I know there could be an issue with the server and data lost but oh well. That can also be handled
Events will always fire however, it may not be a complete event that gets fired but could be an error event.
Once the array is empty the function is done.
Maybe I'm slow, but I just don't get why you would ever use an event that is not derived from an actual action (like clicking). Why go through the rigamarole of creating delegates and events when you can just call a method? It seems like when you create an event, all you're doing is creating a way for the caller to go through some complicated process to call a simple method. And the caller has to raise the event themselves! I don't get it.
Or maybe I'm just not grasping the concept. I get the need for events like OnClick and interactions with controls, but what about for classes? I tried to implement events for a class of mine, say, when the source of an item changed, but quickly realized that there was no point since I could just call a method whenever I wanted to perform a certain action instead of creating an event, raising an event, and writing an event handler. Plus, I can reuse my method, whereas I can't necessarily reuse my event handler.
Someone set me straight please. I feel like I'm just wrong here, and I want to be corrected. The last question I asked didn't really garner any sort of helpful answer.
Thanks.
I've always like the Radio Station metaphor.
When a radio station wants to broadcast something, it just sends it out. It doesn't need to know if there is actually anybody out there listening. Your radio is able to register itself with the radio station (by tuning in with the dial), and all radio station broadcasts (events in our little metaphor) are received by the radio who translates them into sound.
Without this registration (or event) mechanism. The radio station would have to contact each and every radio in turn and ask if it wanted the broadcast, if your radio said yes, then send the signal to it directly.
Your code may follow a very similar paradigm, where one class performs an action, but that class may not know, or may not want to know who will care about, or act on that action taking place. So it provides a way for any object to register or unregister itself for notification that the action has taken place.
Events in general can be a good way to decouple the listener/observer from the caller/raiser.
Consider the button. When someone clicks on the button, the click event fires. Does the listener of the button click care what the button looks like, does, or anything of that nature? Most likely not. It only cares that the click action has taken place, and it now goes and does something.
The same thing can be applied to anything that needs to same isolation/decoupling. It doesn't have to be UI driven, it can just be a logic separation that needs to take place.
Using events has the advantage of separating the class(es) which handle events from the classes which raise them (a la the Observer Pattern). While this is useful for Model View Controller (the button which raises click events is orthogonal to the class that handles them), it is also useful any time you want to make it easy to (whether at runtime or not) to keep the class which handles the events separated from the class which raises them (allowing you to change or replace them).
Basically, the whole point is to keep the classes which handle the events separated from the classes which raise them. Unnecessary coupling is bad, since it makes code maintainence much more difficult (since a change in one place in code will require changes in any pieces of code coupled to it).
Edit:
The majority of the event-handling you will do in Asp.Net will probably be to handle events from classes that are provided to you. Because such classes use event-handling, it makes it easy for you to interface with them. Often, the event will also serve to allow you to interact with the object that raised the event. For example, the databound controls usually raise an event right before they connect to the database, which you can handle in order to use runtime information to alter the arguments being passed to the stored procedure talking to your database, e.g. if the query string provides a page number parameter and the stored procedure has a page number argument.
Events can be used like messages to notify that something has happened, and an consumer can react to them in an appropriate way, so different components are loosely coupled. There's lots of things you can use events for, one example is auditing things that are happening in the system; the auditing component can consume various events and write out to a log when they are fired.
The things that you seem to be missing are two:
There are happenings in software that can take an arbitrary amount of time not only due to waiting for user input (async i/o, database queries and so on). If you launch an async i/o request you would want to subscribe to the event notifying you when the reading is done so you can do something with the data. This idea is generalized in .NET's BackgroundWorker class, which allows you to do heavy tasks in the background (another thread) and receive notifications in the calling thread when it's done.
There are happenings in software that are used by multiple clients not only a single one. For instance, if you have a plugin architecture where your main code offers hooks to plugin code, you could either do something like
foreach (Plugin p in getAvaliablePlugins()) { p.hook1(); }
in every hook all over your code which reduces flexibility (p cannot decide what to do, and has to provide the hook1 method publicly) or you can just
raiseEvent(hook1,this)
where all registered plugins can execute their code because they receive the event, letting them do their job as they see fit.
I think you're confusing ASP.NET's (mis)use of events, with plain ol' event handling.
We'll start with plain ol' event handling. Events is a (yet another) way of fulfilling the "Open [for extension]/Closed [for modification]" principle. When your class exposes an event, it allows external classes (perhaps classes that aren't even thought of, much less built, yet) to have code run by your class. That's a pretty powerful extension mechanism, and it doesn't require your class to be modified in any way.
As an example, consider a web server, that knows how to accept a request, but doesn't know how to process a file (I'll use bi-directional events here, where the handler can pass data back to the event source. Some would argue that's not kosher, but it's the first example that came to mind):
class WebServer {
public event EventHandler<RequestReceivedEventArgs> RequestReceived;
void ReceiveRequest() {
// lots of uninteresting network code here
var e = new RequestReceivedEventArgs();
e.Request = ReadRequest();
OnRequestReceived(e);
WriteResponse(e.Response);
}
void OnRequestReceived(RequestReceivedEventArgs e) {
var h = RequestReceived;
if (h != null) h(e);
}
}
Without changing the source code of that class - maybe it's in a 3rd party library - I can add a class that knows how to read a file from disk:
class FileRequestProcessor {
void WebServer_RequestReceived(object sender, EventArgs e) {
e.Response = File.ReadAllText(e.Request);
}
}
Or, maybe an ASP.NET compiler:
class AspNetRequestProcessor {
void WebServer_RequestReceived(object sender, EventArgs e) {
var p = Compile(e.Request);
e.Response = p.Render();
}
}
Or, maybe I'm just interested in knowing that an event happened, without affecting it at all. Say, for logging:
class LogRequestProcessor {
void WebServer_RequestReceived(object sender, EventArgs e) {
File.WriteAllText("log.txt", e.Request);
}
}
All of these classes are basically "injecting" code in the middle of WebServer.OnRequestReceived.
Now, for the ugly part. ASP.NET has this annoying little habit of having you write event handlers to handle your own events. So, the class that you're inheriting from (System.Web.UI.Page) has an event called Load:
abstract class Page {
public event EventHandler Load;
virtual void OnLoad(EventArgs e) {
var h = this.Load;
if (h != null) h(e);
}
}
and you want to run code when the page is loaded. Following the Open/Closed Principle, we can either inherit and override:
class MyPage : Page {
override void OnLoad(EventArgs e) {
base.OnLoad(e);
Response.Write("Hello World!");
}
}
or use eventing:
class MyPage : Page {
MyPage() {
this.Load += Page_Load;
}
void Page_Load(EventArgs e) {
Response.Write("Hello World!");
}
}
For some reason, Visual Studio and ASP.NET prefer the eventing approach. I suppose you can then have multiple handlers for the Load event, and they would all get run auto-magically - but I never see anyone doing that. Personally, I prefer the override approach - I think it's a bit clearer and you'll never have the question of "why am I subscribed to my own events?".