Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 94 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
94
Dung lượng
16,63 MB
Nội dung
■Tip The WebConfigurationManager API is great for reading configuration settings out of your web.config file—it’s much easier than retrieving configuration settings from a database table. What’s more, WebConfigurationManager can write changes and new values back into your web.config file. However, for performance, scalability, and security reasons, 10 you should avoid writing changes to web.config frequently, and consider storing frequently updated settings (such as user preferences) in your application’s database instead. WebConfigurationManager is best for the sorts of settings that don’t change between deployments, such as server addresses and disk paths. Configuring Connection Strings Many web applications need to deal with database connection strings. Of course, you don’t want to hard-code them in your source code—it’s far more flexible and useful to keep connec- tion strings in a configuration file. ASP.NET has a special API for configuring connection strings. If you add entries to your web.config file’s <connectionStrings> node, such as the following: <configuration> <connectionStrings> <add name="MainDB" connectionString="Server=myServer;Database=someDB; "/> <add name="AuditingDB" connectionString="Server=audit01;Database=myDB; "/> </connectionStrings> </configuration> then you can access those values via WebConfigurationManager.ConnectionStrings. For example, you can use the following code to obtain a LINQ to SQL DataContext: string connectionString = WebConfigurationManager.ConnectionStrings["MainDB"]; var dataContext = new DataContext(connectionString); var query = from customer in dataContext.GetTable<Customer>() where // etc ■Note If you’re using an IoC container to instantia te your da ta access objects, you can usually configure connection strings (and any other settings for IoC components) using the IoC container instead. This was the technique demonstrated in Chapter 4. Configuring Arbitrary Key/Value Pairs If you need a way of configuring mail server addresses, disk paths, or other simple values that can vary between your development and production environments, and if you don’t want to CHAPTER 14 ■ DEPLOYMENT 499 10. Every time you write a change to web.config, it r ecy cles the application process. Also, for it even to be possible to wr ite changes to web.config, y our ASP.NET worker process obviously needs write access to that file. You may prefer not to give your worker processes that much power. 10078ch14.qxd 3/23/09 8:57 PM Page 499 configure those settings using an IoC container, you can add key/value pairs to your w eb.config f ile’s < appSettings> n ode—for example, <configuration> <appSettings> <add key="mailServer" value="smtp.example.com"/> <add key="mailServerPort" value="25"/> <add key="uploadedFilesDirectory" value="e:\web\data\uploadedFiles\"/> </appSettings> </configuration> Then you can access those values using WebConfigurationManager.AppSettings as follows: string host = WebConfigurationManager.AppSettings["mailServer"]; int port = int.Parse(WebConfigurationManager.AppSettings["mailServerPort"]); Configuring Arbitrary Data Structures Sometimes you’ll want to configure data structures more complex than simple key/value pairs. In the previous example, mailServer and mailServerPort were configured as two independent values, which is ugly, because logically they’re two halves of the same configuration setting. If you want a way of configuring arbitrary lists and hierarchies of structured settings, you can start simply by representing those settings as free-form XML in your web.config file’s <configuration> node—for example, <configuration> <mailServers> <server host="smtp1.example.com" portNumber="25"> <useFor domain="example.com"/> <useFor domain="staff.example.com"/> <useFor domain="alternative.example"/> </server> <server host="smtp2.example.com" portNumber="5870"> <useFor domain="*"/> </server> </mailServers> </configuration> N ote that ASP.NET has no native concept of a <mailServers> node —this is just arbitrary XML of my choice. N ext, cr eate an IConfigurationSectionHandler class that can understand this XML. You just need to implement a Create() method that receives the custom data as an XmlNode called section, and tr ansforms it into a strongly typed result. This example produces a list of MailServerEntry objects: public class MailServerEntry { public string Hostname { get; set; } public int PortNumber { get; set; } public List<string> ForDomains { get; set; } CHAPTER 14 ■ DEPLOYMENT500 10078ch14.qxd 3/23/09 8:57 PM Page 500 } public class MailServerConfigHandler : IConfigurationSectionHandler { public object Create(object parent, object configContext, XmlNode section) { return section.SelectNodes("server").Cast<XmlNode>() .Select(x => new MailServerEntry { Hostname = x.Attributes["host"].InnerText, PortNumber = int.Parse(x.Attributes["portNumber"].InnerText), ForDomains = x.SelectNodes("useFor") .Cast<XmlNode>() .Select(y => y.Attributes["domain"].InnerText) .ToList() }).ToList(); } } ■Tip Since ASP.NET 2.0, instead of creating an IConfigurationSectionHandler class, you have the alternative of using the newer ConfigurationSection API instead. That lets you put .NET attributes onto configuration wrapper classes, declaratively associating class properties with configuration attributes. How- ever, in my experience, the new API actually increases the amount of code you have to write. So, I prefer to implement IConfigurationSectionHandler manually, and to populate my configuration object using a quick and elegant LINQ query, as shown in this example. Finally, register your custom configuration section and its IConfigurationSectionHandler class by adding a new node to your web.config file’s <configSections> node: <configuration> <configSections> <section name="mailServers" type="namespace.MailServerConfigHandler, assembly"/> </configSections> </configuration> Then you can access your configuration data anywhere in your code using WebConfigurationManager.GetSection(): IList<MailServerEntry> servers = WebConfigurationManager.GetSection("mailServers") as IList<MailServerEntry>; O ne of the nice things about WebConfigurationManager.GetSection() is that, inter nally, it caches the r esult of y our IConfigurationSectionHandler’ s Create() method call, so it doesn ’ t repeat the XML parsing ev er y time a r equest needs to access that par ticular configur atio n section. CHAPTER 14 ■ DEPLOYMENT 501 10078ch14.qxd 3/23/09 8:57 PM Page 501 Controlling Compilation on the Server One particular web.config flag that you should pay attention to during deployment is <compilation>: <configuration> <system.web> <compilation debug="true"> </compilation> </system.web> </configuration> When the WebForms view engine loads and compiles one of your ASPX templates, it chooses between debug and release compilation modes according to the debug flag. If you leave the default setting in place (i.e., debug="true"), then the compiler does the following: • Makes sure you can step through the code line by line in the debugger by disabling a number of possible code compilation optimizations • Compiles each ASPX/ASCX file separately when it’s requested, rather than compiling many in a single batch (producing many more temporary assemblies, which unfortu- nately consume more memory) • Turns off request timeouts (letting you spend a long time in the debugger) • Instructs browsers not to cache any static resources served by WebResources.axd All these things are helpful during development and debugging, but adversely affect performance on your production server. Naturally, the solution is to flip this switch off when deploying to the production server (i.e., set debug="false"). If you’re deploying to IIS 7, you can use its .NET Compilation configuration tool (Figure 14-8), which edits this and other web.config settings on your behalf. Figure 14-8. Using IIS 7’s .NET Compilation tool to turn off the debug ASPX compilation mode CHAPTER 14 ■ DEPLOYMENT502 10078ch14.qxd 3/23/09 8:57 PM Page 502 Detecting Compiler Errors in Views Before Deployment As you know, ASPX and ASCX files are compiled on the fly as they are needed on the server. They aren’t compiled by Visual Studio when you select Build ➤ Build Solution or press F5. N ormally, the only way to check that none of your views cause compiler errors is to systemati- cally visit every possible action in your application to check that each possible view can be rendered. It can be embarrassing if a basic syntax error finds its way onto your production server because you didn’t happen to check that particular view during development. If you want to verify that all your views can compile without errors, then you can enable a special project option called MvcBuildViews. Open your ASP.NET MVC application’s project file ( YourApp.csproj) in a text editor such as Notepad, and change the MvcBuildViews option from false to true: <MvcBuildViews>true</MvcBuildViews> Save the updated .csproj file and return to Visual Studio. Now whenever you compile your application, Visual Studio will run a post-build step that also compiles all the .aspx, .ascx, and .Master views, which means you’ll be notified of any compiler errors. Detecting Compiler Errors in Views Only When Building in Release Mode Be aware that enabling this post-build step will make compilation take significantly longer. You might prefer to enable this option only when building in Release mode. That will help you to catch compiler errors before deploying, without suffering longer compile times during day-to-day development. To do this, open your application’s .csproj file in Notepad, find the <Target> node called AfterBuild (it’s near the end of the file), and then change its Condition attribute to the following: <Target Name="AfterBuild" Condition="'$(Configuration)'=='Release'"> <AspNetCompiler VirtualPath="temp" PhysicalPath="$(ProjectDir)\ \$(ProjectName)"/> </Target> Note that once you’ve done this, the <MvcBuildViews> node will be ignored and can even be removed entirely. Summary In this chapter, you considered many of the issues you’ll face when deploying an ASP.NET MVC application to a production web server. These include the process of installing IIS, deploying your application files, and making the routing system play nicely with the web server. It was a brief guide, but hopefully all you need to know in most deployment scenarios. If you want to become a genuine IIS expert, there’s much more you can learn about appli- cation health monitoring, pr ocess r ecy cling, tr ust levels , thr ottling bandwidth/CPU/memory usage, and so on. You can consult a dedicated IIS administration resource for more details about these . CHAPTER 14 ■ DEPLOYMENT 503 10078ch14.qxd 3/23/09 8:57 PM Page 503 10078ch14.qxd 3/23/09 8:57 PM Page 504 ASP.NET Platform Features ASP.NET MVC is not designed to stand alone. As a web development framework, it inherits much of its power from the underlying ASP.NET platform, and that in turn from the.NET Framework itself (Figure 15-1). Figure 15-1. ASP.NET MVC builds on more general infrastructure. Even though ASP.NET MVC’s notions of routing, controllers, and views are flexible enough to implement almost any piece of infrastructure you’ll need, to stop there would be missing the point. A good percentage of your work is already done, out of the box, if only you know how to leverage ASP.NET’s built-in raft of time-saving facilities. There are just two problems: Knowing what’s there: We’ve all done it—you struggle for days or weeks to invent the perfect authentication or globalization infrastructure, and then some well-meaning colleague points out that ASP.NET already has the feature; you just need to enable it in web.config. C urses! This ain’t WebForms: Much of ASP.NET’s infrastructure was designed with WebForms in mind, and not all of it translates cleanly into the new er MVC world. While some platform featur es still wor k flawlessly , others need the odd tw eak or workar ound, and some just don’t work or aren’t applicable any more. The goal of this chapter is to address both of those problems. You’ll learn about the most commonly used ASP.NET platform features that are relevant in an MVC application, as well as the tips and tr icks needed to o vercome compatibility problems. Even if you’re an ASP.NET 505 CHAPTER 15 10078ch15.qxd 3/23/09 9:02 PM Page 505 veteran, there’s a good chance you’ll find something you haven’t used yet. This chapter will c over the following: • Authentication—both Windows Authentication and Forms Authentication mechanisms • The Membership, Roles, and Profiles facilities • Authorization • Data caching • Site maps (for navigation) • Internationalization • Features for monitoring and improving performance Just one thing before we get started: this chapter doesn’t attempt to document all of these features in full detail—that would take hundreds of pages. Here, you’ll see the basic usage of each feature in an MVC context, with discussion of any MVC-specific issues. It should be just enough for you to decide whether the feature is right for you. When you decide to pursue a particular feature, you may wish to consult a dedicated ASP.NET 3.5 platform reference. I would recommend Pro ASP.NET 3.5 in C# 2008, Second Edition, by Matthew MacDonald and Mario Szpuszta (Apress, 2007). Windows Authentication In software terms, authentication means determining who somebody is. This is completely separate to authorization, which means determining whether a certain person is allowed to do a certain thing. Authorization usually happens after authentication. Appropriately, ASP.NET’s authentication facility is concerned only with securely identifying visitors to your site, setting up a security context in which you can decide what that particular visitor is allowed to do. The simplest way to do authentication is to delegate the task to IIS (but as I’ll explain shor tly, this is usually only suitable for intranet applications). Do this by specifying Windows Authentication in your web.config file, as follows: <configuration> <system.web> <authentication mode="Windows" /> </system.web> </configuration> ASP.NET will then r ely on IIS to establish a secur ity context for incoming r equests . IIS can authenticate incoming requests against the list of users known in your Windows domain or among the serv er’s existing local user accounts, using one of the following supported mechanisms: A nonymous : The visitor need not supply any cr edentials . Unauthenticated requests are mapped to a special anonymous user account. CHAPTER 15 ■ ASP.NET PLATFORM FEATURES506 10078ch15.qxd 3/23/09 9:02 PM Page 506 Basic: The server uses RFC 2617’s HTTP Basic authentication protocol, which causes the b rowser to pop up an Authentication Required prompt, into which the visitor enters a name and password. These are sent in plain text with the request, so you should only use HTTP Basic authentication over an SSL connection. Digest: Again, the server causes the browser to pop up an Authentication Required prompt, but this time the credentials are sent as a cryptographically secure hash, which is handy if you can’t use SSL. Unfortunately, this mechanism only works for web servers that are also domain controllers, and even then only with Internet Explorer (version 5.0 or later). Integrated: The server uses either Kerberos version 5 or NTLM authentication to establish identity transparently, without the visitor having to enter any credentials at all. This only works transparently when both the client and server machines are on the same Windows domain (or Windows domains configured to trust each other)—if not, it will cause an Authentication Required prompt. This mode is widely used in corporate LANs, but not so suitable for use across the public Internet. You can specify which of these options to allow using IIS 6 Manager (on your web site’s Properties screen, go to Directory Security ➤ “Authentication and access control”) or using IIS 7’s Authentication configuration tool, as shown in Figure 15-2. Figure 15-2. Authentication configuration screens for IIS 6 (left) and IIS 7 (right) ■Note If you’re using IIS 7 and some of these authentica tion mechanisms aren’t a vailable, you’ll need to enable them on your server. Go to Control Panel ➤ Programs and Features ➤ “Turn Windows features on and off” ➤ Internet Information Services ➤ World Wide Web Services ➤ Security. CHAPTER 15 ■ ASP.NET PLATFORM FEATURES 507 10078ch15.qxd 3/23/09 9:02 PM Page 507 Windows Authentication has a few clear advantages: • It takes very little effort to set up, mostly being a matter of configuring IIS. You need not implement any kind of login or logout UI in your MVC application. • Since it uses your centralized Windows domain credentials, there is no need to admin- ister a separate set of credentials, and users don’t need to remember yet another password. • The Integrated option means users don’t even need to slow down to enter a password, and identity is established securely without the need for SSL. The key limitation to Windows Authentication is that it’s usually suitable only for corpo- rate intranet applications, because you need to have a separate Windows domain account for each user (and obviously you won’t give out Windows domain accounts to everyone on the public Internet). For the same reason, you’re unlikely to let new users register themselves, or even provide a UI to let existing users change their passwords. Preventing or Limiting Anonymous Access When you’re using Windows Authentication, perhaps for an intranet application hosted in a Windows domain, it’s often reasonable to require authentication for all requests. That way, visitors are always logged in, and User.Identity.Name will always be populated with the visi- tor’s domain account name. To enforce this, be sure to configure IIS to disable anonymous access (Figure 15-2). However, if you want to allow unauthenticated access to certain application features (such as your site’s home page), but enforce Windows Authentication for other application features (such as administrative pages), then you need to configure IIS to allow both anony- mous access and one or more other authentication options (Figure 15-2). In this arrangement, anonymous access is considered to be the default. Authentication happens in the following scenarios: • The visitor is accessing a URL for which you’ve configured ASP.NET’s URL-based authorization system, UrlAuthorizationModule, not to allow anonymous visitors. This forces an HTTP 401 response, which causes the browser to perform authentication (opening an A uthentication Required prompt if needed). As you’ll see later, URL-based authorization is usually a bad choice for an ASP.NET MVC application. • The server is trying to access a file protected by the Windows access control list (ACL), and the ACL denies access to whatever identity you’ve configured Anonymous Authen- tication to use. Again, this causes IIS to send an HTTP 401 response. For an ASP.NET MVC application, you can only use ACLs to control access to the entire application, not to individual controllers or actions, because those controllers and actions don’t corre- spond to files on disk. • The visitor is accessing a controller or action method decorated with ASP.NET MVC’s [Authorize] filter . That authorization filter rejects anonymous access by sending back an HT TP 401 r esponse . Y ou can optionally specify other parameters that restrict access CHAPTER 15 ■ ASP.NET PLATFORM FEATURES508 10078ch15.qxd 3/23/09 9:02 PM Page 508 [...]... use a built-in NET profile provider called SqlProfileProvider It’s enabled by default in any blank new ASP MVC project, because web.config contains the following: ... database Creating a Custom Profile Provider As is usual for ASP NET’s provider model, you can create a custom profile provider by deriving a class from the abstract base class, ProfileProvider Unless you want to support profile management though the WAT or IIS 7’s NET Profiles configuration tool, you only need to add code to the GetPropertyValues() and SetPropertyValues() methods 527 100 78ch15.qxd 528 3/23/09... project, not a Visual Studio web application ASP.NET MVC applications are web applications, not web projects, so this proxy class won’t be generated If you really want the strongly typed proxy class, check out the Web Profile Builder project (http://code.msdn.microsoft.com/WebProfileBuilder) The framework also supports a notion of anonymous profiles, in which profile data is associated with unregistered... return a SettingsPropertyValueCollection var result = new SettingsPropertyValueCollection(); foreach (SettingsProperty prop in collection) { var spv = new SettingsPropertyValue(prop); if (userData != null) // Use user's profile data if available spv.PropertyValue = userData[prop.Name]; result.Add(spv); } return result; } public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection... 525 100 78ch15.qxd 526 3/23/09 9:02 PM Page 526 CHAPTER 15 I ASP.NET PLATFORM FEATURES Configuring, Reading, and Writing Profile Data Before you can read or write profile data, you need to define the structure of the data you want to work with Do this by adding a node under inside web.config—for example, . the underlying ASP. NET platform, and that in turn from the .NET Framework itself (Figure 15-1). Figure 15-1. ASP. NET MVC builds on more general infrastructure. Even though ASP. NET MVC s notions. DEPLOYMENT 503 100 78ch14.qxd 3/23/09 8:57 PM Page 503 100 78ch14.qxd 3/23/09 8:57 PM Page 504 ASP. NET Platform Features ASP. NET MVC is not designed to stand alone. As a web development framework, . can enable a special project option called MvcBuildViews. Open your ASP. NET MVC application’s project file ( YourApp.csproj) in a text editor such as Notepad, and change the MvcBuildViews option