© Copyright SELA Software & Education Labs Ltd. | 14-18 Baruch Hirsch St Bnei Brak, 51202 Israel | www.selagroup.com
Ido Flatow
Getting to Know ASP.NET 5 and MVC 6
AgendaIntroduction to ASP.NET 5What’s new in ASP.NET 5ASP.NET MVC 6
About MeSenior Architect, Sela GroupMicrosoft Regional Director, and an ASP.NET/IIS MVPCo-author of courses and booksFocus on server, web, and cloudManager of the Israeli Web Developers User Group
History of ASP (18 years)1996 - Active Server Pages (ASP) 2002 – ASP.NET2008 – ASP.NET MVC2010 – ASP.NET Web Pages2012 – ASP.NET Web API, SignalR2014 – ASP.NET vNext
Current ASP.NET stack
Windows Server
IIS
.NET Framework
ASP.NET WebForms MVC Web API
Syst
em.W
eb
HTTP Modules
HTTP Handler
sRequest Pipeline Caching Session
State
Problems with ASP.NET architecture
Limited hosting possibilities (IIS only)Dependency on IIS environment (System.Web)Web evolves faster than .NET frameworkRequires full-blown .NET framework - resource intensive and not web-friendlyHard to optimize for lightweight high-performance apps
Introducing ASP.NET 5 stack
OS
.NET CLR
ASP.NETWeb API MVC Web Pages
HostIIS Self-hosted
.NET Core CLR
Middleware
.NET 2015: High-Level Overview
.NET Framework 4.6
.NET Core & App Models
CautionAt the time of this presentation, we are using DNX-CLR-x86 1.0.0-beta4 (ASP.NET 5 beta 4)As things are moving really fast in this new world, it’s very likely that the things explained here will slightly change
ASP.NET 5 – AgilityFaster Development Cycle
Features are shipped as packagesFramework ships as part of the application
More ControlZero day security bugs patched by MicrosoftSame code runs in development and productionDeveloper opts into new versions, allowing breaking changes
ASP.NET 5 - FastRuntime Performance
Faster startup timesLower memory / higher density (> 90% reduction)
Modular, opt into just features neededUse a raw socket, framework or bothDevelopment productivity and low friction
Edit code and refresh browserFlexibility of dynamic environment with the power of .NETDevelop with Visual Studio, third party and cloud editors
ASP.NET 5 – Cross PlatformRuntime
Windows, Mac, LinuxEditors
Visual Studio, Text, Cloud editorsOmniSharp – Sublime, Emacs, Vi, etc.No editors (command line)
All Open Source with Contributions
ASP.NET 5 FeaturesNew flexible and cross-platform runtimeNew modular HTTP request pipelineRobust environment configurationUnified programming model for MVC APISee changes without re-building the projectSide-by-side versioning of the .NET FrameworkBuilt in Dependency InjectionAbility to self-host or host on IISOpen source in GitHub
File New Project Web
Web AppClass Lib?Console App?
Select a Template
Startup.cs Configuration
Let's talk about OWINOpen Web Interface for .NETCommunity project (http://owin.org) Decouples application from serverEnforces modularity of the serverStack of modules (middlewares) is processing the request from application to serverMicrosoft implementation of OWIN is "Katana"
OWIN Implementation
Host
Middleware
Server
Application
MiddlewareMiddleware
Request Response
Startup, bootstrapping, process management
Manages sockets,delegates to middlewares
Pass-through components stack
Your code
ASP.NET 5 MiddlewaresImproved HTTP performance
New HTTP request pipeline that is lean and fastThe new pipeline also supports OWIN
You choose what to use in your applicationBy registering middlewares
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory)
{ app.UseErrorHandler("/Home/Error"); app.UseStaticFiles(); app.UseIdentity(); app.UseMvc(routes => ...)}
Custom MiddlewareCreate middleware class
app.UseMiddleware<AppHeaderMiddleware>();// Register before app.UseMvc(...);
public class AppHeaderMiddleware { private readonly RequestDelegate next; public AppHeaderMiddleware(RequestDelegate next) { this.next = next; } public async Task Invoke(HttpContext context) { context.Response.Headers.Append(
"X-Application", "ASP.NET 5 Sample App"); await this.next.Invoke(context); }}
Register in Startup.cs (IApplicationBuilder)
Project.json
packages.config not needed!
Package ManagementASP.NET 5 introduces a new, lightweight way to manage dependencies in your projects
No more assembly referencesInstead referencing NuGet packages
project.json file
Structure of the "project.json" file
Dependencies - lists all the dependencies of your application (NuGet, source files, etc.)Configuration - compilation settings (debug, release)Frameworks - target frameworks with their dependenciesSources - what should be compiledWeb root - server root of the appShared files - files shared with dependent projectsCommands - commands available to “dnx”Scripts - pre/post events to hook scripts toMetadata - general project information
Right-click (Project) Properties
• Application tab• Debug tab
Use specific KRE version!
Compilation Process
Debugging without Roslyn
Change the code
C# Compiler invoked
Load code in memory
Execute the dll
dll loaded in memory from File system
Emits the dll in file system
Debugging with Roslyn
Change the code
Load code in memory
Code is Executed in
memory
Roslyn compiles code in memory
Time reduced from 7-8 second to 1-2 second
"K“ / ”DNX” Command Line Tools
KRE / DNX- Runtime EnvironmentEngine that runs your application (compilation system, SDK tools, and the native CLR hosts)
KVM / DNVM - Version ManagerTool for updating and installing different versions of KRE/DNX
KPM / DNU- Package ManagerTool to restore and install (NuGet) packages needed by applications to run
K / DNXEntry point to the runtime - starts the runtime with commands
Open Source
Runtime LoaderIIS: WebEngine4Exe: OS DNX
Operating SystemWindows Windows, OSX,
Linux
LibrariesLoose, GAC, Nuget
NuGet, NPM, Bower
App FrameworksFCL, GAC, NuGet NuGet
Web ServerIIS IIS, HTTP.SYS, Kestrel
Application HostSystem.Web DNX
Platform Libraries.NET BCL & FCL .NET BCL & FCL
.NET on Nuget
Runtime.NET CLR .NET CLR.NET Core CLR
ApplicationMSBuild/
CodeDom -> csc.exe
DNX (Roslyn)
Present vs. Future
© Copyright SELA Software & Education Labs Ltd. | 14-18 Baruch Hirsch St Bnei Brak, 51202 Israel | www.selagroup.com
MVC 6
ASP.NET <5 FrameworksMVC Web APIWeb Pages
Razor
HTML Helpers HTML Helpers
Controllers Controllers
Actions Actions
Filters Filters
Model binding Model bindingDependency
ResolverDependency
Resolver
ASP.NET 5 with MVC 6MVC Web APIWeb Pages
Razor
HTML Helpers
Controllers
Actions
Filters
Model binding
Dependency Resolver
MVC + Web API + Web Pages =
ASP.NET MVC 6!
ASP.NET MVC 6No more duplication - one set of conceptsUsed for creating both UI and APISmooth transition from Web Pages to MVCBased on the new ASP.NET 5 pipelineBuilt DI firstRuns on IIS or self-host
Getting Started with MVC 6
Startup.cs
Project.json
app.UseMvc(routes => { routes.MapRoute("default", "{controller}/{action}/{id?}", new { controller = "Home", action = "Index" }); });app.UseServices(services => { services.addMvc(); })
"dependencies": { "Microsoft.AspNet.Server.IIS": "1.0.0-*", // Add this: "Microsoft.AspNet.Mvc": "6.0.0-*"}
Routing Template Improvements
Inline constraints Product/{ProductId:long}Product/{ProductName:alpha}Product/{ProductName:minlength(10)}Product/{productId:regex(^\\d{4}$)}
Optional parametersProduct/{productId:long?}
Default valuesProduct/{productId:long=1}
Available with MapRoute() and [Route()]
https://github.com/aspnet/Routing/tree/dev/src/Microsoft.AspNet.Routing
Where is the Web API Configuration?Route configuration -> attribute-based routing Message handlers -> middleware pipelineFilters and Formatters -> startup.cs
app.UseServices(services => { services.Configure<MvcOptions>(options>=
{options.AddXmlDataContractSerializerFormatter;)(
options.Filters.Add(new ValidatorFilterAttribute());;)}}
Controllers – Two Birds, One Stone
API – similar, but differentUI – same as with MVC 5
[Route("api/[controller]")]public class ProductsController : Controller{ [HttpGet("{id:int}")] public Product GetProduct(int id) { return new Product() { ID = id }; }}
public class HomeController : Controller{ public IActionResult Index() { return View(); }}
Actions – API with IActionResult[HttpGet("{id:int}", Name = "GetByIdRoute")]public IActionResult GetById (int id){ var item = _items.FirstOrDefault(x => x.Id == id); if (item == null) { return HttpNotFound(); }
return new ObjectResult(item);}
[HttpPost]public IActionResult CreateTodoItem([FromBody] TodoItem item){ _items.Add(item);
return CreatedAtRoute( "GetByIdRoute", new { id = item.Id }, item);}
IActionResult for UI and API
https://github.com/aspnet/Mvc/tree/dev/src/Microsoft.AspNet.Mvc.Core/ActionResults
UI API
PartialViewResult BadRequestResult
RedirectResult ContentResult
ViewResult CreatedAtRouteResult
JsonResult HttpStatusCodeResult
JsonResult
ObjectResult
ChallengeResult
HttpNotFoundResult
FileContentResult
Content NegotiationMVC still respects Accept headersThe XML formatter was removed from the MVC 6 pipeline
You can manually add it to the Formatters collectionForcing a content-type:
Return a JsonResultUse the [Produces("application/json")] attribute
Additional changes:Actions returning string result in text/plain responsesReturning null/void – response will be HTTP 204 (no content)
Last Controller Goodie - DIDependency Injection and MVC
ASP.NET 5 is DI-friendlyBasic DI container available throughout the stackBYOC is also supported (already implemented for Autofac, Ninject, StructureMap, Unity, and Windsor)Out-of-the-box container supports
Singleton / Instance – single instanceTransient – new instance each timeScoped – new instance per request
https://github.com/aspnet/DependencyInjection/tree/dev/src
Last Controller Goodie - DIpublic class ProductsController : Controller{ private readonly IProductsRepository _repository; public ProductsController(IProductsRepository repository) { this._repository = repository; }
public IActionResult Index() { var products = _repository.GetAllProducts(); return View(products); }}
app.UseServices(services => { services.AddTransient<IProductsRepository, DefaultProductsRepository>(); });
Look Ma No Controller
Use the Controller suffixInject HTTP request, principal, and view data with:
Convention-based property injectionConstructor injection
public class SimpleController{ [Activate] public ActionContext ActionContext { get; set; } [Activate] public ViewDataDictionary ViewData { get; set; } [Activate] public IUrlHelper Url { get; set; } public string Get() { return "Hello world"; }}
Enough with Controllers,What About MVC Views?
Oh, right!
Child Actions in MVC <6 Rendering partial views with controller logic and modelDo not confuse with Html.Partial
@Html.Action("GetProductDetails", "Products", new { id = 1})
[ChildActionOnly]public ActionResult GetProductDetails(int id){
var product = _repository.GetProduct(id); return PartialView("ProductDetails", product);}
Child Actions in MVC 6 So what’s the problem?
Part of a controller, but invoked from a viewController flow must distinguish between HTTP calls and view callsPattern lacks an asynchronous invocation
Solution?Replace child actions with View ComponentsSame partial views, but declared in a separate classThink of it as a “mini-controller”Supports the same DI and POCO features as a controllerImplement actions as synchronous or asynchronous
View Components in MVC 6//[ViewComponent(Name = "ProductDetails")]public class ProductDetailsViewComponent : ViewComponent{private readonly IProductsRepository _repository;
public ProductDetailsViewComponent(IProductsRepository repository){ _repository = repository;}
public IViewComponentResult Invoke(int id){ var product = _repository.GetProduct(id); return View(product);}
@Component.Invoke("ProductDetails", 1)// Or as async, if InvokeAsync is implemented in the view component@await Component.InvokeAsync("ProductDetails", 1)
And the Partial View?Create a default.cshtml file(content structured similar as with MVC <6)Place file in:
Controller-specific:Views/{controller}/Components/ProductDetails/Default.cshtmlShared:Views/Shared/Components/ProductDetails/Default.cshtml
Customizing view name is supportedCreate a file other than Default.cshtmlReturn View(viewName, model)
Injecting Services to Views
Preferable than using static classes/methodsUse interfaces instead of concrete typesRegister in IoC using different lifecycles
public class CatalogService : ICatalogService {
public async Task<int> GetTotalProducts() {...} // From ICatalogService}
@inject MyApp.Services.ICatalogService Catalog<html>
<body><h3>Number of products in the catalog</h3>@await Catalog.GetTotalProducts()</body>
</html>
services.AddTransient<ICatalogService, CatalogService>();
Last, but not Least, Tag Helpers
Do this: Ah? What’s that?Instead of doing this:
<form asp-anti-forgery="true" asp-action="UpdateProduct">…
</form>
using (Html.BeginForm("UpdateProduct", "Products", FormMethod.Post)){
@Html.AntiForgeryToken()…
}
It’s the return of Web Controls, NOOOOOO!!!
Tag Helpers are not EvilTag Helpers generate markup only within their enclosing tag Less Razor/HTML mess in the .cshtml fileJavaScript directive style approachUse C# to better construct the markup
Add/remove parts from the inner contentGenerate complex HTML (recursive, nested, …)Cache the output
Existing Tag HelpersHTML elements
<a>, <form>, <input>, <label>, <link>, <script>, <select>, <textarea>
Logical<cache>
PlaceholdersValidationSummary (<div>), ValidationMessage (<span>)
You can create your own Tag HelpersCheck out the source for referencehttps://github.com/aspnet/Mvc/tree/dev/src/Microsoft.AspNet.Mvc.TagHelpers
Key Improvements in ASP.NET 5
Totally modularNuGet is first-class citizen in ASP.NET 5Everything is a package
Lightweight - you use minumum set of modulesFaster startup, lower memory (>90%)Does not require .NET Framework installation - runtime environment (CLR) can be deployed with your application
Key Improvements in ASP.NET 5
Cross platform - can be hosted anywhere:IIS, self-hosted, Linux, MAC...
Web Forms are left aside for nowBetter developer experience
No-compile debugging with Roslyn, MVC unified programming model, basic DI out-of-the-box...
Everything is open-sourceArchitecture is OWIN based
Getting Started with ASP.NET 5Ships with Visual Studio 2015Walkthroughs and samples at http://asp.net/vnextDocumentation at http://docs.asp.net/en/latest Get the code from http://github.com/aspnetRead blogs at http://blogs.msdn.com/b/webdev Try out a nightly build from MyGethttps://www.myget.org/F/aspnetvnext
@idoFlatowhttp://bit.ly/flatowblog
Top Related