• Không có kết quả nào được tìm thấy

The first service that the ASP.NET platform provides to applications is configuration. This may not seem like the most exciting topic, but the configuration feature is rich and flexible and helps avoid one of the pitfalls of complex software development: hard-coding behaviors into software components. As you will learn, the ASP.NET support for configuration can be adapted to suit all kinds of web applications and is worth taking the time to understand. Table 9-1 summarizes this chapter.

Table 9-1. Chapter Summary

Problem Solution Listing

Define simple configuration values. Use application settings. 1–3

Read application settings. Use the WebConfigurationManager.AppSettings property. 4–6 Define settings for connecting to

remote services, such as databases.

Use connection strings. 7

Read connection strings. Use the WebConfigurationManager.ConnectionStrings property.

8

Group related settings. Define a configuration section. 9–12

Read configuration sections. Use the GetWebApplicationSection method defined by the WebConfigurationManager class.

13, 19

Group a collection of similar settings together.

Define a collection configuration section. 14–18

Group sections together. Define a collection section group. 20–21

Read section groups. Use the OpenWebConfiguration method defined by the WebConfigurationManager class.

22

Override configuration settings. Use the location element or create a folder-level configuration file.

23–27

Read the ASP.NET settings. Use the handler classes in the System.Configuration namespace.

28

Preparing the Example Project

For this chapter I created a new project called ConfigFiles, following the same approach I used for earlier example applications. I used the Visual Studio ASP.NET Web Application template, selected the Empty option, and added the core MVC references. I’ll be using Bootstrap again in this chapter, so enter the following command into the Package Manager Console:

Install-Package -version 3.0.3 bootstrap

I added a Home controller to the Controllers folder, the definition of which you can see in Listing 9-1. Throughout this chapter, I’ll be displaying lists of configuration properties and their values, so the data that the Index action passes to the View method is a dictionary. So that I can test the application, I have defined some placeholder data in the controller.

Listing 9-1. The Contents of the HomeController.cs File using System.Collections.Generic;

using System.Web.Mvc;

namespace ConfigFiles.Controllers {

public class HomeController : Controller { public ActionResult Index() {

Dictionary<string, string> configData = new Dictionary<string, string>();

configData.Add("Placeholder Property", "Placeholder Value");

return View(configData);

} } }

I created a view by right-clicking the Index action method in the code editor and selecting Add View from the pop-up menu. I called the view Index.cshtml, selected the Empty (without model) template, and unchecked all of the view option boxes. You can see the content I defined in the view in Listing 9-2.

Listing 9-2. The Contents of the Index.cshtml File

@model Dictionary<string, string>

@{ Layout = null; }

<!DOCTYPE html>

<html>

<head>

<meta name="viewport" content="width=device-width" />

<link href="~/Content/bootstrap.min.css" rel="stylesheet" />

<link href="~/Content/bootstrap-theme.min.css" rel="stylesheet" />

<style> body { padding-top: 10px; } </style>

<title>Configuration</title>

</head>

<body class="container">

<div class="panel panel-primary">

<div class="panel-heading">Configuration Data</div>

<thead>

<tr><th>Property</th><th>Value</th></tr>

</thead>

<tbody>

@foreach (string key in Model.Keys) {

<tr><td>@key</td><td>@Model[key]</td></tr>

} </tbody>

</table>

</div>

</body>

</html>

Start the application and navigate to the root URL or /Home/Index to see how the view is rendered, as shown in Figure 9-1.

Figure 9-1. Testing the example application

ASP.NET Configuration

Aside from a few standard additions to configure a database or enable debugging, most MVC framework developers don’t give any thought to the Web.config file, which is a shame because it provides a useful set of features that configure ASP.NET and that can be consumed within application code. In the sections that follow, I describe how the Web.config file forms part of a larger configuration system and explain how you can use this system to control the behavior of your applications. Table 9-2 puts the ASP.NET configuration system into context.

Table 9-2. Putting the ASP.NET Configuration System in Context

Question Answer

What is it? It’s a flexible set of classes and files that control the behavior of the ASP.NET foundation and services, the MVC framework, and your web application code.

Why should I care? Using the built-in configuration support is much easier than writing your own settings code,

Understanding the Configuration Hierarchy

Most MVC framework developers only need to edit the Web.config file in the top-level of the Visual Studio project, but this is just one of a hierarchy of configuration files that ASP.NET uses. When an application is started, ASP.NET starts at the top of the hierarchy and works its way down. Each level in the hierarchy has a slightly narrower scope, and the overall effect is to allow lower-level configuration files to override more general settings that have been previously defined. The application-level Web.config file—the one in the root folder of Visual Studio—is close to the bottom of the hierarchy and relies on dozens of settings that have been defined in higher-level files. Table 9-3 summarizes the configuration files and explains how they relate to one another.

Table 9-3. The Hierarchy of Configuration Files

Scope Name Description

Global Machine.config This is the top-level file in the hierarchy. Changes to this file affect every ASP.NET application running on the server. See the following text for the location of this file.

Global ApplicationHost.config This file defines the configuration sections and default values for IIS or IIS Express. It is at the second level of the hierarchy and is used to define settings specific to the app server. See the following text for the location of this file.

Global Web.config This is the global version of the Web.config file and is located in the same directory as the Machine.config file. It provides the server-wide default values for ASP.NET and is at the second level of the hierarchy. Changes to this file override the settings in Machine.config.

Site Web.config An ASP.NET site is an IIS folder hierarchy that can contain multiple applications. The Web.config file in the site’s root folder sets the default configuration for all the applications in that site. This file is at level 3 in the hierarchy and is used to override settings in the global Web.config file.

App Web.config This is the application-level Web.config file found in the root folder of the application and is the one that developers most often use for configuration.

It overrides the values specified in the site-level Web.config.

Folder location elements A location element in the app-level Web.config file specifies

configuration settings for a URL specified by the path attribute. See the

“Overriding Configuration Settings” section for details.

Folder Web.config This is a Web.config file added to a folder within the application and has the same effect as a location attribute in the app-level Web.config file. The MVC framework uses a web.config file in the Views folder to configure the view engine. See the “Overriding Configuration Settings”

section for details.

Tip

the MVC framework includes a file called

web.config

(with a lowercase

w

) in the

Views

folder. the file names

are not case sensitive, and this is an example of a folder-level

Web.config

file as described in the table.

ASP.NET starts with the Machine.config file, which is at the top of the hierarchy to get the starting point for the configuration and then moves to the second-level of the hierarchy and processes the ApplicationHost.config and global Web.config files. New settings are added to form a merged configuration, and values for existing settings are replaced. This process continues down the hierarchy until the app-level Web.config file is reached, and elements are used to expand the merged configuration or replace existing configuration values. Finally, the location elements and the folder-level Web.config files are processed to create specific configurations for parts of the application. Figure 9-2 shows the hierarchy of files as they are processed.

Machine

ApplicationHost

Web (Global)

Web (Global)

Web (Site)

Web (App)

Web (Folder) Location elements

Figure 9-2. The hierarchy of ASP.NET configuration files

Tip

i have included the site-level

Web.config

file for completeness, but it is specific to iiS. iiS is still widely used, but there is a substantial shift toward cloud deployment and the use of other servers using the oWin api. i recommend that you don’t use iiS sites and that you install each application in isolation because it makes it easier to move between deployment models. instead, use application-level

Web.config

files.

Although the configuration is spread throughout multiple files, the overall effect is a consistent configuration where settings are defined for every application at the global level and then progressively refined in the site, application, and folder-level files. This is why something as complex as an MVC framework application needs only a few lines of settings in the Web.config file: Hundreds of other settings are defined further up the hierarchy.

Tip

if any of the files are missing, aSp.net skips to the next level in the hierarchy. But, as you’ll learn, the global files define the structure that later files use to define configuration settings as well as their default values.

One of the reasons that developers work with the application-level Web.config file is that the files higher up in the hierarchy cannot be edited, something that is almost always the case for hosting and cloud platforms and frequently true for IIS servers running in private data centers as well.

Caution

the aSp.net platform caches the configuration data after it processes the hierarchy of files to improve

performance. however, the configuration files are monitored, and any changes cause the application to be restarted,

which can cause any state data to be lost and interrupt service to users. for this reason, it is important you don’t modify

the configuration files for a production system while the application is running.

During development you will sometimes need to change the global configuration files to re-create the settings that you will encounter in production. You can find the Machine.config and global Web.config files in the following folder:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config

You may have a slightly different path if you are using a later version of .NET or have installed Windows into a nonstandard location. You can find the ApplicationHost.config file used by IIS Express in the following folder, where <user> is replaced by the name of the current user:

C:\Users\<user>\Documents\IISExpress\config

Working with Basic Configuration Data

The configuration file system allows you to define settings for your application in different ways ranging from simple and generic key-value pairs to complex custom settings that are completely tailored to the needs of one application.

In this section, I’ll show you how to define different kinds of basic setting and explain how you access them programmatically. After all, there is no point in being able to define a configuration if you can’t read it at runtime.

Table 9-4 puts basic configuration data into context.

Table 9-4. Putting the Basic ASP.NET Configuration Data in Context

Question Answer

What is it? The basic configuration data consists of application settings and connection strings.

Application settings are a set of key-value pairs, and connection strings contain information required to establish connections to external systems, such as databases.

Why should I care? Application settings are the simplest way to define custom configuration information for an application. Connection strings are the standard mechanism for defining database connections and are widely used with ASP.NET.

How is it used by the MVC framework?

The MVC framework uses application settings to some of its own configuration data.

Connection strings are not used directly but are relied on for persistence for application models.

Access to configuration data is provided through the WebConfigurationManager class, defined in the System.Web.Configuration namespace. The WebConfigurationManager class makes it easy to work with the configuration system—but there are some oddities, as I’ll explain. There are several useful static members of the WebConfigurationManager class, as described in Table 9-5.

Note

the classes that aSp.net provides for obtaining configuration information also allow changes to be made to the configuration. i think this is a terrible idea; in fact, i think it is such a bad idea that i am not going to demonstrate how it is done. i sometimes come across projects that try to modify the configuration as the application is running and it always ends badly.

Using Application Settings

Application settings are simple key-value pairs and are the easiest way to extend the configuration to define values that are specific to an application. Listing 9-3 shows the application settings that I added to the application-level Web.config file (the one that is at the root level in the Visual Studio project).

Listing 9-3. Defining Application Settings in the Web.config File

<?xml version="1.0" encoding="utf-8"?>

<configuration>

<appSettings>

<add key="webpages:Version" value="3.0.0.0" />

<add key="webpages:Enabled" value="false" />

<add key="ClientValidationEnabled" value="true" />

<add key="UnobtrusiveJavaScriptEnabled" value="true" />

<add key="defaultCity" value="New York"/>

<add key="defaultCountry" value="USA"/>

<add key="defaultLanguage" value="English"/>

Table 9-5. The Most Useful Members Defined by the WebConfigurationManager Class

Name Description

AppSettings Returns a collection of key-value pairs used to define simple application-specific settings. See the “Using Application Settings”

section for details.

ConnectionStrings Returns a collection of ConnectionStringSettings objects that describe the connection strings. See the “Using Connection Strings”

section for details.

GetWebApplicationSection(section) Returns an object that can be used to get information about the

specified configuration section at the application level. This method will ignore any folder-level configuration even if the current request targets such a folder. See the “Grouping Settings Together” section for details.

OpenWebConfiguration(path) Returns a System.Configuration.Configuration object that reflects the complete configuration at the specified level. See the “Overriding Configuration Settings” section for details.

<system.web>

<compilation debug="true" targetFramework="4.5.1" />

<httpRuntime targetFramework="4.5.1" />

</system.web>

</configuration>

Tip

the configuration examples in this chapter all follow a related theme, which is to express the default values that a new user account might require. this is one of the most common uses for configuration data in the projects that i see in development—and is often hard-coded into the application components.

The Web.config file that Visual Studio created for the project already has an appSettings element, which is defined within the top-level configuration element. There can be only one appSettings element in the

configuration file (unless you are using a location element, which I describe later in this chapter), so I have added to the existing element to define some new settings.

Tip

Don’t confuse application settings with application state, which i describe in Chapter 10. application settings are read-only values that are used to define custom configuration values, while application state is used for data values that can change as the application is running.

ASP.NET configuration files have a well-defined XML schema, which allows for some useful features. One such feature is that some configuration elements—including the appSettings element—are actually collections of properties and values. To control the content of the collection, you can use three different child elements within appSettings, as described in Table 9-6.

Table 9-6. The Elements Used to Control the Contents of a Configuration Collection Name Description

add Defines a new application setting. The attributes supported by this element are key and value, which define the name of the setting and its value.

clear Removes all of the application settings. No attributes are supported.

remove Removes a single application setting, specified by the key attribute.

In Listing 9-3, I used the add element to define three new settings: defaultCity, defaultCountry, and defaultLanguage.

Tip

You can get complete details of the XML schema used for configuration files from MSDn.

See

http://msdn.microsoft.com/en-us/library/zeshe0eb(v=vs.100).aspx

.

Reading Application Settings

Reading application settings is done through the WebConfigurationManager.AppSettings property, which returns an instance of the NameValueCollection class, defined in the System.Collections.Specialized namespace. There are four useful properties for reading application settings, as described in Table 9-7.

In Listing 9-4, you can see how I have updated the Index action in the Home controller to read application settings.

Listing 9-4. Reading Application Settings in the HomeController.cs File using System.Collections.Generic;

using System.Web.Mvc;

using System.Web.Configuration;

namespace ConfigFiles.Controllers {

public class HomeController : Controller { public ActionResult Index() {

Dictionary<string, string> configData = new Dictionary<string, string>();

foreach (string key in WebConfigurationManager.AppSettings) { configData.Add(key, WebConfigurationManager.AppSettings[key]);

}

return View(configData);

} } }

I have used a standard foreach loop to iterate through the set of application settings’ names and add them—and the corresponding values—to the view model Dictionary. You can see the effect by starting the application and requesting the /Home/Index URL, as shown in Figure 9-3.

Table 9-7. The NameValueCollection Properties Useful for Reading Application Settings

Name Description

AllKeys Returns a string array containing the application settings’ names Count Returns the number of application settings

Item[index] Returns the value of the application setting at the specified index Item[key] Returns the value of the application setting with the specified key

I enumerated all of the application settings, which is helpful to demonstrate how the configuration system works but isn’t a realistic demonstration of how settings are usually consumed. In Listing 9-5, you can see that I have added a DisplaySingle action method to the Home controller, which uses an application setting to vary the model data sent to the view.

Listing 9-5. Adding an Action Method in the HomeController.cs File using System.Collections.Generic;

using System.Web.Mvc;

using System.Web.Configuration;

namespace ConfigFiles.Controllers {

public class HomeController : Controller { public ActionResult Index() {

Dictionary<string, string> configData = new Dictionary<string, string>();

foreach (string key in WebConfigurationManager.AppSettings) { configData.Add(key, WebConfigurationManager.AppSettings[key]);

}

return View(configData);

}

Figure 9-3. Reading the application settings

public ActionResult DisplaySingle() {

return View((object)WebConfigurationManager.AppSettings["defaultLanguage"]);

} } }

In the new action method, I get the value of the defaultLanguage application setting and use it as the view model data. Listing 9-6 shows the view that I created for the action method.

Listing 9-6. The Contents of the DisplaySingle.cshtml File

@model string

@{

Layout = null;

}

<!DOCTYPE html>

<html>

<head>

<meta name="viewport" content="width=device-width" />

<title>Single Config Value</title>

<link href="~/Content/bootstrap.min.css" rel="stylesheet" />

<link href="~/Content/bootstrap-theme.min.css" rel="stylesheet" />

<style>body { padding-top: 10px; }</style>

</head>

<body class="container">

<div class="alert alert-success">

Value: @Model </div>

</body>

</html>

Defining simple settings in the configuration file has a number of benefits. First, settings are not hard-coded in the components of the application, such as models and views, and this means that making changes is simple and easy. Second, Visual Studio includes a useful feature that will automatically transform a configuration file for testing or deployment, which makes it easy to consistently change settings as an application moves out of development and toward production. Finally, using application settings makes it easy to ensure that all of the components that rely on a setting have the same value—something that is hard to do with hard-coded values. Start the application and request the /Home/DisplaySingle URL to see the effect of the new action method and its reliance on an application setting, as illustrated by Figure 9-4.