Setting up your app
.csproj
- Used by MsBuild
- Used by NuGet
- Add packages and tools packages
Program.cs
- Called first thing when the app starts. Main() called by runtime.
- Please note that all ASP.NET Core apps are now console apps and you define what you want to make of them.
- Sets up the hosting enviroment into which the web app will be loaded. Methods called in order to setup the environment:
- .UseKestrel
- .UseContentRoot – root folder for static content
- .ConfigureAppConfiguration – prepare the configuration for your app (config files, environment variables, applies command line args to the app.
- .AddUserSecrets – store sensitive data outside code files
- .ConfigureLogging – define where you want to log your runtime data (e.g. based on entries in an appsettings.json section; you can also log to console output) and whether you want to log debug data.
- .UseIISIntegration – enables integration with IIS and IIS Express
- .UseDefaultServiceProvider – configures dependency injection
- .UseStartup – allows you to specify a class which defines middleware and services.
- Template provides a call to a WebHost.CreateDefaultBuilder() which does the most typically used setup. This approach hides a lot of internal details, so we will break it down below.
- Minimal working setup:
public static IWebHost BuildWebHost(string[] args) { return new WebHostBuilder() .UseKestrel() .UseContentRoot(Directory.GetCurrentDirectory()) .UseIISIntegration() .UseStartup<Startup>() .Build(); }
- Complete setup:
public static IWebHost BuildWebHost(string[] args) { return new WebHostBuilder() .UseKestrel() .UseContentRoot(Directory.GetCurrentDirectory()) .ConfigureAppConfiguration((hosting) => config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); config.AddEnvironmentVariables(); // Load data from env. variables if (args != null) { config.AddCommandLine(args); } }) .UseIISIntegration() .UseStartup<Startup>() .Build(); }
Startup.cs
- Called right after the methods in Program.cs
- Called by runtime.
- Configure services to be used by the app
public void ConfigureServices(IServiceCollection services);
- This covers a lot of different things, from defining dependency injection bindings, setting up session, identity (authentication), MVC. Configure using options arguments. The options argument is usually extended through extension methods for specific components.
- Services can also be used by middleware. That seems to be the reason why services are set up before the middleware. For example, we set up MVC services by calling .AddMvc() – later, in the Configure() we assign MVC to the HTTP pipeline by calling .UseMvc().
- Configure HTTP request pipeline – middleware (pp. 391)
public void Configure(IApplicationBuilder app, IHostingEnvironment env);
-
- This is done by setting up various middleware components that interact with the HTTP request/response: developer error pages, status code pages, serving static content, using session, using authentication, using MVC and defining routes.
- Types of middleware:
- Content generating middleware – adds content to the response. MVC itself belongs to this category – it is assigned to the middleware via .UseMvc().
- Short-circuiting middleware – intercepts requests before they reach the content generating middleware components and determines whether the request should be passed through (often for performance reasons).
- Request-editing middleware: makes changes to the HTTP request for downstream components to process.
- Response-editing middleware: makes changes to the HTTP response after all the other components are done.
- Create a class of your own and add it to HTTP pipeline:
app.UseMiddleware<YourMiddlewareClassHere>();
Startup.cs – some examples
public void ConfigureServices(IServiceCollection services) {
// "using Microsoft.EntityFrameworkCore" needed for this one.
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(
_configuration["Data:SportsStoreProducts:ConnectionString"]));
services.AddTransient<IProductRepository, EFProductRepository>();
services.AddMemoryCache(); // Needed for using Session.
services.AddSession(); // Needed for using Session.
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); // Additional info in development. app.UseStatusCodePages(); // Additional info with HTTP errors. app.UseBrowserLink(); // Dev only } app.UseStaticFiles(); // Serve static files from /wwwroot. app.UseSession(); // Needed for using Session. app.UseExceptionHandler() // Production app.UseMvc(routes => { // Define routes. routes.MapRoute(name: "default", template: "{controller=Product}/{action=List}/{id?}"); });
Environment variables
- ASPNET_ENVIRONMENT: {Development, Staging, Production}
- cmd.exe commands
- Please note if you set via cmd.exe, you must restart the cmd.exe
- A nice article
setx ASPNETCORE_ENVIRONMENT "Development" // Set value echo %ASPNETCORE_ENVIRONMENT% // Get value
Routes
- defined in Startup.Configure():
app.UseMvc(routes => { routes.MapRoute( name: null, template: "{category}/Page{productPage:int}", defaults: new { controller = "Product", action = "List" } ); routes.MapRoute( name: null, template: "Page{productPage:int}", defaults: new { controller = "Product", action = "List" } ); routes.MapRoute( name: null, template: "{category}", defaults: new { controller = "Product", action = "List" } ); routes.MapRoute( name: "", template: "{controller=Product}/{action=List}" ); });
Entity Framework Core
Setup
- Create a SomethingDbContext class. Inherit from DbContext and add your properties. Return DbSet<>.
- Create a repository interface and a repository implementation. Make the SomethingDbContext property private. Return results as properties.
- Add EF Core command-line tools to your project. Copy-paste the following line to .csproj.
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0"/>
- Define a connection string in appsettings.json
{ "Data": { "SportsStoreProducts": { "ConnectionString": "Server=(localdb)\\MSSQLLocalDb;Database=SportsStore;Trusted_Connection=True;MultipleActiveResultSets=true" } } }
- Map services provided by EF Core to your SomethingDbContext. Do this in Startup.cs.
public IConfiguration Configuration { get; set; } // Access appsettings.json public void ConfigureServices(IServiceCollection services) { // Setting up Entity Framework Core. // Maps services provided by the EF Core to our ApplicationDbContext class. // UseSqlServer is an extension method that comes from Microsoft.EntityFrameworkCore namespace and is specific to EF Core. services.AddDbContext<ApplicationDbContext>( options => options.UseSqlServer( Configuration["Data:SportsStoreProducts:ConnectionString"])); ...
- Turn off ValidateScopes in Program.BuildWebHost().
Reference one project from another project
- .csproj file
<ItemGroup> <ProjectReference Include="..\SportsStore\SportsStore.csproj" /> </ItemGroup>
- If VSCode does not recognize any types from newly referenced project, try rebuilding the test project from terminal:
dotnet test .\SportsStore.Tests\
Tag Helpers – built in
- A quick list of interesting tag helpers. These are used as attributes on regular HTML elements:
/* Model binding */ asp-for="SomeModelPropertyName" /* Model validation errors. Both -for and -summary apply * a CSS class input-validation-error to erroneous input elements. */ asp-validation-summary="All" // Use with div // Use: div.span[asp-validation-for=Name] asp-validation-for="Name" asp-validation-for="Description" // /* Resource referencing (.js, .css). The paths you provide must be under /wwwroot */ asp-href-include="" // More on this below. asp-href-exclude="" /* Routing - you can use this for links, form action...*/ asp-action="ControllerAction" asp-controller="Controller" asp-route-<action_parameter_name>="<parameter_value>" // E.g. asp-route-category="@category" // asp-route-productPage="1"
- some tag helpers (like HrefInclude and HrefExclude) use glob file pattern matching
- Characters ** means any depth and number of directories until your reach what you want.
asp-href-include="\lib\bootstrap\dist\**\*.min.css" asp-href-exclude="**\*-grid-*, **\*-reboot*"
Tag Helpers – roll your own
- pass in routing elements via a Dictionary. Every HTML attribute with prefix “page-url-” will be transferred into the dictionary:
[HtmlAttributeName(DictionaryAttributePrefix = "page-url-")] public Dictionary<string, object> PageUrlValues { get; set; } = newDictionary<string, object>();
and then use this with IUrlHelper.Action():
helper.Action(PageAction, PageUrlValues)
- Framework calls your tag helper’s Process() method:
public override void Process(TagHelperContext context, TagHelperOutput output);
View Components
- Inherit from ViewComponent.
- Logic is in a method:
public IViewComponentResult Invoke(); // or public IViewComponentResult InvokeAsync();
- View must be in location Views\Shared\Components\<view component name>\Default.cshtml (this is the mandatory view file name).
- When you want to render the view component’s view somewhere on your front end, call from Razor:
@await Component.InvokeAsync("view component name")
Relevant Files
_ViewImports.cshtml
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
Concepts
Model validation
[Required(ErrorMessage = "Country mandatory.")]
Model Binding
- Skip automatic model binding by applying attribute:
[BindNever]
Other
[UIHint("password")] [Authorize] [AllowAnonymous]
Relevant types
IConfigure
- Fetches data from appsettings.json
bool foo = (Configuration .GetSection("ShortCircuitMiddleware")? .GetValue<bool>("EnableBrowserShortCircuit")) .Value;
- You can inject an object of this type without declaring a DI binding – framework provides a default implementation out of the box.
TagBuilder
- Build html tags
IUrlHelperFactory / IUrlHelper
- Retrieve a Url Helper from ViewContext, to help you with routing.
- IUrlHelper.Action()
ViewBag
- passes data between controller and view.
TempData
- part of session state feature. Temporary data store, persists until read the first time.
RouteData
- accessible from various other types: View Components, Controllers.
- you can get details on current route via indexers
RouteData?.Values["category"]
- if you are using RouteData from your controllers or view components, it is a bit difficult to set up values within your unit tests. This is because controller’s or view component’s RouteData property is read-only (getter). To properly set up, you have to manually create several properties:
NavigationMenuViewComponent target = new NavigationMenuViewComponent(mock.Object); target.ViewComponentContext = new ViewComponentContext() { ViewContext = new ViewContext { RouteData = new Microsoft.AspNetCore.Routing.RouteData() } }; target.RouteData.Values["category"] = "Cat1";
JsonConvert
- serialize and deserialize objects to and from JSON.
Controller.ModelState
IsValid; AddModelError();
Other types
- ConsoleTable – class to help you write out contents in a tabular format. Use with console output.
Front end stuff
Bootstrap
Font Awesome
- Open source icons integrated into apps via as fonts.
- Install via Bower.
- Include in your _Layout.cshtml
<link rel="stylesheet" asp-href-include="/lib/fontawesome/web-fonts-with-css/css/*.css">
- Find icons at:
https://fontawesome.com/icons?d=gallery