1. .NET Core + ASP.NET Core Training Course
Session 7
2. .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
3. .NET Core
What weâll learn today?
Session 7 Agenda
⢠Working with Static Files
⢠Error Handling
⢠Logging
4. .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.
5. .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
6. .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.
7. .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
8. .NET Core
Working with Static Files
Static files
In case of serving static files outside the wwwroot directory: http://<app>/StaticFiles/test.png
9. .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
10. .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:
12. .NET Core
Enabling directory browsing
Static files
And add required services by calling AddDirectoryBrowser extension method from
Startup.ConfigureServices:
13. .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
14. .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);
15. .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.
16. .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.
18. .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.
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 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");
23. .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();
24. .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)
25. .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
26. .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.
27. .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.
28. .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.
29. .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.
30. .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.
32. .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
33. .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
34. .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.
35. .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.
37. .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
38. .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
39. .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)
40. .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.
41. .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
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.