ASP.NET 错误处理
作者 :Erik Reitan
下载 Wingtip Toys 示例项目 (C#) 或 下载电子书 (PDF)
本教程系列将介绍使用 ASP.NET 4.5 和 Microsoft Visual Studio Express 2013 for Web 生成 ASP.NET Web Forms应用程序的基础知识。 本教程系列随附了一个包含 C# 源代码的Visual Studio 2013项目。
在本教程中,你将修改 Wingtip Toys 示例应用程序,以包括错误处理和错误日志记录。 错误处理将允许应用程序正常处理错误并相应地显示错误消息。 错误日志记录可让你查找并修复已发生的错误。 本教程以上一教程“URL 路由”为基础,是 Wingtip Toys 教程系列的一部分。
学习内容:
- 如何将全局错误处理添加到应用程序的配置。
- 如何在应用程序、页面和代码级别添加错误处理。
- 如何记录错误以供以后查看。
- 如何显示不会危及安全性的错误消息。
- 如何实现错误日志记录模块和处理程序 (ELMAH) 错误日志记录。
概述
ASP.NET 应用程序必须能够以一致的方式处理执行期间发生的错误。 ASP.NET 使用公共语言运行时 (CLR) ,它提供了一种以统一方式通知应用程序错误的方法。 发生错误时,将引发异常。 异常是应用程序遇到的任何错误、条件或意外行为。
在 .NET Framework 中,异常是从 System.Exception
类继承的对象。 异常引发自发生问题的代码区域。 异常将调用堆栈传递到应用程序提供用于处理异常的代码的位置。 如果应用程序不处理异常,则强制浏览器显示错误详细信息。
最佳做法是在代码块中的代码级别Try
//Catch
Finally
处理 中的错误。 尝试放置这些块,以便用户可以在发生这些问题的上下文中更正问题。 如果错误处理块离发生错误的位置太远,则向用户提供解决问题所需的信息会变得更加困难。
Exception 类
Exception 类是异常从中继承的基类。 大多数异常对象是 Exception 类的某个派生类的实例,例如 类 SystemException
、 IndexOutOfRangeException
类或 ArgumentNullException
类。 Exception 类具有属性(如 StackTrace
属性、 InnerException
属性和 Message
属性),这些属性提供有关所发生错误的特定信息。
异常继承层次结构
运行时具有一组基本异常,这些异常派生自 SystemException
遇到异常时运行时引发的 类。 大多数继承自 Exception 类的类(如 IndexOutOfRangeException
类和 ArgumentNullException
类)不实现其他成员。 因此,可以在异常层次结构、异常名称和异常中包含的信息中找到异常最重要的信息。
异常处理层次结构
在 ASP.NET Web Forms应用程序中,可以根据特定的处理层次结构处理异常。 可在以下级别处理异常:
- 应用程序级别
- 页面级别
- 代码级别
当应用程序处理异常时,通常可以检索有关从 Exception 类继承的异常的其他信息,并将其显示给用户。 除了应用程序、页面和代码级别外,还可以在 HTTP 模块级别使用 IIS 自定义处理程序处理异常。
应用程序级别错误处理
可以通过修改应用程序的配置或在应用程序的 Global.asax 文件中添加Application_Error
处理程序,在应用程序级别处理默认错误。
可以通过向 Web.config 文件添加节customErrors
来处理默认错误和 HTTP 错误。 使用 customErrors
节可以指定发生错误时用户将被重定向到的默认页面。 它还允许指定特定状态代码错误的单个页面。
<configuration>
<system.web>
<customErrors mode="On" defaultRedirect="ErrorPage.aspx?handler=customErrors%20section%20-%20Web.config">
<error statusCode="404" redirect="ErrorPage.aspx?msg=404&handler=customErrors%20section%20-%20Web.config"/>
</customErrors>
</system.web>
</configuration>
遗憾的是,使用配置将用户重定向到其他页面时,你没有所发生错误的详细信息。
但是,可以通过将代码添加到 Global.asax 文件中的Application_Error
处理程序来捕获应用程序中任何位置发生的错误。
void Application_Error(object sender, EventArgs e)
{
Exception exc = Server.GetLastError();
if (exc is HttpUnhandledException)
{
// Pass the error on to the error page.
Server.Transfer("ErrorPage.aspx?handler=Application_Error%20-%20Global.asax", true);
}
}
页面级别错误事件处理
页面级处理程序将用户返回到发生错误的页面,但由于不维护控件实例,因此页面上不再有任何内容。 若要向应用程序的用户提供错误详细信息,必须专门将错误详细信息写入页面。
通常使用页面级错误处理程序来记录未经处理的错误或将用户带到可显示有用信息的页面。
此代码示例演示 ASP.NET 网页中 Error 事件的处理程序。 此处理程序捕获页中的块中 try
/catch
尚未处理的所有异常。
private void Page_Error(object sender, EventArgs e)
{
Exception exc = Server.GetLastError();
// Handle specific exception.
if (exc is HttpUnhandledException)
{
ErrorMsgTextBox.Text = "An error occurred on this page. Please verify your " +
"information to resolve the issue."
}
// Clear the error from the server.
Server.ClearError();
}
处理错误后,必须通过调用 ClearError
) 类 (HttpServerUtility
Server 对象的 方法来清除错误,否则将看到以前发生的错误。
代码级错误处理
try-catch 语句由 try 块组成,后跟一个或多个 catch 子句,这些子句指定不同异常的处理程序。 引发异常时,公共语言运行时 (CLR) 查找处理此异常的 catch 语句。 如果当前正在执行的方法不包含 catch 块,则 CLR 会查找调用当前方法的方法,依此查看调用堆栈。 如果未找到 catch 块,则 CLR 向用户显示未经处理的异常消息,并停止执行程序。
下面的代码示例演示了用于处理错误的常见方法try
finally
/catch
/。
try
{
file.ReadBlock(buffer, index, buffer.Length);
}
catch (FileNotFoundException e)
{
Server.Transfer("NoFileErrorPage.aspx", true);
}
catch (System.IO.IOException e)
{
Server.Transfer("IOErrorPage.aspx", true);
}
finally
{
if (file != null)
{
file.Close();
}
}
在上述代码中,try 块包含需要防范可能异常的代码。 执行块,直到引发异常或块成功完成为止。 FileNotFoundException
如果发生异常或IOException
异常,则执行将传输到其他页面。 然后,无论是否发生错误,都执行 finally 块中包含的代码。
添加错误日志记录支持
在将错误处理添加到 Wingtip Toys 示例应用程序之前,需要通过将类添加到逻辑文件夹来添加ExceptionUtility
错误日志记录支持。 通过执行此操作,每次应用程序处理错误时,错误详细信息都将添加到错误日志文件中。
右键单击 “逻辑 ”文件夹,然后选择“ 添加 ->新建项”。
随即出现“添加新项”对话框。选择左侧的 Visual C# ->Code 模板组。 然后,从中间列表中选择“ 类”并将其命名为 ExceptionUtility.cs。
选择“添加” 。 将显示新的类文件。
将现有代码替换为以下代码:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.IO; namespace WingtipToys.Logic { // Create our own utility for exceptions public sealed class ExceptionUtility { // All methods are static, so this can be private private ExceptionUtility() { } // Log an Exception public static void LogException(Exception exc, string source) { // Include logic for logging exceptions // Get the absolute path to the log file string logFile = "~/App_Data/ErrorLog.txt"; logFile = HttpContext.Current.Server.MapPath(logFile); // Open the log file for append and write the log StreamWriter sw = new StreamWriter(logFile, true); sw.WriteLine("********** {0} **********", DateTime.Now); if (exc.InnerException != null) { sw.Write("Inner Exception Type: "); sw.WriteLine(exc.InnerException.GetType().ToString()); sw.Write("Inner Exception: "); sw.WriteLine(exc.InnerException.Message); sw.Write("Inner Source: "); sw.WriteLine(exc.InnerException.Source); if (exc.InnerException.StackTrace != null) { sw.WriteLine("Inner Stack Trace: "); sw.WriteLine(exc.InnerException.StackTrace); } } sw.Write("Exception Type: "); sw.WriteLine(exc.GetType().ToString()); sw.WriteLine("Exception: " + exc.Message); sw.WriteLine("Source: " + source); sw.WriteLine("Stack Trace: "); if (exc.StackTrace != null) { sw.WriteLine(exc.StackTrace); sw.WriteLine(); } sw.Close(); } } }
发生异常时,可以通过调用 LogException
方法将异常写入异常日志文件。 此方法采用两个参数:异常对象和包含异常源详细信息的字符串。 异常日志将写入 App_Data 文件夹中 的ErrorLog.txt 文件。
添加错误页
在 Wingtip Toys 示例应用程序中,一个页面将用于显示错误。 错误页旨在向站点用户显示安全错误消息。 但是,如果用户是发出 HTTP 请求的开发人员,该请求正在代码所在的计算机上本地提供,则其他错误详细信息将显示在错误页上。
在解决方案资源管理器中右键单击 Wingtip Toys) ( 项目名称,然后选择“添加新>项”。
随即出现“添加新项”对话框。选择左侧的 Visual C# ->Web 模板组。 从中间列表中选择“ 具有母版页的 Web 窗体”,并将其命名为 ErrorPage.aspx。
单击“添加”。
选择 Site.Master 文件作为母版页,然后选择 “确定”。
将现有标记替换为以下内容:
<%@ Page Title="" Language="C#" AutoEventWireup="true" MasterPageFile="~/Site.Master" CodeBehind="ErrorPage.aspx.cs" Inherits="WingtipToys.ErrorPage" %> <asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server"> <h2>Error:</h2> <p></p> <asp:Label ID="FriendlyErrorMsg" runat="server" Text="Label" Font-Size="Large" style="color: red"></asp:Label> <asp:Panel ID="DetailedErrorPanel" runat="server" Visible="false"> <p> </p> <h4>Detailed Error:</h4> <p> <asp:Label ID="ErrorDetailedMsg" runat="server" Font-Size="Small" /><br /> </p> <h4>Error Handler:</h4> <p> <asp:Label ID="ErrorHandler" runat="server" Font-Size="Small" /><br /> </p> <h4>Detailed Error Message:</h4> <p> <asp:Label ID="InnerMessage" runat="server" Font-Size="Small" /><br /> </p> <p> <asp:Label ID="InnerTrace" runat="server" /> </p> </asp:Panel> </asp:Content>
替换代码隐藏 (ErrorPage.aspx.cs) 的现有代码,使其如下所示:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using WingtipToys.Logic; namespace WingtipToys { public partial class ErrorPage : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { // Create safe error messages. string generalErrorMsg = "A problem has occurred on this web site. Please try again. " + "If this error continues, please contact support."; string httpErrorMsg = "An HTTP error occurred. Page Not found. Please try again."; string unhandledErrorMsg = "The error was unhandled by application code."; // Display safe error message. FriendlyErrorMsg.Text = generalErrorMsg; // Determine where error was handled. string errorHandler = Request.QueryString["handler"]; if (errorHandler == null) { errorHandler = "Error Page"; } // Get the last error from the server. Exception ex = Server.GetLastError(); // Get the error number passed as a querystring value. string errorMsg = Request.QueryString["msg"]; if (errorMsg == "404") { ex = new HttpException(404, httpErrorMsg, ex); FriendlyErrorMsg.Text = ex.Message; } // If the exception no longer exists, create a generic exception. if (ex == null) { ex = new Exception(unhandledErrorMsg); } // Show error details to only you (developer). LOCAL ACCESS ONLY. if (Request.IsLocal) { // Detailed Error Message. ErrorDetailedMsg.Text = ex.Message; // Show where the error was handled. ErrorHandler.Text = errorHandler; // Show local access details. DetailedErrorPanel.Visible = true; if (ex.InnerException != null) { InnerMessage.Text = ex.GetType().ToString() + "<br/>" + ex.InnerException.Message; InnerTrace.Text = ex.InnerException.StackTrace; } else { InnerMessage.Text = ex.GetType().ToString(); if (ex.StackTrace != null) { InnerTrace.Text = ex.StackTrace.ToString().TrimStart(); } } } // Log the exception. ExceptionUtility.LogException(ex, errorHandler); // Clear the error from the server. Server.ClearError(); } } }
显示错误页时,将 Page_Load
执行事件处理程序。 在 Page_Load
处理程序中,确定第一次处理错误的位置。 然后,通过调用 GetLastError
Server 对象的 方法来确定发生的最后一个错误。 如果异常不再存在,则会创建一个泛型异常。 然后,如果 HTTP 请求是在本地发出的,则会显示所有错误详细信息。 在这种情况下,只有运行 Web 应用程序的本地计算机才会看到这些错误详细信息。 显示错误信息后,会将错误添加到日志文件,并从服务器中清除错误。
显示应用程序的未经处理的错误消息
通过将节 customErrors
添加到 Web.config 文件,可以快速处理整个应用程序中发生的简单错误。 还可以根据错误的状态代码值指定如何处理错误,例如 404 - 找不到文件。
更新配置
通过将节添加到 customErrors
Web.config 文件来更新配置。
在解决方案资源管理器中,查找并打开 Wingtip Toys 示例应用程序根目录下 Web.config文件。
将
customErrors
节添加到节点内的 Web.config 文件中,<system.web>
如下所示:<configuration> <system.web> <customErrors mode="On" defaultRedirect="ErrorPage.aspx?handler=customErrors%20section%20-%20Web.config"> <error statusCode="404" redirect="ErrorPage.aspx?msg=404&handler=customErrors%20section%20-%20Web.config"/> </customErrors> </system.web> </configuration>
保存 Web.config 文件。
节 customErrors
指定模式,该模式设置为“开”。 它还指定 , defaultRedirect
它告知应用程序在发生错误时要导航到哪个页面。 此外,还添加了一个特定的 error 元素,该元素指定在找不到页面时如何处理 404 错误。 在本教程的后面部分,你将添加其他错误处理,这些错误处理将在应用程序级别捕获错误的详细信息。
运行应用程序
现在可以运行应用程序以查看更新的路由。
按 F5 运行 Wingtip Toys 示例应用程序。
浏览器将打开并显示 Default.aspx 页。在浏览器中输入以下 URL, (确保使用端口号) :
https://localhost:44300/NoPage.aspx
查看浏览器中显示的 ErrorPage.aspx 。
请求 不存在的 NoPage.aspx 页时,如果提供了其他详细信息,则错误页将显示简单的错误消息和详细的错误信息。 但是,如果用户从远程位置请求了不存在的页面,则错误页只会以红色显示错误消息。
包括用于测试的异常
若要验证发生错误时应用程序将如何运行,可以特意在 ASP.NET 中创建错误条件。 在 Wingtip Toys 示例应用程序中,当加载默认页面以查看发生的情况时,将引发测试异常。
在 Visual Studio 中打开 Default.aspx 页的代码隐藏。
将显示 Default.aspx.cs 代码隐藏页。在处理程序中
Page_Load
,添加代码,使处理程序如下所示:protected void Page_Load(object sender, EventArgs e) { throw new InvalidOperationException("An InvalidOperationException " + "occurred in the Page_Load handler on the Default.aspx page."); }
可以创建各种不同类型的异常。 在上面的代码中,你将在加载 Default.aspx 页面时创建 InvalidOperationException
。
运行应用程序
可以运行应用程序以查看应用程序如何处理异常。
按 Ctrl+F5 运行 Wingtip Toys 示例应用程序。
应用程序将引发 InvalidOperationException。注意
必须按 Ctrl+F5 才能在不中断代码的情况下显示页面,才能在 Visual Studio 中查看错误的来源。
查看浏览器中显示的 ErrorPage.aspx 。
如错误详细信息中所示,异常被 Web.config 文件中的 节捕获customError
。
添加 Application-Level 错误处理
可以在应用程序级别捕获错误并检索错误详细信息,而不是使用 customErrors
Web.config 文件中的 部分捕获异常(其中获取的异常信息很少)。
在解决方案资源管理器中,找到并打开 Global.asax.cs 文件。
添加 Application_Error 处理程序,使其如下所示:
void Application_Error(object sender, EventArgs e) { // Code that runs when an unhandled error occurs. // Get last error from the server Exception exc = Server.GetLastError(); if (exc is HttpUnhandledException) { if (exc.InnerException != null) { exc = new Exception(exc.InnerException.Message); Server.Transfer("ErrorPage.aspx?handler=Application_Error%20-%20Global.asax", true); } } }
当应用程序中发生错误时, Application_Error
将调用 处理程序。 在此处理程序中,将检索并查看最后一个异常。 如果异常未经处理,并且异常包含内部异常详细信息 (即 InnerException
,) 不为 null,则应用程序会将执行转移到显示异常详细信息的错误页。
运行应用程序
可以通过在应用程序级别处理异常来运行应用程序以查看提供的其他错误详细信息。
按 Ctrl+F5 运行 Wingtip Toys 示例应用程序。
应用程序引发InvalidOperationException
。查看浏览器中显示的 ErrorPage.aspx 。
添加 Page-Level 错误处理
通过使用向页面的 指令添加 ErrorPage
属性 @Page
,或者将事件处理程序添加到页面的代码隐藏,可以将页面级错误处理添加到 Page_Error
页面。 在本部分中,将添加一个 Page_Error
事件处理程序,用于将执行传输到 ErrorPage.aspx 页。
在解决方案资源管理器中,找到并打开 Default.aspx.cs 文件。
添加处理程序
Page_Error
,使代码隐藏如下所示:using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace WingtipToys { public partial class _Default : Page { protected void Page_Load(object sender, EventArgs e) { throw new InvalidOperationException("An InvalidOperationException " + "occurred in the Page_Load handler on the Default.aspx page."); } private void Page_Error(object sender, EventArgs e) { // Get last error from the server. Exception exc = Server.GetLastError(); // Handle specific exception. if (exc is InvalidOperationException) { // Pass the error on to the error page. Server.Transfer("ErrorPage.aspx?handler=Page_Error%20-%20Default.aspx", true); } } } }
当页面上发生错误时, Page_Error
将调用 事件处理程序。 在此处理程序中,将检索并查看最后一个异常。 如果发生, InvalidOperationException
事件处理程序会将 Page_Error
执行传输到显示异常详细信息的错误页。
运行应用程序
现在可以运行应用程序以查看更新的路由。
按 Ctrl+F5 运行 Wingtip Toys 示例应用程序。
应用程序引发InvalidOperationException
。查看浏览器中显示的 ErrorPage.aspx 。
关闭浏览器窗口。
删除用于测试的异常
若要允许 Wingtip Toys 示例应用程序在不引发本教程前面添加的异常的情况下正常运行,请删除该异常。
打开 Default.aspx 页的代码隐藏。
在处理程序中
Page_Load
,删除引发异常的代码,以便处理程序如下所示:protected void Page_Load(object sender, EventArgs e) { }
添加 Code-Level 错误日志记录
如本教程前面所述,可以添加 try/catch 语句来尝试运行代码部分并处理发生的第一个错误。 在此示例中,将仅将错误详细信息写入错误日志文件,以便以后可以查看错误。
在 解决方案资源管理器 的逻辑文件夹中,找到并打开 PayPalFunctions.cs 文件。
HttpCall
更新 方法,使代码如下所示:public string HttpCall(string NvpRequest) { string url = pEndPointURL; string strPost = NvpRequest + "&" + buildCredentialsNVPString(); strPost = strPost + "&BUTTONSOURCE=" + HttpUtility.UrlEncode(BNCode); HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url); objRequest.Timeout = Timeout; objRequest.Method = "POST"; objRequest.ContentLength = strPost.Length; try { using (StreamWriter myWriter = new StreamWriter(objRequest.GetRequestStream())) { myWriter.Write(strPost); } } catch (Exception e) { // Log the exception. WingtipToys.Logic.ExceptionUtility.LogException(e, "HttpCall in PayPalFunction.cs"); } //Retrieve the Response returned from the NVP API call to PayPal. HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse(); string result; using (StreamReader sr = new StreamReader(objResponse.GetResponseStream())) { result = sr.ReadToEnd(); } return result; }
上述代码调用 LogException
类中包含的 ExceptionUtility
方法。 本教程前面已将 ExceptionUtility.cs 类文件添加到 逻辑 文件夹。 LogException
方法采用两个参数。 第一个参数是异常对象。 第二个参数是用于识别错误源的字符串。
检查错误日志记录信息
如前所述,可以使用错误日志来确定应首先修复应用程序中的错误。 当然,只会记录已捕获并写入错误日志的错误。
在 解决方案资源管理器 中,查找并打开 App_Data 文件夹中的ErrorLog.txt 文件。
可能需要从解决方案资源管理器顶部选择“显示所有文件”选项或“刷新”选项才能查看 ErrorLog.txt 文件。查看 Visual Studio 中显示的错误日志:
安全错误消息
请务必注意,当应用程序显示错误消息时,它不应透露恶意用户可能认为有助于攻击应用程序的信息。 例如,如果应用程序尝试写入数据库失败,它不应显示包含其正在使用的用户名的错误消息。 出于此原因,向用户显示红色的一般错误消息。 所有其他错误详细信息仅显示给本地计算机上的开发人员。
使用 ELMAH
ELMAH (错误日志记录模块和处理程序) 是一种错误日志记录工具,可作为 NuGet 包插入到 ASP.NET 应用程序中。 ELMAH 提供以下功能:
- 记录未经处理的异常。
- 用于查看重新编码的未经处理的异常的整个日志的网页。
- 用于查看每个记录的异常的完整详细信息的网页。
- 每个错误发生时的电子邮件通知。
- 日志中最近 15 个错误的 RSS 源。
必须先安装 ELMAH,然后才能使用 ELMAH。 使用 NuGet 包安装程序可以轻松完成此操作。 如本教程系列前面所述,NuGet 是一个 Visual Studio 扩展,可用于在 Visual Studio 中轻松安装和更新开放源代码库和工具。
在 Visual Studio 中的“ 工具 ”菜单中,选择“ NuGet 包管理器>”“管理解决方案的 NuGet 包”。
“ 管理 NuGet 包 ”对话框显示在 Visual Studio 中。
在 “管理 NuGet 包 ”对话框中,展开左侧的“ 联机 ”,然后选择“ nuget.org”。然后,从联机可用包列表中查找并安装 ELMAH 包。
需要有 Internet 连接才能下载包。
在 “选择项目 ”对话框中,确保已选中 “WingtipToys ”选择,然后单击“ 确定”。
如果需要,请在“管理 NuGet 包”对话框中单击“关闭”。
如果 Visual Studio 请求重新加载任何打开的文件,请选择“全部是”。
ELMAH 包在项目根目录处的 Web.config 文件中为自己添加条目。 如果 Visual Studio 询问是否要重新加载修改的 Web.config 文件,请单击“ 是”。
ELMAH 现在已准备好存储发生的任何未处理错误。
查看 ELMAH 日志
查看 ELMAH 日志非常简单,但首先将创建一个未经处理的异常,该异常将记录在 ELMAH 日志中。
按 Ctrl+F5 运行 Wingtip Toys 示例应用程序。
若要将未经处理的异常写入 ELMAH 日志,请在浏览器中使用端口号) 导航到以下 URL (:
https://localhost:44300/NoPage.aspx
将显示错误页。若要显示 ELMAH 日志,请使用端口号) 在浏览器中导航到以下 URL (:
https://localhost:44300/elmah.axd
总结
本教程介绍了如何在应用程序级别、页面级别和代码级别处理错误。 你还了解了如何记录已处理和未处理的错误,以供以后查看。 你添加了 ELMAH 实用工具,以便使用 NuGet 向应用程序提供异常日志记录和通知。 此外,你还了解了安全错误消息的重要性。
教程系列结论
感谢你继续关注。 我希望这组教程能帮助你更熟悉 ASP.NET Web Forms。 如果需要有关 ASP.NET 4.5 和 Visual Studio 2013 中提供的Web Forms功能的详细信息,请参阅Visual Studio 2013发行说明 ASP.NET 和 Web 工具。 此外,请务必查看 后续步骤 部分中提到的教程,并明确尝试 免费的 Azure 试用版。
后续步骤
若要详细了解如何将 Web 应用程序部署到 Microsoft Azure,请参阅将具有成员资格、OAuth 和SQL 数据库的安全 ASP.NET Web Forms应用部署到 Azure 网站。
免费试用版
Microsoft Azure - 免费试用版
将网站发布到 Microsoft Azure 将节省时间、维护和费用。 这是将 Web 应用部署到 Azure 的快速过程。 需要维护和监视 Web 应用时,Azure 提供各种工具和服务。 在 Azure 中管理数据、流量、标识、备份、消息传递、媒体和性能。 而且,所有这些内容都是以非常经济高效的方法提供的。
其他资源
ASP.NET 运行状况监视的日志记录错误详细信息
ELMAH
致谢
我要感谢以下为本教程系列内容做出重要贡献的人员:
- Alberto Poblacion, MVP & MCT, 西班牙
- 亚历克斯·特森,荷兰 (推特: @alexthissen)
- 安德烈·图尔尼尔,美国
- Apurva Joshi,Microsoft
- 博扬·弗尔霍夫尼克,斯洛文尼亚
- 巴西布鲁诺·桑尼诺 (推特: @bsonnino)
- 巴西卡洛斯·多斯桑托斯
- 戴夫·坎贝尔,美国 (推特: @windowsdevnews)
- Jon Galloway,Microsoft (twitter: @jongalloway)
- 迈克尔·夏普斯,美国 (推特: @mrsharps)
- Mike Pope
- 米切尔·塞勒斯, 美国 (推特: @MitchelSellers)
- Paul Cociuba, Microsoft
- 葡萄牙保罗·莫尔加多
- Pranav Rastogi, Microsoft
- Tim Ammann,Microsoft
- Tom Dykstra,Microsoft
社区贡献
- 格雷厄姆·门迪克· (@grahammendick)
MSDN 上的 Visual Studio 2012 相关代码示例: Navigation Wingtip Toys - 詹姆斯·查尼· jchaney@agvance.net ()
MSDN 上的 Visual Studio 2012 相关代码示例:Visual Basic 中的 ASP.NET 4.5 Web Forms 教程系列 - Andrielle Azevedo - Microsoft 技术受众参与者 (推特: @driazevedo)
Visual Studio 2012 translation: Iniciando com ASP.NET Web Forms 4.5 - Parte 1 - Introdução e Visão Geral