.NET Core + ASP.NET Core Training Course Session 7
.NET Core What we learned? Session 6 Overview • Overview on HTTP Protocol • Introducing ASP.NET Core 1.0 • Starting up the ASP.NET core applications • Startup Class Anatomy • Middleware in ASP.NET core
.NET Core What we’ll learn today? Session 7 Agenda • Working with Static Files • Error Handling • Logging
.NET Core Content root Static files The content root is the base path to any content used by the app, such as its views and web content. By default the content root is the same as application base path for the executable hosting the app; an alternative location can be specified with WebHostBuilder.
.NET Core Web root Static files The web root of your app is the directory in your project for public, static resources like css, js, and image files. The static files middleware will only serve files from the web root directory (and sub- directories) by default. The web root path defaults to <content root>/wwwroot, but you can specify a different location using the WebHostBuilder. http://<app>/images/<imageFileName> http://localhost:9189/images/banner3.svg
.NET Core Working with Static Files Static files Static files, such as HTML, CSS, image, and JavaScript, are assets that an ASP.NET Core app can serve directly to clients.
.NET Core Working with Static Files Static files The static file middleware can be configured by adding a dependency on the Microsoft.AspNetCore.StaticFiles package to your project and then calling the UseStaticFiles extension method from Startup.Configure: “Microsoft.AspNetCore.StaticFiles” must be added in the project.json file
.NET Core Working with Static Files Static files In case of serving static files outside the wwwroot directory: http://<app>/StaticFiles/test.png
.NET Core Static file authorization Static files The static file module provides no authorization checks. Any files served by it, including those under wwwroot are publicly available. To serve files based on authorization: • Store them outside of wwwroot and any directory accessible to the static file middleware and • Serve them through a controller action, returning a FileResult where authorization is applied
.NET Core Enabling directory browsing Static files Directory browsing allows the user of your web app to see a list of directories and files within a specified directory. Directory browsing is disabled by default for security reasons. To enable directory browsing, call the UseDirectoryBrowser extension method from Startup.Configure:
.NET Core Enabling directory browsing Static files
.NET Core Enabling directory browsing Static files And add required services by calling AddDirectoryBrowser extension method from Startup.ConfigureServices:
.NET Core Serving a default document Static files Setting a default home page gives site visitors a place to start when visiting your site. • UseDefaultFiles must be called before UseStaticFiles • UseDefaultFiles is a URL re-writer that doesn’t actually serve the file • To enable the static file middleware (UseStaticFiles) to serve the file The first file found from the list will be served as if the request 1. Default.htm 2. Default.html 3. Index.htm 4. Index.html
.NET Core UseFileServer Static files UseFileServer combines the functionality of UseStaticFiles, UseDefaultFiles, and UseDirectoryBrowser. • Enables static files and the default file to be served, but does not allow directory browsing: app.UseFileServer(); • Enables static files, default files and directory browsing: app.UseFileServer(enableDirectoryBrowsing: true);
.NET Core UseFileServer Static files As with UseStaticFiles, UseDefaultFiles, and UseDirectoryBrowser, if you wish to serve files that exist outside the web root, you instantiate and configure an FileServerOptions object that you pass as a parameter to UseFileServer.
.NET Core UseFileServer Static files If enableDirectoryBrowsing is set to true you are required to call AddDirectoryBrowser extension method from Startup.ConfigureServices: UseDefaultFiles and UseDirectoryBrowser will take the url http://<app>/StaticFiles without the trailing slash and cause a client side redirect to http://<app>/StaticFiles/ (adding the trailing slash). Without the trailing slash relative URLs within the documents would be incorrect.
.NET Core FileExtensionContentTypeProvider Static files contains a collection that maps file extensions to MIME content types.
.NET Core Non-standard content types Static files The ASP.NET static file middleware understands almost 400 known file content types. Unknown types will serve as 404 error. Enabling ServeUnknownFileTypes is a security risk and using it is discouraged. FileExtensionContentTypeProvider provides a safer alternative to serving files with non-standard extensions. The following code enables serving unknown types and will render the unknown file as an image.
.NET Core Considerations Static files • UseDirectoryBrowser and UseStaticFiles can leak secrets. • Be careful about which directories you enable with UseStaticFiles or UseDirectoryBrowser as the entire directory and all sub-directories will be accessible. • The URLs for content exposed with UseDirectoryBrowser and UseStaticFiles are subject to the case sensitivity and character restrictions of their underlying file system. For example, Windows is case insensitive, but Mac and Linux are not.
.NET Core Considerations Static files • ASP.NET Core applications hosted in IIS use the ASP.NET Core Module to forward all requests to the application including requests for static files. The IIS static file handler is not used because it doesn’t get a chance to handle requests before they are handled by the ASP.NET Core Module. • To remove the IIS static file handler (at the server or website level): • Navigate to the Modules feature • Select StaticFileModule in the list • Tap Remove in the Actions sidebar • Code files (including c# and Razor) should be placed outside of the app project’s web root (wwwroot by default).
.NET Core Configuring an Exception Handling Page Error Handling When errors occur in your ASP.NET app, we can handle them with Configuring an Exception Handling Page in the Startup class’s Configure() method. We can add a simple exception page (During Development. All that’s required is to add a dependency on Microsoft.AspNetCore.Diagnostics to the project and then add one line to Configure() in Startup.cs: And When not in development, app.UseExceptionHandler("/Error");
.NET Core Configuring an Exception Handling Page Error Handling
.NET Core Configuring Status Code Pages Error Handling You can configure the StatusCodePagesMiddleware to provide a rich status code page for HTTP status codes such as 500 (Internal Server Error) or 404 (Not Found) to the Configure method, this middleware adds very simple, text-only handlers for common status codes. app.UseStatusCodePages();
.NET Core Configuring Status Code Pages Error Handling pass it a content type and a format string: The middleware can handle redirects (with either relative or absolute URL paths), passing the status code as part of the URL: (302 / Found)
.NET Core Configuring Status Code Pages Error Handling the middleware can re-execute the request from a new path format string: will still return the original status code to the browser, but will also execute the handler given at the path specified If you need to disable status code pages for certain requests
.NET Core Limitations of Exception Handling During Client-Server Interaction Error Handling Web apps have certain limitations to their exception handling capabilities because of the nature of disconnected HTTP requests and responses. 1. Once the headers for a response have been sent, you cannot change the response’s status code, nor can any exception pages or handlers run. The response must be completed or the connection aborted. 2. If the client disconnects mid-response, you cannot send them the rest of the content of that response. 3. There is always the possibility of an exception occurring one layer below your exception handling layer. Don’t forget, exception handling pages can have exceptions, too. It’s often a good idea for production error pages to consist of purely static content.
.NET Core Server Exception Handling Error Handling • If the server catches an exception before the headers have been sent it will send a 500 Internal Server Error response with no body. • If it catches an exception after the headers have been sent it must close the connection. • Requests that are not handled by your app will be handled by the server, and any exception that occurs will be handled by the server’s exception handling. • Any custom error pages or exception handling middleware or filters you have configured for your app will not affect this behavior.
.NET Core Startup Exception Handling Error Handling • Only the hosting layer can handle exceptions that take place during app startup. • Exceptions that occur in your app’s startup can also impact server behavior. • For example, to enable SSL in Kestrel, one must configure the server with KestrelServerOptions.UseHttps(). If an exception happens before this line in Startup, then by default hosting will catch the exception, start the server, and display an error page on the non-SSL port. If an exception happens after that line executes, then the error page will be served over HTTPS instead.
.NET Core Logging Logging ASP.NET Core has built-in support for logging, and allows developers to easily leverage their preferred logging framework’s functionality as well. Adding logging is done by requesting either an ILoggerFactory or an ILogger<T> via Dependency Injection. If an ILoggerFactory is requested, a logger must be created using its CreateLogger method.
.NET Core Logging Logging When a logger is created, a category name must be provided. The category name specifies the source of the logging events. By convention this string is hierarchical, with categories separated by dot (.) characters. In your real world applications, you will want to add logging based on application-level, not framework-level, events.
.NET Core Logging Logging
.NET Core Logging Verbosity Levels Logging Trace Used for the most detailed log messages, typically only valuable to a developer debugging an issue. These messages may contain sensitive application data and so should not be enabled in a production environment. Disabled by default. Example: Credentials: {"User":"someuser", "Password":"P@ssword"} Debug These messages have short-term usefulness during development. They contain information that may be useful for debugging, but have no long-term value. This is the default most verbose level of logging. Example: Entering method Configure with flag set to true Information These messages are used to track the general flow of the application. These logs should have some long term value, as opposed to Verbose level messages, which do not. Example: Request received for path /foo
.NET Core Logging Verbosity Levels Logging Warning The Warning level should be used for abnormal or unexpected events in the application flow. These may include errors or other conditions that do not cause the application to stop, but which may need to be investigated in the future. Handled exceptions are a common place to use the Warning log level. Examples: Login failed for IP 127.0.0.1 or FileNotFoundException for file foo.txt Error An error should be logged when the current flow of the application must stop due to some failure, such as an exception that cannot be handled or recovered from. These messages should indicate a failure in the current activity or operation (such as the current HTTP request), not an application-wide failure. Example: Cannot insert record due to duplicate key violation
.NET Core Logging Verbosity Levels Logging Critical A critical log level should be reserved for unrecoverable application or system crashes, or catastrophic failure that requires immediate attention. Examples: data loss scenarios, out of disk space The Logging package provides helper extension methods for each LogLevel value, allowing you to call, for example, LogInformation, rather than the more verbose Log(LogLevel.Information, ...) method.
.NET Core Logging Verbosity Levels Logging Each of the LogLevel-specific extension methods has several overloads, allowing you to pass in some or all of the following parameters: string data The message to log. EventId eventId A numeric id to associate with the log, which can be used to associate a series of logged events with one another. Event IDs should be static and specific to a particular kind of event that is being logged. For instance, you might associate adding an item to a shopping cart as event id 1000 and completing a purchase as event id 1001. This allows intelligent filtering and processing of log statements. string format A format string for the log message. object[] args An array of objects to format. Exception error An exception instance to log.
.NET Core Logging Logging Some loggers, such as the built-in ConsoleLogger, will ignore the eventId parameter.
.NET Core Logging Logging It is recommended that you perform application logging at the level of application and its APIs, not at the level of the framework
.NET Core Configuring Logging in Application Logging To configure logging in your ASP.NET Core application, you should resolve ILoggerFactory in the Configure method of Startup class. Note Optionally it’s possible to configure logging when setting up Hosting, rather than in Startup. The console, debug, and event log loggers allow you to specify the minimum logging level at which those loggers should write log messages (for example, logLevel => logLevel >= LogLevel.Warning ) or (category, loglevel) => category.Contains("MyController") && loglevel >= LogLevel.Trace
.NET Core Configuring TraceSource Logging Logging When running on the full .NET Framework you can configuring logging to use the existing System.Diagnostics.TraceSource libraries and providers, including easy access to the Windows event log. add the Microsoft.Extensions.Logging.TraceSource package to project (in project.json)
.NET Core Configuring TraceSource Logging Logging The yellow line with the “warn: ” prefix, along with the following line, is output by the ConsoleLogger. The next line, beginning with “TodoApi.Controllers.TodoController”, is output from the TraceSource logger.
.NET Core Configuring Other Providers Logging elmah.io - provider for the elmah.io service Loggr - provider for the Loggr service NLog - provider for the NLog library Serilog - provider for the Serilog library
.NET Core Logging Recommendations Logging 1. Log using the correct LogLevel. This will allow you to consume and route logging output appropriately based on the importance of the messages. 2. Log information that will enable errors to be identified quickly. Avoid logging irrelevant or redundant information. 3. Keep log messages concise without sacrificing important information. 4. Although loggers will not log if disabled, consider adding code guards around logging methods to prevent extra method calls and log message setup overhead, especially within loops and performance critical methods. 5. Name your loggers with a distinct prefix so they can easily be filtered or disabled. Remember the Create<T> extension will create loggers named with the full name of the class. 6. Use Scopes sparingly, and only for actions with a bounded start and end. For example, the framework provides a scope around MVC actions. Avoid nesting many scopes within one another. 7. Application logging code should be related to the business concerns of the application. Increase the logging verbosity to reveal additional framework-related concerns, rather than implementing yourself.
.NET Core Demo Demo

.NET Core, ASP.NET Core Course, Session 7

  • 1.
    .NET Core +ASP.NET Core Training Course Session 7
  • 2.
    .NET Core What welearned? Session 6 Overview • Overview on HTTP Protocol • Introducing ASP.NET Core 1.0 • Starting up the ASP.NET core applications • Startup Class Anatomy • Middleware in ASP.NET core
  • 3.
    .NET Core What we’lllearn today? Session 7 Agenda • Working with Static Files • Error Handling • Logging
  • 4.
    .NET Core Content root Staticfiles The content root is the base path to any content used by the app, such as its views and web content. By default the content root is the same as application base path for the executable hosting the app; an alternative location can be specified with WebHostBuilder.
  • 5.
    .NET Core Web root Staticfiles The web root of your app is the directory in your project for public, static resources like css, js, and image files. The static files middleware will only serve files from the web root directory (and sub- directories) by default. The web root path defaults to <content root>/wwwroot, but you can specify a different location using the WebHostBuilder. http://<app>/images/<imageFileName> http://localhost:9189/images/banner3.svg
  • 6.
    .NET Core Working withStatic Files Static files Static files, such as HTML, CSS, image, and JavaScript, are assets that an ASP.NET Core app can serve directly to clients.
  • 7.
    .NET Core Working withStatic Files Static files The static file middleware can be configured by adding a dependency on the Microsoft.AspNetCore.StaticFiles package to your project and then calling the UseStaticFiles extension method from Startup.Configure: “Microsoft.AspNetCore.StaticFiles” must be added in the project.json file
  • 8.
    .NET Core Working withStatic Files Static files In case of serving static files outside the wwwroot directory: http://<app>/StaticFiles/test.png
  • 9.
    .NET Core Static fileauthorization Static files The static file module provides no authorization checks. Any files served by it, including those under wwwroot are publicly available. To serve files based on authorization: • Store them outside of wwwroot and any directory accessible to the static file middleware and • Serve them through a controller action, returning a FileResult where authorization is applied
  • 10.
    .NET Core Enabling directorybrowsing Static files Directory browsing allows the user of your web app to see a list of directories and files within a specified directory. Directory browsing is disabled by default for security reasons. To enable directory browsing, call the UseDirectoryBrowser extension method from Startup.Configure:
  • 11.
    .NET Core Enabling directorybrowsing Static files
  • 12.
    .NET Core Enabling directorybrowsing Static files And add required services by calling AddDirectoryBrowser extension method from Startup.ConfigureServices:
  • 13.
    .NET Core Serving adefault document Static files Setting a default home page gives site visitors a place to start when visiting your site. • UseDefaultFiles must be called before UseStaticFiles • UseDefaultFiles is a URL re-writer that doesn’t actually serve the file • To enable the static file middleware (UseStaticFiles) to serve the file The first file found from the list will be served as if the request 1. Default.htm 2. Default.html 3. Index.htm 4. Index.html
  • 14.
    .NET Core UseFileServer Static files UseFileServercombines the functionality of UseStaticFiles, UseDefaultFiles, and UseDirectoryBrowser. • Enables static files and the default file to be served, but does not allow directory browsing: app.UseFileServer(); • Enables static files, default files and directory browsing: app.UseFileServer(enableDirectoryBrowsing: true);
  • 15.
    .NET Core UseFileServer Static files Aswith UseStaticFiles, UseDefaultFiles, and UseDirectoryBrowser, if you wish to serve files that exist outside the web root, you instantiate and configure an FileServerOptions object that you pass as a parameter to UseFileServer.
  • 16.
    .NET Core UseFileServer Static files IfenableDirectoryBrowsing is set to true you are required to call AddDirectoryBrowser extension method from Startup.ConfigureServices: UseDefaultFiles and UseDirectoryBrowser will take the url http://<app>/StaticFiles without the trailing slash and cause a client side redirect to http://<app>/StaticFiles/ (adding the trailing slash). Without the trailing slash relative URLs within the documents would be incorrect.
  • 17.
    .NET Core FileExtensionContentTypeProvider Static files containsa collection that maps file extensions to MIME content types.
  • 18.
    .NET Core Non-standard contenttypes Static files The ASP.NET static file middleware understands almost 400 known file content types. Unknown types will serve as 404 error. Enabling ServeUnknownFileTypes is a security risk and using it is discouraged. FileExtensionContentTypeProvider provides a safer alternative to serving files with non-standard extensions. The following code enables serving unknown types and will render the unknown file as an image.
  • 19.
    .NET Core Considerations Static files •UseDirectoryBrowser and UseStaticFiles can leak secrets. • Be careful about which directories you enable with UseStaticFiles or UseDirectoryBrowser as the entire directory and all sub-directories will be accessible. • The URLs for content exposed with UseDirectoryBrowser and UseStaticFiles are subject to the case sensitivity and character restrictions of their underlying file system. For example, Windows is case insensitive, but Mac and Linux are not.
  • 20.
    .NET Core Considerations Static files •ASP.NET Core applications hosted in IIS use the ASP.NET Core Module to forward all requests to the application including requests for static files. The IIS static file handler is not used because it doesn’t get a chance to handle requests before they are handled by the ASP.NET Core Module. • To remove the IIS static file handler (at the server or website level): • Navigate to the Modules feature • Select StaticFileModule in the list • Tap Remove in the Actions sidebar • Code files (including c# and Razor) should be placed outside of the app project’s web root (wwwroot by default).
  • 21.
    .NET Core Configuring anException Handling Page Error Handling When errors occur in your ASP.NET app, we can handle them with Configuring an Exception Handling Page in the Startup class’s Configure() method. We can add a simple exception page (During Development. All that’s required is to add a dependency on Microsoft.AspNetCore.Diagnostics to the project and then add one line to Configure() in Startup.cs: And When not in development, app.UseExceptionHandler("/Error");
  • 22.
    .NET Core Configuring anException Handling Page Error Handling
  • 23.
    .NET Core Configuring StatusCode Pages Error Handling You can configure the StatusCodePagesMiddleware to provide a rich status code page for HTTP status codes such as 500 (Internal Server Error) or 404 (Not Found) to the Configure method, this middleware adds very simple, text-only handlers for common status codes. app.UseStatusCodePages();
  • 24.
    .NET Core Configuring StatusCode Pages Error Handling pass it a content type and a format string: The middleware can handle redirects (with either relative or absolute URL paths), passing the status code as part of the URL: (302 / Found)
  • 25.
    .NET Core Configuring StatusCode Pages Error Handling the middleware can re-execute the request from a new path format string: will still return the original status code to the browser, but will also execute the handler given at the path specified If you need to disable status code pages for certain requests
  • 26.
    .NET Core Limitations ofException Handling During Client-Server Interaction Error Handling Web apps have certain limitations to their exception handling capabilities because of the nature of disconnected HTTP requests and responses. 1. Once the headers for a response have been sent, you cannot change the response’s status code, nor can any exception pages or handlers run. The response must be completed or the connection aborted. 2. If the client disconnects mid-response, you cannot send them the rest of the content of that response. 3. There is always the possibility of an exception occurring one layer below your exception handling layer. Don’t forget, exception handling pages can have exceptions, too. It’s often a good idea for production error pages to consist of purely static content.
  • 27.
    .NET Core Server ExceptionHandling Error Handling • If the server catches an exception before the headers have been sent it will send a 500 Internal Server Error response with no body. • If it catches an exception after the headers have been sent it must close the connection. • Requests that are not handled by your app will be handled by the server, and any exception that occurs will be handled by the server’s exception handling. • Any custom error pages or exception handling middleware or filters you have configured for your app will not affect this behavior.
  • 28.
    .NET Core Startup ExceptionHandling Error Handling • Only the hosting layer can handle exceptions that take place during app startup. • Exceptions that occur in your app’s startup can also impact server behavior. • For example, to enable SSL in Kestrel, one must configure the server with KestrelServerOptions.UseHttps(). If an exception happens before this line in Startup, then by default hosting will catch the exception, start the server, and display an error page on the non-SSL port. If an exception happens after that line executes, then the error page will be served over HTTPS instead.
  • 29.
    .NET Core Logging Logging ASP.NET Corehas built-in support for logging, and allows developers to easily leverage their preferred logging framework’s functionality as well. Adding logging is done by requesting either an ILoggerFactory or an ILogger<T> via Dependency Injection. If an ILoggerFactory is requested, a logger must be created using its CreateLogger method.
  • 30.
    .NET Core Logging Logging When alogger is created, a category name must be provided. The category name specifies the source of the logging events. By convention this string is hierarchical, with categories separated by dot (.) characters. In your real world applications, you will want to add logging based on application-level, not framework-level, events.
  • 31.
  • 32.
    .NET Core Logging VerbosityLevels Logging Trace Used for the most detailed log messages, typically only valuable to a developer debugging an issue. These messages may contain sensitive application data and so should not be enabled in a production environment. Disabled by default. Example: Credentials: {"User":"someuser", "Password":"P@ssword"} Debug These messages have short-term usefulness during development. They contain information that may be useful for debugging, but have no long-term value. This is the default most verbose level of logging. Example: Entering method Configure with flag set to true Information These messages are used to track the general flow of the application. These logs should have some long term value, as opposed to Verbose level messages, which do not. Example: Request received for path /foo
  • 33.
    .NET Core Logging VerbosityLevels Logging Warning The Warning level should be used for abnormal or unexpected events in the application flow. These may include errors or other conditions that do not cause the application to stop, but which may need to be investigated in the future. Handled exceptions are a common place to use the Warning log level. Examples: Login failed for IP 127.0.0.1 or FileNotFoundException for file foo.txt Error An error should be logged when the current flow of the application must stop due to some failure, such as an exception that cannot be handled or recovered from. These messages should indicate a failure in the current activity or operation (such as the current HTTP request), not an application-wide failure. Example: Cannot insert record due to duplicate key violation
  • 34.
    .NET Core Logging VerbosityLevels Logging Critical A critical log level should be reserved for unrecoverable application or system crashes, or catastrophic failure that requires immediate attention. Examples: data loss scenarios, out of disk space The Logging package provides helper extension methods for each LogLevel value, allowing you to call, for example, LogInformation, rather than the more verbose Log(LogLevel.Information, ...) method.
  • 35.
    .NET Core Logging VerbosityLevels Logging Each of the LogLevel-specific extension methods has several overloads, allowing you to pass in some or all of the following parameters: string data The message to log. EventId eventId A numeric id to associate with the log, which can be used to associate a series of logged events with one another. Event IDs should be static and specific to a particular kind of event that is being logged. For instance, you might associate adding an item to a shopping cart as event id 1000 and completing a purchase as event id 1001. This allows intelligent filtering and processing of log statements. string format A format string for the log message. object[] args An array of objects to format. Exception error An exception instance to log.
  • 36.
    .NET Core Logging Logging Some loggers,such as the built-in ConsoleLogger, will ignore the eventId parameter.
  • 37.
    .NET Core Logging Logging It isrecommended that you perform application logging at the level of application and its APIs, not at the level of the framework
  • 38.
    .NET Core Configuring Loggingin Application Logging To configure logging in your ASP.NET Core application, you should resolve ILoggerFactory in the Configure method of Startup class. Note Optionally it’s possible to configure logging when setting up Hosting, rather than in Startup. The console, debug, and event log loggers allow you to specify the minimum logging level at which those loggers should write log messages (for example, logLevel => logLevel >= LogLevel.Warning ) or (category, loglevel) => category.Contains("MyController") && loglevel >= LogLevel.Trace
  • 39.
    .NET Core Configuring TraceSourceLogging Logging When running on the full .NET Framework you can configuring logging to use the existing System.Diagnostics.TraceSource libraries and providers, including easy access to the Windows event log. add the Microsoft.Extensions.Logging.TraceSource package to project (in project.json)
  • 40.
    .NET Core Configuring TraceSourceLogging Logging The yellow line with the “warn: ” prefix, along with the following line, is output by the ConsoleLogger. The next line, beginning with “TodoApi.Controllers.TodoController”, is output from the TraceSource logger.
  • 41.
    .NET Core Configuring OtherProviders Logging elmah.io - provider for the elmah.io service Loggr - provider for the Loggr service NLog - provider for the NLog library Serilog - provider for the Serilog library
  • 42.
    .NET Core Logging Recommendations Logging 1.Log using the correct LogLevel. This will allow you to consume and route logging output appropriately based on the importance of the messages. 2. Log information that will enable errors to be identified quickly. Avoid logging irrelevant or redundant information. 3. Keep log messages concise without sacrificing important information. 4. Although loggers will not log if disabled, consider adding code guards around logging methods to prevent extra method calls and log message setup overhead, especially within loops and performance critical methods. 5. Name your loggers with a distinct prefix so they can easily be filtered or disabled. Remember the Create<T> extension will create loggers named with the full name of the class. 6. Use Scopes sparingly, and only for actions with a bounded start and end. For example, the framework provides a scope around MVC actions. Avoid nesting many scopes within one another. 7. Application logging code should be related to the business concerns of the application. Increase the logging verbosity to reveal additional framework-related concerns, rather than implementing yourself.
  • 43.