Upload
andy-butland
View
794
Download
0
Embed Size (px)
Citation preview
ASP.Net 5
and C# 6
8October
2015
What’s this got to do with Umbraco?• In the short-term… not much!
• It’ll be a while before Umbraco itself runs on ASP.Net 5
• But for .Net developers there is a big change coming – of the scale we’ve had before:• “Classic” ASP…• … ASP.Net Web Forms…• … ASP.Net MVC…• ASP.Net 5
• Arguably, working with Umbraco, we are behind the .Net curve – so it’s important not to get left behind
Contents
1
2
3
ASP.Net 5
C# 6
Discussion time
ASP.Net 5
Two runtimes• .Net Core
• Sub-set of full framework• No Windows Forms, WPF, Silverlight• As I understand, no Web Forms (as no System.Web)• Also no System.Drawing
• Implemented as set of NuGet packages• Cross-platform and Nano server support
• .Net Full Framework• Not going away… so Windows hosting with full access
to .Net APIs remain
Open source• Large parts of the framework are fully open-
source
Working environment• Dynamic compilation
• Change C# code and refresh – no build needed• Can still publish to deploy pre-compiled code
• Embraced front-end community ecosystems• npm and bower• Gulp and grunt
Request pipeline• Lightweight web request handling
• Currently ASP.Net suffers in comparison to other frameworks due to the overhead in the pipeline of handling web requests
• Start with nothing and configure the middleware you need
• Middleware components can process the request with a response, or modify the request/response and pass it on
• Middleware replaces HttpModules
public void Configure(IApplicationBuilder app){ app.UseStaticFiles(); app.UseIdentity(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller}/{action}/{id?}", defaults: new { controller = "Home", action = "Index" }); });}
Solutions and projects• Global.json
Solution level configuration – project references (replaces .sln)
• Project.jsonProject level configuration – references, frameworks, dependencies (replaces .csproj and packages.config)
• WwwrootRoot of project != root of website, more secure, client side files live here
• Startup.csConfigures application start-up (replaces Global.asax)
Configuration• No more web.config, instead config.json
• Internal references can be set-up within the configuration
• XML or other sources can be used too• The methods used are configured in application
start-up (see later example)
{ "MyAppSetting": "MyAppSettingValue", "Data": { "DefaultConnection": { "ConnectionString": "Server=..." } }, "EntityFramework": { "ApplicationDbContext": { "ConnectionString": "Data:DefaultConnection:ConnectionString" } } }
public class HomeController : Controller{ private readonly IConfiguration _config; public HomeController(IConfiguration config) { _config = config; } public IActionResult Index() { var configSetting = _config.Get("MyAppSetting"); }}
Application start-up• The application is configured on start-up via the
three parts of Startup.cs• Constructor
• Wires up configuration• ConfigureServices() method
• Specify what services the application will use• Configure() method
• Sets up the required middleware and request pipeline
public Startup(IHostingEnvironment env){
Configuration = new Configuration().AddJsonFile("config.json").AddEnvironmentVariables();
}
public void ConfigureServices(IServiceCollection services){
services.AddEntityFramework(Configuration).AddSqlServer().AddDbContext<ApplicationDbContext>();
services.AddIdentity<ApplicationUser, IdentityRole>(Configuration).AddEntityFrameworkStores<ApplicationDbContext>();
services.AddMvc();
services.AddSingleton(_ => Configuration);}
public void Configure(IApplicationBuilder app){
// Add static files to the request pipeline.app.UseStaticFiles();
// Add cookie-based authentication to the request pipeline.app.UseIdentity();
// Add MVC and routing to the request pipeline.app.UseMvc(routes =>{routes.MapRoute(
name: "default",template: "{controller}/{action}/{id?}",defaults: new { controller = "Home", action = "Index" });
});
Dependency injection• Commonly used pattern – SOLID – usually
supported with a third party IoC container• ASP.Net 5 has it’s own simple one, suitable for
most requirements• Can even be injected into a view
public interface IService{
int GetResult();}
public class SimpleService : IService{
public int GetResult() { return 99; }}
public class HomeController : Controller{
private readonly IService _service; public ServiceController(IService service){
_service = service;} public int Get(){
return service.GetResult();}
}
public void ConfigureServices(IServiceCollection services){
services.AddSingleton<IService, SimpleService>(); // or AddScoped(), or AddTransient()}
public void ConfigureServices(IServiceCollection services){
services.AddSingleton<IService, SimpleService>();
// or AddScoped(), or AddTransient()}
ASP.Net MVC 6• MVC and Web API combined
• All controller action methods now return IActionResult – which might be a view for MVC or JSON for an API
• New features• View components• Tag helpers
ASP.Net MVC 6: View Components• View components replace @Html.Action()• They live outside of the controller but can still
access services via dependency injection• Wired up by convention
• Located via attribute and/or class name suffix• Base class not essential but provides access to
useful information and services
[ViewComponent(Name = "PromotedProducts")]public class PromotedProductsViewComponent : ViewComponent{
private readonly IProductService _productService;
public PromotedProductsViewComponent(IProductService productService){
_productService = productService;}
public async Task<IViewComponentResult> InvokeAsync(
int numberOfProducts){
var products = await _productService.GetPromotedProducts() .Take(numberOfProducts);
return View(products);}
}
<div>@await Component.InvokeAsync("PromotedProducts", 5)
</div>
ASP.Net MVC 6: Tag Helpers• Replacement/improvement on HTML helpers• Intermingling of front-end/back-end code
• More intuitive for FEDs to use – no more idiosyncratic anonymous typed HTML attributes
<form asp-controller="Products" asp-action="Create" method="post"><div>
<label asp-for="Name">Name:</label><input asp-for="Name" />
</div>
<input type="submit" value="Save" /></form>
...
<li><a asp-controller="Home" asp-action="Index“ class="home-link">Home</a></li>
<!– Instead of: --><li>@Html.ActionLink("Home", "Index", "Home", new { @class = "home-link")</li>
C# 6
C# 6• Available with VS.Net 2015 and the Roslyn
compiler• Brings a mix of nice little features
• Saves some typing• Avoid some bugs• General “syntactic sugar”
Null conditional (or “Elvis”) operator• Helps with handling NullReferenceExceptions• On encountering a null value, the whole
expression immediately returns null• ?. =
public static string Truncate(string value, int length){
var result = value;if (value != null){
result = value.Substring(0, Math.Min(value.Length, length));}
return result;}
public static string Truncate(string value, int length){
return value?.Substring(0, Math.Min(value.Length, length));}
public static int GetCustomerCount(IList<Customer> customers){
return customers?.Length ?? 0;}
Nameof expression• Used in situations where you want to return in
code the name of a variable• Without them, danger is that the variable name
change in a refactor is missed in the string• Handy in logging or exception guard clauses
public void DoSomething(string data){
if (data == null){
throw new ArgumentNullException("data");}
}
public void DoSomething(string data){
if (data == null){
throw new ArgumentNullException(nameof(data));}
}
String interpolation• A nicer, easier to write and follow syntax for
string formatting• Formatting variables are placed in-line within the
string• Existing string.Format() syntax can be fiddly to
line up arguments and lead to tricky bugs
var s = string.Format("{0} is {1} year{2} old", p.Name, p.Age, p.Age == 1 ? "" : "s");
...
var s = $"{p.Name} is {p.Age} year{(p.Age == 1 ? "" : "s")} old";
Expression bodied methods• More succinct format for one-liner methods• Need to consider code readability and consistency
when adopting use
public static int Add(int arg1, int arg2){
return arg1 + arg2;}
public static int Add(int arg1, int arg2) => arg1 + arg2;
Auto-property initialisers• Allows setting a default value for an instance of a
class, without writing this code in the constructor• Useful for collection initialisers – ensuring you
return empty collections instead of nulls• Used in conjunctions with primary constructors
where variables provided for auto-initialisation
public class Customer {
public Customer() {
FirstName = "Fred";LastName = "Bloggs";
}
public string FirstName { get; set; }
public string LastName { get; set; }}
public class Customer {
public string FirstName { get; set; } = "Fred";
public string LastName { get; set; } = "Bloggs"; }
public IList<Customer> Customers { get; set; } = new List<Customer>();
public class Customer {
public Customer(string firstName, string lastName) {}
public string FirstName { get; set; } = firstName;
public string LastName { get; set; } = lastName; }
Out parameter declaration in method call• Allows an out variable to be declared as it is
used.• Small improvement to save a bit of typing – less
code, less bugs!
public bool IsOver18 (string age){ int ageAsNumber; if (int.TryParse(value, out ageAsNumber)) {
return ageAsNumber > 18; }
return false;}
...
public bool IsOver18 (string age){ return int.TryParse(value, out int ageAsNumber) && ageAsNumber > 18;}
Using a static class• Allows a static class to be referenced as a using• Another simple one that removes a bit of clutter• Question here though whether this really
improves readability, so likely one to use with care
using System;
public class Program{
public static void Main(string[] args){
Console.WriteLine("A");Console.WriteLine("B");
}}
using System;using System.Console;
public class Program{
public static void Main(string[] args){
WriteLine("A");WriteLine("B");
}}
Exception handling enhancements• Try/catch blocks have always allowed for
targeting particular exceptions• With C# 6 you can apply further filters• Asynchronous code is also now usable in catch
blocks
try{
// ...}catch (Exception exception) if (expression){
// ...}
try{
// ...}catch (Exception exception){
await WriteErrorToLog(exception);}
In closing…• ASP.Net 5 is coming… time to get up to speed,
even if not going to be using it directly for a while• C# 6 is available now with VS.Net 2015
Provided as Creative Commons 3.0 Share Alike:
http://creativecommons.org/licenses/by-nc-sa/3.0/