Author: Dflying Chen ( http://dflying.cnblogs.com/ )
After understanding the basic concepts and completing the prerequisites (please refer to: Developing the ASP.NET Atlas server-side Extender control - basic concepts and prerequisites), we can start developing this ValidateUserNameExtender.
First, create a new Atlas Control Project in Visual Studio and name it ValidateUserName. After creation, the solution should look like the following picture:
As you can see, the following assembly is automatically referenced for us in the Project Template:
Microsoft.Web.Atlas.dll, which is the core assembly of Atlas and will be used by the following Microsoft.AtlasControlExtender.dll.
Microsoft.AtlasControlExtender.dll, this is the assembly where the base class of the Extender in Atlas provided by Microsoft is located. Several necessary classes in our customized Extender inherit from the base class provided in this assembly.
At the same time, this Project Template also created a JavaScript file and three C# files for us:
ValidateUserNameBehavior.js, which is the core part of our Extender and is also the file that accommodates all client-side scripts. The content will be basically the same as using ASP.NET Atlas develops the content of the ValidateUserNameBehavior.js file in the custom Behavior to verify in real time whether the user name is registered, which will be analyzed in detail later. Atlas' Extender is actually an encapsulation of this client-side Behavior, making it a server-side control to simplify the work of website program developers when using it. As a control developer, it adds a lot of work.
ValidateUserNameDesigner.cs, used here to write code that provides design-time support in Visual Studio.
ValidateUserNameExtender.cs, used here to define our Extender.
ValidateUserNameProperties.cs is used to define the properties used in our Extender. The values of these properties will be mapped to the properties of the client's Behavior.
Let's start with the ValidateUserNameBehavior.js JavaScript file. Open the ValidateUserNameBehavior.js file. We will find that Template has added 77 lines of code for us, and there are many TODOs in the code. There are 3 more in the read me section of the code. Step one:
Create local variables to store attribute values.
Add these local variables to the Type Descriptor. This step is to let Atlas understand your class.
Add accessors (getters and setters) to local variables.
Before starting step 1, we first change the default namespace in the Template to what we need. Here I use Dflying.Atlas.ControlTookit.ValidateUserName, and update all related class names that appear in the code.
Then for step 1 and step 3, we do it together. Refer to ValidateUserNameBehavior.js in the custom Behavior that uses ASP.NET Atlas to develop real-time verification of whether the user name is registered. CheckResultLabelID, ServiceName, MethodName, ValidMessage and InvalidMessage should be added. attributes, here I only give an example:
var _MethodName;
this.get_MethodName = function() {
return _MethodName;
}
this.set_MethodName = function(value) {
if (_MethodName != value) {
_MethodName = value;
this.raisePropertyChanged('MethodName');
}
}
Then step 2: this.getDescriptor = function() {
var td = Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'getDescriptor');
td.addProperty('CheckResultLabelID', String);
td.addProperty('ServiceName', String);
td.addProperty('MethodName', String);
td.addProperty('ValidMessage', String);
td.addProperty('InvalidMessage', String);
return td;
}
Finally, there are the constructor and analysis function, which also appear in TODO:
this.initialize = function() {
Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'initialize');
_blurHandler = Function.createDelegate(this, blurHandler);
this.control.element.attachEvent('onblur', _blurHandler);
}
this.dispose = function() {
if (_blurHandler) {
this.control.element.detachEvent('onblur', _blurHandler);
_blurHandler = null;
}
Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'dispose');
}
Plus the Handler that calls the Web Service and the corresponding CallBack:
this.initialize = function() {
Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'initialize');
_blurHandler = Function.createDelegate(this, blurHandler);
this.control.element.attachEvent('onblur', _blurHandler);
}
this.dispose = function() {
if (_blurHandler) {
this.control.element.detachEvent('onblur', _blurHandler);
_blurHandler = null;
}
Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'dispose');
}
There is also a part of Code automatically generated by Template, which is used to connect the status interaction between the server and the client. In this example, we do not need to use it. Of course, there is no harm in keeping it:
this.getClientState = function() {
var value = Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'get_ClientState');
if (value == '') value = null;
return value;
}
this.setClientState = function(value) {
return Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'set_ClientState',[value]);
}
The last thing to note is the last line of this JavaScript:
Sys.TypeDescriptor.addType('dflying', 'ValidateUserNameBehavior', Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior);
Among them, dflying represents the prefix of the client control declaration generated by our Extender, and ValidateUserNameBehavior represents the tag name of the client control. These two names should be picked and remembered, and they will also be used in the following CS files.
In this way, the complete ValidateUserNameBehavior.js source code is as follows:
ValidateUserNameBehavior.js
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Permissive License.
// Seehttp://www.microsoft.com/resources/sharedsource/licensingbasics/sharedsourcelicenses.mspx .
// All other rights reserved.
Type.registerNamespace('Dflying.Atlas.ControlTookit.ValidateUserName');
Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior = function() {
Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.initializeBase(this);
var _blurHandler;
var _CheckResultLabelID;
var _checkResultLabel;
var_ServiceName;
var_MethodName;
var _ValidMessage = "You can use this user name.";
var _InvalidMessage = "This user name has already been used, please choose another.";
this.get_CheckResultLabelID = function() {
return _CheckResultLabelID;
}
this.set_CheckResultLabelID = function(value) {
if (_CheckResultLabelID != value) {
_checkResultLabel = $(value);
debug.assert(_checkResultLabel != null, "CheckResultLabelID must be set to a valid DOM element.");
_CheckResultLabelID = value;
this.raisePropertyChanged('CheckResultLabelID');
}
}
this.get_ServiceName = function() {
return _ServiceName;
}
this.set_ServiceName = function(value) {
if (_ServiceName != value) {
_ServiceName = value;
this.raisePropertyChanged('ServiceName');
}
}
this.get_MethodName = function() {
return _MethodName;
}
this.set_MethodName = function(value) {
if (_MethodName != value) {
_MethodName = value;
this.raisePropertyChanged('MethodName');
}
}
this.get_ValidMessage = function() {
return _ValidMessage;
}
this.set_ValidMessage = function(value) {
if (_ValidMessage != value) {
_ValidMessage = value;
this.raisePropertyChanged('ValidMessage');
}
}
this.get_InvalidMessage = function() {
return _InvalidMessage;
}
this.set_InvalidMessage = function(value) {
if (_InvalidMessage != value) {
_InvalidMessage = value;
this.raisePropertyChanged('InvalidMessage');
}
}
this.initialize = function() {
Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'initialize');
_blurHandler = Function.createDelegate(this, blurHandler);
this.control.element.attachEvent('onblur', _blurHandler);
}
this.dispose = function() {
if (_blurHandler) {
this.control.element.detachEvent('onblur', _blurHandler);
_blurHandler = null;
}
Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'dispose');
}
this.getDescriptor = function() {
var td = Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'getDescriptor');
td.addProperty('CheckResultLabelID', String);
td.addProperty('ServiceName', String);
td.addProperty('MethodName', String);
td.addProperty('ValidMessage', String);
td.addProperty('InvalidMessage', String);
return td;
}
function blurHandler() {
if (this.control.element.value == '') {
_checkResultLabel.innerHTML = '';
return;
}
Sys.Net.ServiceMethod.invoke(
_ServiceName,
_MethodName,
'',
{ userNameCandidate : this.control.element.value},
_onMethodComplete
);
}
function _onMethodComplete(result)
{
_checkResultLabel.innerHTML = result ? _ValidMessage : _InvalidMessage;
}
this.getClientState = function() {
var value = Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'get_ClientState');
if (value == '') value = null;
return value;
}
this.setClientState = function(value) {
return Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.callBaseMethod(this, 'set_ClientState',[value]);
}
}
Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior.registerSealedClass('Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior', Microsoft.AtlasControlExtender.BehaviorBase);
Sys.TypeDescriptor.addType('dflying', 'ValidateUserNameBehavior', Dflying.Atlas.ControlTookit.ValidateUserName.ValidateUserNameBehavior);
At this point, the client part has been completed, followed by the server side, which is the remaining three Preparation of CS files.