Contents tagged with AJAX
I wanted to be able to capture a snapshot and to upload it in AJAX style. Of course, if you know me you can guess I wanted this with ASP.NET Web Forms and client callbacks!
OK, so I came up with this markup:
The properties and events worth notice are:
Width & Height: should be self explanatory;
PictureTaken: a handler for a server-side .NET event that is raised when the picture is sent to the server asynchronously.
startCapture: when called, starts displaying the output of the camera in real time;
stopCapture: pauses the update of the camera;
takeSnapshot: takes a snapshot of the current camera output (as visible on screen) and sends it asynchronously to the server, raising the PictureTaken event.
When the startCapture method is called, the PictureSnapshot control (or, better, its underlying VIDEO tag) starts displaying whatever the camera is pointing to (if we so authorize it).
Here is an example of one of my home walls… yes, I deliberately got out of the way!
OK, enough talk, the code for PictureSnapshot looks like this:
As you can see, it inherits from WebControl. This is the simplest class in ASP.NET that allows me to output the tag I want, and also includes some nice stuff (width, height, style, class, etc). Also, it implements ICallbackEventHandler for the client callback stuff.
You may find it strange that I am setting explicitly the WIDTH and HEIGHT attributes, that is because VIDEO requires it in the tag, not just on the STYLE. In the way, I am removing any CROSSORIGIN, SRC, MUTED, PRELOAD, LOOP, AUTOPLAY, MEDIAGROUP, POSTER and CONTROLS attributes that may be present in the markup, because we don’t really want them.
The PictureTakenEventArgs class:
Finally, a simple event handler for PictureTaken:
Pictures arrive as instances of the Image class, and you can do whatever you want with it.
As always, feedback is greatly appreciated!
Continuing with my quest for reusable, no dependencies, Web Forms AJAX controls, this time I wanted a replacement for the venerable UpdatePanel control. Specifically, I wanted to address the following issues:
Allow the partial update of a region on my page, including all of its controls;
Have the ability to only send data for controls living inside my control, not everything else on the page (read, __VIEWSTATE);
I ended up with a CallbackPanel control, which is what I am going to talk about. Here is its declaration:
The CallbackPanel control supports some properties:
SendAllData: if all the data in the form should be sent, including viewstate, or just the data for the controls inside the CallbackPanel (default is false);
For causing an update, we call its callback function, passing it a parameter and an optional context:
The most important property in CallbackPanel is the server-side event, OnCallback: this is raised whenever the callback function is called:
This event receives a CallbackEventArgs argument, which is nothing more than:
And finally, the code for the CallbackPanel itself:
Again, it is implementing ICallbackEventHandler, for client callbacks, but this time it is inheriting from Panel, which is a nice container for other controls. The rest should be self-explanatory, I guess. If you have questions, do send them to me!
As always, hope you like it!
Set up a control that renders an AUDIO tag;
Generate a voice sound from the passed text parameter on the server and save it into an in-memory stream;
Convert the stream’s contents to a Data URI;
Return the generated Data URI to the client as the response to the client callback.
So, first of all, my markup looks like this:
As you can see, the SpeechSynthesizer control features a few optional properties:
- Age: the age for the generated voice (default is the one of the system’s default language);
- Gender: gender of the generated voice (same default as per Age);
- Culture: the culture of the generated voice (system default);
- Rate: the speaking rate, from –10 (fastest) to 10 (slowest), where the default is 0 (normal rate);
- Ssml: if the text is to be considered SSML or not (default is false);
- Volume: the volume %, between 0 and 100 (default);
- VoiceName: the name of a voice that is installed on the server machine.
The Age, Gender and Culture properties and the VoiceName are exclusive, you either specify one or the other. If you want to know the voices installed on your machine, have a look at the GetInstalledVoices method. If no property is specified, the speech will be synthesized with the operating system’s default (Microsoft Anna on Windows 7, Microsoft Dave, Hazel and Zira on Windows 8, etc). By the way, you can get additional voices, either commercially or for free, just look them up in Google.
Without further delay, here is the code:
As you can see, the SpeechSynthesizer control inherits from HtmlGenericControl, this is the simplest out-of-the-box class that will allow me to render my tag of choice (in this case, AUDIO); by the way, this class requires that I decorate it with a ConstructorNeedsTagAttribute, but you don’t have to worry about it. It implements ICallbackEventHandler for the client callback mechanism. I make sure that all of AUDIO’s attributes are removed from the output, because I don’t want them around.
Inside of it, I have an instance of the SpeechSynthesizer class, the one that will be used to do the actual work. Because this class is disposable, I make sure it is disposed at the end of the control’s life cycle. Based on the parameters being supplied, I either call the SelectVoiceByHints or the SelectVoice methods. One thing to note is, we need to set up a synchronization context, because the SpeechSynthesizer works asynchronously, so that we can wait for its result.
A full markup example would be:
And that’s it! Have fun with speech on your web apps!
I have been playing recently with HTML5, and one thing that I got to understand really well was the new upload mechanisms available. Specifically, I wanted to understand how SkyOneDrive, Google Drive, Dropbox, etc, all support dropping files from the local machine, and how to use it in an ASP.NET Web Forms (sorry!) project, and I got it!
So, I want to have a panel (a DIV) that allows dropping files from the local machine; I want to be able to filter these files by their content type, maximum length, or by any custom condition. If the dropped files pass all conditions, they are sent asynchronously (read, AJAX) and raise a server-side event. After that, if they are multimedia files, I can preview them on the client-side.
My markup looks like this:
The UploadPanel control inherits from the Panel class, so it can have any of its properties. In this case, I am setting a specific width, height and border, so that it is easier to target.
Out of the box, it supports the following validations:
MaximumFiles: The maximum number of files to drop; if not set, any number is accepted;
MaximumLength: The maximum length of any individual file, in bytes; if not set, any file size is accepted;
ContentTypes: A comma-delimited list of content types; can take a precise content type, such as “image/gif” or a content type part, such as “image/”; if not specified, any content type is accepted.
When a file is dropped into the UploadPanel, the following client-side events are raised:
OnValidationFailure: Raised whenever any of the built-in validations (maximum files, maximum length and content types) fails, for any of the dropped files;
OnBeforeUpload: Raised before the upload starts, and after all built-in validations (maximum files, maximum length and content types) succeed; this gives developers a chance to analyze the files to upload and to optionally cancel the upload, or to add additional custom parameters that will be posted together with the files;
OnUploadFailure: Raised if the upload fails for some reason;
OnUploadCanceled: Raised if the upload is canceled;
OnUploadProgress: Raised possibly several times as the file is being uploaded, providing an indication of the total upload progress;
OnUploadSuccess: Raised when the upload terminates successfully;
OnUploadComplete: Raised when the upload completes, either successfully or not;
OnPreviewFile: Raised for each multimedia file uploaded (images, videos, sound), to allow previewing it on the client-side; the handler function receives the file as a data URL.
The Upload event takes a parameter of type UploadEventArgs which looks like this:
This class receives a list of all the files uploaded and also any custom properties assigned on the OnBeforeUpload event. It also allows the return of a response string, that will be received by the OnUploadSuccess or OnUploadComplete client-side events:
Finally, the code:
The UploadPanel class inherits from Panel and implements ICallbackEventHandler, for client callbacks. If you are curious, the __CALLBACKID, __CALLBACKPARAM, __EVENTTARGET and __EVENTARGUMENT are required for ASP.NET to detect a request as a callback, but only __CALLBACKID needs to be set with the unique id of the UploadPanel control.
HTML5 offers a lot of exciting new features. Stay tuned for some more examples of its integration with ASP.NET!
First, the target markup:
No custom properties whatsoever, just an handler for the AutoFill event, which will be called whenever the fill function is invoked.
The AutoFillDropDownList inherits from DropDownList:
Again, for client callbacks, we need to implement ICallbackEventHandler. In its RaiseCallbackEvent we raise the AutoFill event, store its output in the request itself (HttpContext.Items collection), and on GetCallbackResult, we take this value and pass it to the client.
Another important thing is, whenever there is a postback, we need to raise the AutoFill event again, because the drop down must be in a consistent state, therefore we need to get its items. We do that in the PreLoad event of the page.
The AutoFill event uses a special argument:
Results: the key-value pairs that will be used to fill the drop down list items.
A typical handler might look like this:
There are no dependencies on any external libraries other than Microsoft AJAX Library, which is included by the ScriptManager.
Hope you like it!
I have talked about client callbacks in the past, and even provided a general-purpose control for invoking code on the server-side. This time, I will provide two more examples:
Since this blog started, back in 2008, I wrote a lot of posts. I’d say some are still up to date. I picked a few of them, those I’m more proud of, in no particular order.
ASP.NET Web Forms:
Let me know what you think of them! Are there others you particularly enjoyed?
Client Callbacks are probably the less known (and I dare say, less loved) of all the AJAX options in ASP.NET, which also include the UpdatePanel, Page Methods and Web Services. The reason for that, I believe, is it’s relative complexity:
Dynamically register function that calls the above reference;
So, here’s what I want to do:
Have a DOM element which exposes a method that is executed server side, passing it a string and returning a string;
Have a server-side event that handles the client-side call;
Have two client-side user-supplied callback functions for handling the success and error results.
The control itself looks like this:
And the event argument class:
You will notice two properties on the CallbackControl:
Async: indicates if the call should be made asynchronously or synchronously (the default);
SendAllData: indicates if the callback call will include the view and control state of all of the controls on the page, so that, on the server side, they will have their properties set when the Callback event is fired.
The CallbackEventArgs class exposes two properties:
Argument: the read-only argument passed to the client-side function;
Result: the result to return to the client-side callback function, set from the Callback event handler.
An example of an handler for the Callback event would be:
Finally, in order to fire the Callback event from the client, you only need this:
The syntax of the callback function is:
arg: some string argument;
context: some context that will be passed to the callback functions (success or failure);
callbackSuccessFunction: some function that will be called when the callback succeeds;
callbackFailureFunction: some function that will be called if the callback fails for some reason.
Give it a try and see if it helps!
One thing I didn’t refer on my previous post on ASP.NET MVC CRUD with AJAX was how to retrieve model validation information into the client.