. Node generation algorithm of TreeView control with privilege control under NET Platform

Source: Internet
Author: User
Tags foreach continue count goto insert object model tostring trim
treeview| Control | control | Algorithm ONE, INTRODUCTION

In application system development, the TreeView is a control that uses a high frequency. Its main feature is to be able to achieve a more clear classification, navigation, browsing and other functions. Therefore, the use of its methods and programming skills have been the attention of technical personnel. As application requirements change, in many cases we need to implement the control of the data display, that is, the data that the user sees is filtered, or contiguous, or some discrete value. In the case of the TreeView, it is possible to display a complete set of nodes with a strict parent-child relationship, and the nodes to be displayed after permission filtering may become discrete and no longer have a complete inheritance relationship. In this paper, an improved algorithm is proposed to solve this problem by analyzing the existing implementation methods. The attached sample program further explains the algorithm design idea.



Simple analysis of two or three kinds of common generation methods

As described in [2,3], there are basically three ways in which the TreeView is generated:

1. Interface design to populate the TreeView node directly in the TreeView designer or code.
This way, by dragging and dropping the control to generate the tree, the application scope is narrow, is a kind of non programming way;

2. Create a tree structure from the XML file.
This approach is more intuitive in form of XML file (string) spanning trees. Because XML itself is a tree, in the automatic generation Code of the TreeView under the. NET platform, the actual content of the TreeView is represented by XML. In addition, XML file spanning tree is very important for distributed application in heterogeneous environment. In fact, the use of XML as a universal data transfer format has been universally recognized;

3. Get the data from the database (in. NET, we can understand as a dataset, and build a tree structure.
This way, the recursive generation of trees through parent-child relationships is the easiest way to understand the programming implementation. Generally, top-down recursive generation is widely used.

Here, let's give a practical example to illustrate that we have such a dataset (which can be seen as a list of departments of a company):




Tagvalue
Contentvalue
ParentID

G01
Marketing Department


G02
Consulting Department


G03
Research and Development Department


G04
Testing Department


GS01
Marketing a Department
G01

GS02
Marketing Department Two
G01

GS03
Marketing Department Three
G01

GSL01
Marketing of a Beijing office
GS01

GSL02
Marketing a Shanghai office
GS01

GS04
Consultant
G02

GS05
Consultant Department Two
G02

GS06
Develop a
G03

GS07
Research and Development Two department
G03

GS08
Test A
G04

GS09
Test Unit Two
G04

GSL03
Research and development of a Hangzhou branch
GS06

GSL04
Develop an XI ' an branch
GS06


Table 1 Sample datasets

Where the tagvalue is the actual value of the node, Contentvalue is the value of the node displayed on the user interface or the label value, ParentID is the tagvalue of the node's parent node. If the node is the root node, generally set ParentID to be empty or equal to Tagvalue.

By default, we can assemble all the nodes into a tree according to the following algorithm,

Algorithm 1: Generating tree basic algorithm by parent-child relationship recursion

L Step 0: Data preparation, given data sets.
Generally, a dataset follows such a format, that is, (Tagvalue,contentvalue,parentid);

L Step 1: Given the node to be added (usually the root node at initial time), the Curnode, and the ParentID value of the node to be added (the initial parentid of the root node), is recorded as Curparentid;

L Step 2: Find all nodes in the dataset with the specified ParentID value, get the node set objarr[],
if (Objarr = null)
Return
Else
{
Traversal node Set
for (int i=0; i<objarr.length;i++)
{
Add Objarr[i] As a curnode child node, and recursively (soon Objarr[i] as Curnode,objarr[i tagvalue as Curparentid,goto step 1);
}
}





Finally you can get the TreeView as shown in the following illustration:




Figure 1 TreeView Effect Chart


The disadvantage of this approach is that the traversal order of "parent and child nodes" means that the parent node of each child node must exist, otherwise it will not be searched, that is, there may be a fault phenomenon. In many practical applications, we found that this implementation can not be fully effective, the most typical case is when the nodes are represented by the actual values (such as the list of institutions, personnel lists, resource lists, etc.) to control the rights, then often filtered from the database node will appear in the data set fault phenomenon. For example, we assume that when you set permissions on a given data such as table 2, that is, the first line of the "marketing department" to remove (note: Permission filtering operation is beyond the scope of this article, where the data set is already quasi-good), then use algorithm 1 generated TreeView as shown in Figure 2

Tagvalue
Contentvalue
ParentID

G02
Consulting Department


G03
Research and Development Department


G04
Testing Department


GS01
Marketing a Department
G01

GS02
Marketing Department Two
G01

GS03
Marketing Department Three
G01

GSL01
Marketing of a Beijing office
GS01

GSL02
Marketing a Shanghai office
GS01

GS04
Consultant
G02

GS05
Consultant Department Two
G02

GS06
Develop a
G03

GS07
Research and Development Two department
G03

GS08
Test A
G04

GS09
Test Unit Two
G04

GSL03
Research and development of a Hangzhou branch
GS06

GSL04
Develop an XI ' an branch
GS06


Table 2 Given data sets






Figure 2 TreeView Effect Chart

As you can see, this creates a node omission. In general, we can solve the problem from two aspects, on the one hand can be fixed data sets, on the other hand, can modify the spanning tree algorithm. It is obvious that the direct correction of datasets is complex and can bring about efficiency problems. And the unilateral modification of the spanning tree algorithm is not very good (that is, the missing node directly into the root node), because there will be parents and the younger sibling phenomenon.

Third, the tree algorithm by the depth number recursive generation

Reviewing some of the existing methods (text [1~5]), the method based on the node depth spanning tree gives us some inspiration, we can increase the depth field when we construct the dataset, but the depth here is not a simple level number, it is an extended concept, specifically a depth number, There is a certain correspondence between it and the parents number. For example, the dataset shown in table 1 can be numbered as follows:

Tagvalue
Contentvalue
ParentID
Depthid

G01
Marketing Department

a001

G02
Consulting Department

A002

G03
Research and Development Department

A003

G04
Testing Department

a004

GS01
Marketing a Department
G01
a001001

GS02
Marketing Department Two
G01
a001002

GS03
Marketing Department Three
G01
a001003

GSL01
Marketing of a Beijing office
GS01
a001001001

GSL02
Marketing a Shanghai office
GS01
a001001002

GS04
Consultant
G02
a002001

GS05
Consultant Department Two
G02
a002002

GS06
Develop a
G03
a003001

GS07
Research and Development Two department
G03
a003002

GS08
Test A
G04
a004001

GS09
Test Unit Two
G04
a004002

GSL03
Research and development of a Hangzhou branch
GS06
a003001001

GSL04
Develop an XI ' an branch
GS06
a003001002


Table 3 data sets with depth numbering

Where Depthid is the depth number of the node. The process of generating depth numbering is actually not complicated, first we can set number rules, such as the prefix of the hierarchy number, encoding length, starting value, and so on. When you number a node, just find the maximum number of the hierarchy and then increase by 1. The implementation process is no longer detailed here.

Therefore, we naturally think of the idea of using algorithm 1 to design a tree based on depth numbering program. At this point, we can find the descendant node set based on the depth number of the current node, but give a maximum span (which can be understood as the interval series between the highest and lowest levels) because it is impossible to find it indefinitely. This method can partly compensate for the "parent node and child node" traversal of the defect, because when the fault occurs along the number will continue to look backward. But it can still be missed, like our given dataset ("Research and development" filtered out):

Tagvalue
Contentvalue
ParentID
Depthid

G01
Marketing Department

a001

G02
Consulting Department

A002

G03
Research and Development Department

A003

G04
Testing Department

a004

GS01
Marketing a Department
G01
a001001

GS02
Marketing Department Two
G01
a001002

GS03
Marketing Department Three
G01
a001003

GSL01
Marketing of a Beijing office
GS01
a001001001

GSL02
Marketing a Shanghai office
GS01
a001001002

GS04
Consultant
G02
a002001

GS05
Consultant Department Two
G02
a002002

GS07
Research and Development Two department
G03
a003002

GS08
Test A
G04
a004001

GS09
Test Unit Two
G04
a004002

GSL03
Research and development of a Hangzhou branch
GS06
a003001001

GSL04
Develop an XI ' an branch
GS06
a003001002


Table 4 Given data sets

In the spanning tree process, when looking for a a003 from the "Research and Development Department" (R), it should be found that "R two" (A003002) because it is the nearest node. The following sequence is to follow the "research and development two" and then look down, it is obviously impossible to find "research and development of a Hangzhou branch" and "development of an XI ' an division", because the number sequence is not the same, so that the resulting tree will also miss the node.

We propose a new algorithm, that is, to break the traditional traversal order, using a bottom-up traversal sequence. Figuratively speaking, the traditional approach is to continuously derive a new child node (as shown in Figure 3 (a)) through an existing root node or parent node. The new algorithm is to create a subtree by constantly aggregating nodes, and finally to converge into a tree (shown in Figure 3 (b)).






Fig. 3 Diagram of the TreeView node generation process



Algorithm 2: The tree algorithm is generated from bottom up by hierarchy (depth) Traversal method

L Step 0: Data preparation, given data set (Tagvalue,contentvalue,depthid), Tagvalue is the actual value of the node, Contentvalue is the value of the node display or tag value, Depthid is the depth number of the node. If the node is the root node, the Depthid length is the shortest. Given maximum depth imaxdeplen and minimum depth imindeplen. Given the Hashtable used to store the current subtree;

L Step 1: Given the current traversal of the hierarchy length Icurdeplen, initially set to Imaxdeplen;

L Step 2: In the DataSet, find the level of the satisfying condition according to the given Icurdeplen, and get the node set objarr[],
if (Objarr = null)
Return
Else
{
Traversal node Set
for (int i=0; i<objarr.length;i++)
{
Step 2.1 finds the parent of objarr[i], if no parent node, join directly, goto step 2.2; If there is a parent node, first find whether the parent node is already in Hashtable. If so, it is removed from the Hashtable and recorded as Tempparnode; otherwise the new node is generated Tempparnode;goto step 2.3;
Step 2.2 If the current node Objarr[i] is not in the Hashtable, add objarr[i];continue to the Hashtable;
Step 2.3 If the current node Objarr[i] is not in the Hashtable, the node Tempnode is generated according to Objarr[i], otherwise it is removed from the Hashtable and recorded as Tempnode The tempnode is inserted into the tempparnode and will be deposited in Hashtable.
}
}

L Step 3: If the current level of Icurdeplen is greater than the minimum level imindeplen, then continue backtracking, will icurdeplen minus 1 and as the current Icurdeplen,goto step 2; otherwise goto step 4.

L Step 4: After getting the table of nodes stored with Hashtable (actually a subtree), traverse the Hashtable and insert each Shang tree into the TreeView.





In this algorithm, we calculate the minimum length and maximum length of the node depth number in the dataset in the beginning, so as to not blindly search. However, if the depth number of each level in the dataset is fixed, you can simplify the search process. The key value of the Hashtable that holds the temporary subtree is the tag value of the current child tree root node, and the advantage is that it is convenient to find and does not need to traverse a node in the TreeView. So, each time you process the node at the previous level, you can add the hashtable item by simply looking at its parent node in the Hashtable, or inserting it into a subtree.

The Appendix example program implements this algorithm, and here is a few key functions.

function form and its parameter explanation
Function

Populatecompletetree (ref System.Windows.Forms.TreeView Objtreeview,dataset dssource,string Strtreecaption,int Itagindex,int icontentindex,int Idepthindex)

1. Objtreeview is the final TreeView to be generated;

2. Dssource is a given dataset;

3. strtreecaption specifies the name of the TreeView root node;

4. Itagindex is the column number of the Tagvalue field in the dataset;

5. Icontentindex is the column number of the Contentvalue field in the dataset;

6. Idepthindex is the column number of the Depthid field in the dataset;
1. Using hierarchical (depth) traversal method to generate the tree keynote function;

2. Invoke Collectnodes (DataSet dssource,int itagindex,int icontentindex,int idepthindex,int icurdeplen,int iMinDepLen,ref Hashtable Objarrnode)

Collectnodes (DataSet dssource,int itagindex,int icontentindex,int idepthindex,int icurdeplen,int iMinDepLen,ref Hashtable Objarrnode)

1. Dssource,itagindex,icontentindex,idepthindex-ditto;

2. Icurdeplen refers to the current level depth numbering length;

3. Imindeplen refers to the minimum depth that is the topmost depth number length;

4. Objarrnode refers to the hashtable for storing the middle subtree.
1. Gather nodes from bottom to top;

2. Call Lookupparentnode (DataSet dssource,int idepthindex,string strsubdepth,int itagindex,int icontentindex)

Lookupparentnode (DataSet dssource,int idepthindex,string strsubdepth,int itagindex,int icontentindex)

1. Dssource,itagindex,icontentindex,idepthindex-ditto;

2. Strsubdepth refers to the depth number of the current node (because it is a recursive lookup)
1. Find the closest control level because it is possible that the parent node hierarchy does not exist.







At this point, if a given dataset (we filter out "research and development" and "marketing"),

Tagvalue
Contentvalue
ParentID
Depthid

G01
Marketing Department

a001

G02
Consulting Department

A002

G04
Testing Department

a004

GS02
Marketing Department Two
G01
a001002

GS03
Marketing Department Three
G01
a001003

GSL01
Marketing of a Beijing office
GS01
a001001001

GSL02
Marketing a Shanghai office
GS01
a001001002

GS04
Consultant
G02
a002001

GS05
Consultant Department Two
G02
a002002

GS07
Research and Development Two department
G03
a003002

GS08
Test A
G04
a004001

GS09
Test Unit Two
G04
a004002

GSL03
Research and development of a Hangzhou branch
GS06
a003001001

GSL04
Develop an XI ' an branch
GS06
a003001002


Table 5 Given data sets

The spanning tree is shown in the following illustration,




Figure 4 TreeView Effect Chart

This is the result we need.

Of course, sometimes we will take the so-called "neutral" approach for structural needs. For example, for the TreeView control node generation problem mentioned in this article, if you do not want to write algorithms to generate depth numbers, then we can also by adding a bit to the DataSet method, that is, using a flag bit to identify whether the data has been filtered. After using the traditional algorithm to generate the tree, then check to see if there are unfiltered data, and if so, find the ancestor node, insert it into the ancestor node. But the "Find ancestor node" Here is done on the TreeView, and when the nodes are many, their efficiency is definitely not high enough to search the dataset directly.

In addition, the introduction of depth numbering will not only bring convenience to the spanning tree, but also make the permissions set more flexible. Specifically to our example, if we want to filter out some departments, then we will take these departments one by one, we call it "discrete value set way." And when the structure of the system is large, we would prefer to select a range, such as a department and its control of the N-level filter out, this is a "continuous value set", then contains the hierarchy of the depth of the concept number can be a good solution to this problem. In the actual system development, we also found that the use of this approach is feasible.



Iv. other ways of TreeView generation

The TreeView can also be generated from the XML file (string) as mentioned earlier. The key to implementing this approach is to construct a TreeView-like XML document or string. The basic idea should be similar to the algorithms discussed earlier, but only slightly more complex in the implementation of the program (where the index of an XML node can be based on the Document Object Model (DOM)). Also note that there are a lot of third-party TreeView controls, and the format of the XML documents they support is different. Limited to space, this article does not discuss the specific implementation process in detail.

V. Summary

This article mainly discusses. NET platform, the design method of TreeView control node is designed, and the method is studied, and a complete solution is given.

In the concrete application of the tree, in addition to spanning the tree, the node increase, delete, change, check even the node upgrade and downgrade are very common. In essence, these operations are related to the operation of the database operations, so in the "bottom-up hierarchy (depth) traversal" generated in the TreeView, these operations are implemented in accordance with the traditional method, the extra action is nothing more than adding or modifying the depth number. Of course, the actual demand is changeable, the corresponding algorithm design and analysis is endless.



Reference documents (Reference):

[1] Zane Thomas. Dataviewtree for Windows forms,http://www.abderaware.com/whitepapers/datatreeview.htm

[2] Lee Honggen. Application of tree-shaped structure in development, http://www.microsoft.com/china/community/Column/21.mspx

[3] Lee Honggen. . NET platform, the design of Web tree structure, http://www.microsoft.com/china/community/Column/30.mspx

[4] Don schlichting. Populating the TreeView control from a Database, http://www.15seconds. Com/issue/030827.htm

[5] How to to:populate a TreeView control from a Dataset in Visual Basic. NET, Http://support. microsoft.com/?kbid=320755

[6] Scott Mitchell. displaying XML Data in the Internet Explorer TreeView control,http://aspnet. 4guysfromrolla.com/articles/051403-1.aspx




-------------
Source code:

Using System;
Using System.Data;
Using System.Windows.Forms;
Using System.Collections;


Namespace Poptreeview
{
<summary>
Summary description of the treeoperator.
</summary>
public class Treeoperator
{
Public Treeoperator ()
{
//
TODO: Add constructor logic here
//
}


<summary>
Using hierarchical (depth) traversal method to generate trees
</summary>
<param name= "Objtreeview" > Target tree </param>
<param name= "Dssource" > DataSet </param>
<param name= "strtreecaption" > Tree display name </param>
<param name= "Itagindex" > Value index </param>
<param name= "Icontentindex" > Content index </param>
<param name= "Idepthindex" > Hierarchy index </param>
public static void Populatecompletetree (ref System.Windows.Forms.TreeView Objtreeview,dataset dssource,string Strtreecaption,int itagindex,int icontentindex,int Idepthindex)
{
From the bottom start traversal, open up a hashtable (with the tag value as the keyword), the current calculation of the node
ObjTreeView.Nodes.Clear ();
int imaxlen = Getmaxdepthlen (Dssource,idepthindex);
int iminlen = Gettopdepthlen (Dssource,idepthindex);
Hashtable Objarrnode = new Hashtable ();
Collectnodes (Dssource,itagindex,icontentindex,idepthindex,imaxlen,iminlen,ref objArrNode);

TreeNode Objrootnode = new TreeNode (strtreecaption);

After you get the node table, insert the tree
foreach (Object Objnode in Objarrnode.values)
{
TreeNode Objnewnode = new TreeNode ();
Objnewnode = (TreeNode) objnode;
OBJROOTNODE.NODES.ADD (Objnewnode);
}

OBJTREEVIEW.NODES.ADD (Objrootnode);
}


<summary>
Aggregating nodes from bottom to top
</summary>
<param name= "Dssource" ></param>
<param name= "Itagindex" ></param>
<param name= "Icontentindex" ></param>
<param name= "Idepthindex" ></param>
<param name= "Icurdeplen" ></param>
<param name= "Imindeplen" ></param>
<param name= "Objarrnode" ></param>
private static void Collectnodes (DataSet dssource,int itagindex,int icontentindex,int idepthindex,int icurdeplen,int Imindeplen,ref Hashtable Objarrnode)
{
Collecting nodes
System.Data.DataView DV;
System.Windows.Forms.TreeNode Tempnode;

Find a given Layer node
int I=icurdeplen;
Todo
{
DV = new DataView (dssource.tables[0]);
String strexpr = "LEN (TRIM (" +dssource.tables[0].) Columns[idepthindex]. columnname+ ") =" +convert.tostring (i);
Dv. RowFilter = strexpr;
i--;
}while (I>=imindeplen && dv. count<=0);
Icurdeplen = i+1;

#region-layer backtracking, collecting nodes
foreach (System.Data.DataRowView drow in DV)
{
Find parent Node
string[] Strarrparentinfo = Lookupparentnode (Dssource,idepthindex,drow[idepthindex). ToString (). Trim (), itagindex,icontentindex);
String strtagvalue = Drow[itagindex]. ToString (). Trim ();
String strcontentvalue = Drow[icontentindex]. ToString ();

If no parent node, join directly
if (Strarrparentinfo = null)
{
The current node is not in Hashtable
if (objarrnode[strtagvalue]==null)
{
Add current node
Tempnode = new TreeNode (strcontentvalue);
Tempnode.tag = Strtagvalue;
Objarrnode.add (Strtagvalue,tempnode);
}
}
else//has a parent node to find if the parent node is already in Hashtable
{
String strpartagvalue = Strarrparentinfo[0]. Trim ();
String strparcontentvalue = Strarrparentinfo[1]. Trim ();

The parent node is already in the Hashtable
if (objarrnode[strpartagvalue]!= null)
{
The current node is not in Hashtable
if (objarrnode[strtagvalue]==null)
{
Tempnode = new TreeNode (strcontentvalue);
Tempnode.tag = Strtagvalue;
}
Else
{
Remove and remove the node, and then insert the parent node
Tempnode = new TreeNode ();
Tempnode = (TreeNode) objarrnode[strtagvalue];
Objarrnode.remove (Strtagvalue);
}

Insert into parent node
TreeNode Tempparnode = new TreeNode ();
Tempparnode = (TreeNode) objarrnode[strpartagvalue];
TEMPPARNODE.NODES.ADD (Tempnode);
Objarrnode[strpartagvalue] = Tempparnode;
}
else//parent node is not in Hashtable
{
The current node is not in Hashtable
if (objarrnode[strtagvalue]==null)
{
Tempnode = new TreeNode (strcontentvalue);
Tempnode.tag = Strtagvalue;
}
Else
{
Remove and remove the node, and then insert the parent node
Tempnode = new TreeNode ();
Tempnode = (TreeNode) objarrnode[strtagvalue];
Objarrnode.remove (Strtagvalue);
}

Create the parent node and insert the current node into the parent node
TreeNode Tempparnode = new TreeNode (strparcontentvalue);
Tempparnode.tag = Strpartagvalue;
TEMPPARNODE.NODES.ADD (Tempnode);
Objarrnode.add (Strpartagvalue,tempparnode);
}
}
}
#endregion

And a layer that's not traversed.
if (Icurdeplen>imindeplen)
{
Collectnodes (Dssource,itagindex,icontentindex,idepthindex,icurdeplen-1,imindeplen,ref objArrNode);
}

}


<summary>
Find Father Node
</summary>
<param name= "Dssource" ></param>
<param name= "Idepthindex" ></param>
<param name= "Strsubdepth" ></param>
<param name= "Itagindex" ></param>
<param name= "Icontentindex" ></param>
<returns> find returns an array of strings consisting of tag values, content values, and depth values, otherwise return null</returns>
private static string[] Lookupparentnode (DataSet dssource,int idepthindex,string strsubdepth,int itagindex,int Icontentindex)
{
System.Data.DataView DV;
int isublen = Strsubdepth.length;

if (isublen<=1)
{
return null;
}

int i=1;
Todo
{
DV = new DataView (dssource.tables[0]);
String strexpr = "TRIM (" +dssource.tables[0]. Columns[idepthindex]. columnname+ ") = '" +strsubdepth.substring (0,isublen-i) + "'";
Dv. RowFilter = strexpr;
i++;
}while (I<isublen && dv. count<=0);

if (DV. count<=0)
{
return null;
}
Else
{
String[] Strarr = {Dv[0][itagindex]. ToString (), Dv[0][icontentindex]. ToString (), Dv[0][idepthindex]. ToString ()};
return strarr;
}
}


<summary>
Get maximum depth value (length of depth)
</summary>
<param name= "Dssource" > DataSet </param>
<param name= "Idepthindex" > Depth index (column number) </param>
<returns> Maximum Depth value </returns>
private static int Getmaxdepthlen (DataSet dssource,int idepthindex)
{
DataRowCollection Objrowcol = dssource.tables[0]. Rows;
int iMax = Objrowcol[0][idepthindex]. ToString (). Trim (). Length;

foreach (DataRow objrow in Objrowcol)
{
int icurlen = Objrow[idepthindex]. ToString (). Trim (). Length;
if (Imax<icurlen)
{
IMax = Icurlen;
}
}

return iMax;
}


<summary>
Get minimum depth value (length of depth)
</summary>
<param name= "Dssource" > DataSet </param>
<param name= "Idepthindex" > Depth index (column number) </param>
<returns> Minimum depth value </returns>
private static int Gettopdepthlen (DataSet dssource,int idepthindex)
{
DataRowCollection Objrowcol = dssource.tables[0]. Rows;
int imin = Objrowcol[0][idepthindex]. ToString (). Trim (). Length;

foreach (DataRow objrow in Objrowcol)
{
int icurlen = Objrow[idepthindex]. ToString (). Trim (). Length;
if (Imin>icurlen)
{
Imin = Icurlen;
}
}

return imin;
}


}
}


-----------
Memo: Originally I wanted to publish in the publication, the length is very long, here has been abridged. Welcome correction, Communication!





Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.