Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ASP.NET Core Patterns and Pitfalls

ASP.NET Core Patterns and Pitfalls

Talk from NDC London 2017. Demos at https://github.com/davidfowl/NDCLondon2017/


David Fowler

January 21, 2017


  1. ASP.NET Core Patterns and Pitfalls from Real-World Applications @davidfowl @damianedwards

  2. Logging • Always configure a logger for use in production

    (e.g Serilog, Application Insights) • Use logging as the first step towards diagnosing problems with your application • Changing the verbosity is possible without an application restart • To avoid logging too much information, pick specific categories to bump the verbosity for • ASP.NET logs to various places: • ANCM (IIS) – Logs to the EventLog when it fails to launch the process • ANCM also uses regular IIS failed request tracing • Unhandled exceptions are logged to the configured logger providers by default
  3. Configuration & Options • Reload file-based configuration when source file

    changes • Reload options objects from underlying configuration when they change using IOptionsSnapshot • Use IConfigureOptions<> when you require other services to configure an options object • Keep environmental configuration local to the environment it applies to by using user secrets, environment variables and platform config stores like Azure KeyVault • Set environment variables local to the application via IIS in the web.config file
  4. File Upload • If uploaded files need to be servable

    by the browser then put them in the web root • Simplest way is to use MVC controller that accepts IFormFile or IFormFileCollection • Low-level access via HttpContext.ReadFormAsync and HttpContext.Form • Check HttpRequest.HasFormContentType before reading the form • Block user from uploading anything that can execute on the server (unless it’s a feature e.g. cshtml files) • Large files are buffered on disk to avoid memory bloat • Sanitize file paths sent from client before saving on server • For large multipart uploads, don’t use model binding. Manually read using HttpRequest.GetMultipartBoundary() (1.1.0 only) • IIS Limits still apply!
  5. Dependency Injection • Keep your DI factories fast and synchronous

    (no async constructors) • Avoid manually calling GetService where possible the built in container can do a better job if it can see the object graph • Disposable transient services are captured by the container for disposal. This can turn into a memory leak if resolved from the top level container • Turn on scope validation to make sure you don’t have scoped services capturing singletons • https://github.com/aspnet/Mvc/commit/85ca3e4976d841425412fb987a6f38 dbbaa0a6eb
  6. Optimized Type Activation Constructor Injection public A(B b) public B(C

    c) Public C() Compiles to: new A(new B(new C())); Service Locator public A(IServiceProvider sp) { _b = sp.GetService<B>(); } public B(IServiceProvider sp) { _c = sp.GetService<C>(); } public C() Compiles to: new C(); new B(GetService<C>()); new A(GetService<B>());
  7. MVC • Protect against mass assignment with separate input/output models

    • Tag Helpers • Handling attribute values correctly • Ensure file existence before processing files specified in attributes • Using TempData for Post-Redirect-Get state
  8. Testing your pipeline • Use the TestHost to run full

    pipeline in memory tests without a network. • Use environments to separate test configuration from other environmental configuration.
  9. Per request state • HttpContext.Items – Per request storage when

    all consumers have access to the http context. • HttpContext.Get/SetFeature – For adding a capabilities to the HttpContext. E.g. IHttpSendFileFeature, IWebSocketFeature • Scoped services – Services that have a lifetime that matches the http request (or any other scope). • Use the IHttpContextAccessor to access the HttpContext outside of a request context.