Eliminate errors in XML and HTML editing by adding IntelliSense support for your configuration sections and controls.
Visual Studio provides developers with IntelliSense in code by interrogating compiled objects or assemblies, but it is unable to provide the same assistance when editing XML, HTML, or ASPX files. In this hack, you will learn how to enable IntelliSense in these documents using an XML schema.
IntelliSense in HTML and XML documents relies on XML schema. ASP.NET has schemas defined for the built-in types (DataGrid, TextBox, etc.), but if you find yourself editing custom sections in application configuration files or want to add IntelliSense to your custom controls, you can create your own schema and reference it from your files. Visual Studio will then add the elements you define in your schema to the default ones and provide you with the same level of support you expect from the built-in controls.
The schema you need to create is composed of three basic sections: the header, the names, and the types.
The schema header is fairly standard and will look almost identical for each schema you create:
<?xml version="1.0" encoding="utf-8" ?> <xsd:schema targetNamespace="http://www.orbitalspacelaser.com/schemas" xmlns="http://www.orbitalspacelaser.com/schemas" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:vs= "http://schemas.microsoft.com/Visual-Studio-Intellisense" vs:friendlyname="Custom Intellisense Forms Controls" vs:ilschema="false" vs:iscasesensitive="false" vs:requireattributequotes="true">
The sections that you will need to change are the targetNamespace, the xmlns, and the vs:friendlyname attribute. Generally, targetNamespace and xmlns should be the same and set to some unique schema namespace. The format is a URL that uniquely identifies the namespace that this schema describes. A format such as http://OrganizationName/schema/ProjectName is generally acceptable.
The vs:friendlyname attribute should be set to some string that succinctly describes the set of items you are providing for IntelliSense with this schema.
Note that the schema must have a matching close tag (</xsd:schema>) at the end of the document for it to be validated and used.
Following the header section are the names of the items that are valid in the schema. This section is basically a simple list of items that are valid in the document you will be editing, be it a list of custom control names that are valid in an ASPX or elements that are valid in a XML configuration file:
<xsd:element name="AlphaControl" type="AlphaControlDef" />
The name attribute will determine what Visual Studio matches in the file. Thus, the preceding element will match <AlphaControl> in the XML file you are editing (remember that ASPX files are XML files). The type of the element will be defined in the next section. For most situations, using the name and adding "Def" to the end should be sufficient.
The types defined in the schema are actually what Visual Studio will use to create the IntelliSense prompts when you are editing a file. Types can be very complex and can also be nested, so if you have a hierarchy (with custom controls, for example) you can mirror that in the schema:
<xsd:complexType name="AlphaControlDef"> <xsd:attribute name="Alpha" type="xsd:boolean" /> <xsd:attribute name="Delta" type="xsd:double" /> <xsd:attribute name="Gamma"> <xsd:simpleType> <xsd:restriction base="xsd:string"> <xsd:enumeration value="ValueOne" /> <xsd:enumeration value="ValueTwo" /> <xsd:enumeration value="ValueThree" /> </xsd:restriction> </xsd:simpleType> </xsd:attribute> <xsd:attributeGroup ref="BaseClassAttributes" /> </xsd:complexType>
This type represents a few simple attributes that demonstrate much of the flexibility of the schema. Our element contains three attributes and also a group of attributes defined elsewhere. Both Alpha and Delta have simple xsd types set, and Visual Studio will simply prompt you to enter a value of the appropriate type, providing a list of choices where applicable (such as True/False with Boolean attributes).
The attribute definition for Gamma defines a custom simpleType, which allows us to enhance the built-in xsd types. We start with a string, but we add a restriction to it. When we edit this type in Visual Studio, this restriction tells Visual Studio that the value for Gamma can only be one of the options listed in the enumeration, so it will prompt the developer to pick one of them, as shown in Figure 4-22.
XML schemas provide a great many options on how to build these attributes, but these simple options should cover most controls and configuration sections you will need to create.
Application configuration files are straight XML and will generally be custom to an application, so creating the schema is a fairly straightforward process. In general, your use of attribute groups and other more complex constructs will be limited in these situations.
Creating schema for a custom control often involves extending the existing schema of one of ASP.NET's built-in controls. In this situation, we can eliminate a lot of typing and create a more useful schema by copying the appropriate portions of the default ASP.NET schema. After creating your schema file, locate and open the file <VS Install Directory>\Common7\Packages\schemas\xml\asp.xsd. This file contains the schema for all the built-in controls. Find and copy into your new schema the appropriate attributeGroup elements that apply to your control.
|
In most cases, you will be able to use the ControlAttributes group even if no other groups apply. After pasting these definitions into your schema, you can simply reference them with an attribute group tag inside the appropriate type:
<xsd:attributeGroup ref="ControlAttributes" />
After that, your type will automatically provide all the attributes defined in the referenced attribute group.
After you have created the schema, you need to place it where Visual Studio expects to find it. The normal directory will be <VS Install Directory>\Common7\Packages\schemas\xml. After you copy your new schema to this directory, Visual Studio will be able to reference it in files in which the appropriate XML namespace is imported. Be sure to restart your Visual Studio environment to ensure the new schema is recognized.
Referencing a schema after it has been installed is a matter of adding an attribute to the document you are editing to make Visual Studio use the XML namespace you created. To do this, simply add an xmlns attribute to the root element in the file with a value equal to the targetNamespace you defined in your schema.
It's easy to set configuration files to use a schema. Simply add the xmlns to the node below which your schema should apply. For example, if your schema defines the elements your application would expect in the appSettings node of the file, the types and attributes you had defined in your schema would apply beneath that point, such as with this schema, which provides assistance adding a ConnectionString attribute to your appSettings (Figure 4-23 shows it in action):
<?xml version="1.0" encoding="utf-8" ?> <xsd:schema targetNamespace= "http://www.orbitalspacelaser.com/schemas/config" xmlns="http://www.orbitalspacelaser.com/schemas/config" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:vs= "http://schemas.microsoft.com/Visual-Studio-Intellisense" vs:friendlyname="Custom Intellisense Forms Controls" vs:ilschema="false" vs:iscasesensitive="false" vs:requireattributequotes="true"> <xsd:element name="ConnectionString" type="ConnectionStringDef"/> <xsd:complexType name="ConnectionStringDef"> <xsd:attribute name="Server" type="xsd:string"/> <xsd:attribute name="Database" type="xsd:string"/> <xsd:attribute name="User" type="xsd:string"/> <xsd:attribute name="Password" type="xsd:string"/> </xsd:complexType> </xsd:schema>
|
For an ASPX file, this means changing the body tag to include the namespace and giving it an alias:
<body xmlns:cc1="http://www.orbitalspacelaser.com/schemas/controls">
The cc1 will then be the alias for this namespace. If you are referencing a custom control library, it should match the TagPrefix defined in the Register directive at the top of the page:
<%@ Register TagPrefix="cc1" Namespace="CustomControlIntellisense" Assembly="CustomControlIntellisense" %>
Now when you wish to reference the control, simply open a tag with the alias defined, as shown in Figure 4-24.
Visual Studio will now display your types in the list of available tags and will provide IntelliSense for the defined attributes.
Ben Von Handorf