https://aka.ms/aspnetcore-makeover
- Intro (goals/non-goals/what you'll learn)
- Pick The Right Starting Template
- Web Application (no auth)
- Web API
- SPA
- Other templates
- Source Control and Solution Structure
- editorconfig
- gitignore
- Maintainability
- Tests
- Health Checks
- Front End
- Bootstrap
- Libman
- SEO
- Performance (no way we'll get to this in 50 minutes...)
- Caching
- Miniprofiler
- Web Optimizer
- Creating your own templates
using Microsoft.AspNetCore.Mvc.Testing;
using OneHour.Web;
using System;
using System.Threading.Tasks;
using Xunit;
namespace WebApp.Tests
{
public class BasicTests
: IClassFixture<WebApplicationFactory<Startup>>
{
private readonly WebApplicationFactory<Startup> _factory;
public BasicTests(WebApplicationFactory<Startup> factory)
{
_factory = factory;
}
[Theory]
[InlineData("/")]
[InlineData("/Index")]
[InlineData("/Privacy")]
public async Task Get_EndpointsReturnSuccessAndCorrectContentType(string url)
{
// Arrange
var client = _factory.CreateClient();
// Act
var response = await client.GetAsync(url);
// Assert
response.EnsureSuccessStatusCode(); // Status Code 200-299
Assert.Equal("text/html; charset=utf-8",
response.Content.Headers.ContentType.ToString());
}
[Fact]
public async Task Get_HealthCheckReturnsHealthy()
{
// Arrange
var client = _factory.CreateClient();
// Act
var response = await client.GetAsync("/health");
// Assert
response.EnsureSuccessStatusCode(); // Status Code 200-299
Assert.Equal("Healthy",
response.Content.ReadAsStringAsync().Result);
}
}
}
{
"version": "1.0",
"defaultProvider": "cdnjs",
"libraries": [
{
"library": "[email protected]",
"files": [
"jquery.min.js"
],
"destination": "wwwroot/lib/jquery/dist"
},
{
"library": "[email protected]",
"files": [
"jquery.validate.unobtrusive.min.js"
],
"destination": "wwwroot/lib/jquery-validation-unobtrusive/"
},
{
"library": "[email protected]",
"provider": "jsdelivr",
"files": [
"dist/jquery.validate.js",
"dist/additional-methods.js"
],
"destination": "wwwroot/lib/jquery-validation/dist/"
},
{
"provider": "unpkg",
"library": "[email protected]",
"destination": "wwwroot/lib/bootstrap/",
"files": [
"dist/css/bootstrap.css",
"dist/css/bootstrap-grid.css",
"dist/css/bootstrap-reboot.css",
"dist/js/bootstrap.js"
]
},
{
"provider": "unpkg",
"library": "[email protected]",
"destination": "wwwroot/lib/ionicons",
"files": [ "dist/css/ionicons.min.css" ]
}
]
}
using Ducksoft.NetCore.Razor.Sitemap.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
namespace OneHour.Web.Utility
{
public static class SitemapExtensions
{
public static IServiceCollection ConfigureMvcRazorPages(this IServiceCollection services,
CompatibilityVersion version, string startPageUrl = "", string startPageArea = "")
{
services.AddMvc()
.SetCompatibilityVersion(version)
.AddRazorPagesOptions(options =>
{
var isSupportAreas = !string.IsNullOrWhiteSpace(startPageArea);
options.AllowAreas = isSupportAreas;
options.AllowMappingHeadRequestsToGetHandler = true;
if (isSupportAreas)
{
options.Conventions.AddAreaPageRoute(startPageArea, startPageUrl, string.Empty);
}
else if (!string.IsNullOrWhiteSpace(startPageUrl))
{
options.Conventions.AddPageRoute(startPageUrl, string.Empty);
}
})
.AddRazorPagesOptions(options =>
{
options.Conventions.Add(new SitemapRouteConvention());
})
.AddRazorPagesOptions(options =>
{
options.Conventions.AddPageRoute("/Sitemap", "sitemap.xml");
});
return services;
}
}
}
{
"$schema": "http://json.schemastore.org/template",
"author": "YOUR NAME",
"classifications": [ "ASP.NET Core", "Solution" ],
"identity": "[YOUR NAME].AspNetCoreSolutionTemplateTemplate.CSharp",
"name": "ASP.NET Core One Hour",
"shortName": "aspnetonehour",
"sourceName": "OneHour"
}
One thing I really miss in the list is adding an EditorConfig file to the solution. It makes collaboration much easier when it comes to various coding styles like spaces vs tabs, ordering of
using
or the use ofvar
in C#.