ASP.NET Internals

47
Vitaly Baum @butaji ASP.NET MVC Internals

Transcript of ASP.NET Internals

Vitaly Baum @butaji

ASP.NET MVC

Internals

> whoami

Vitaly Baum

Product Manager @ bright box

[email protected]

http://twitter.com/butaji

BACKGROUND

Web Application

MVC

What and How

Controller

How do I write Controllers?

How do requests come to Controller?

View

How does ViewEngine render views?

Why do I need to change ViewEngine?

AGENDA

QUESTIONS• Non-IIS

• Azure in production

• NoSQL

• NGINX

OK. MVC

MVC• Front Controller

An object that handles all requests

• Page Controller

An object that handles a request for a specific

page or action on a Web site

HTTP

HTTP

1. Request

2. Environment

3. Response

IIS• System.Web.dll

• IHttpHandler (extensions)

• IHttpModule (HttpApplication events)

using System;

using System.Web;

public class LoggingHttpModule : IHttpModule

{

public void Dispose() {}

public void Init(HttpApplication context)

{

context.BeginRequest += BeginRequest;

}

void BeginRequest(object sender, EventArgs e)

{

Logger.Instance.Log("Hi there!");

}

}

public class RequestHandler : IHttpHandler

{

public RequestHandler() { }

public bool IsReusable { get { return false; } }

public void ProcessRequest(HttpContext context)

{

context.Response.ContentType = "application/json";

context.Response.Write("{ id : 1 }");

}

}

ASP.NET MVC?

• Were implemented on HttpHandlers

• https://servicestack.net/features

• http://www.castleproject.org/projects/monorail/

• http://mvc.fubu-project.org

IIS + ASP.NET• Highly coupled

• Hard to manage (ain’t my job)

• New features only with OS updates

a. Web Server

b. Middleware

c. Application

SERVER INTEROP

• authentication

• cookies

• authorization

• output caching

• localisation

• request servicing (app)

MIDDLEWARE

SERVER INTEROP• Rack (ruby)

• WSGI (Python)

• Node.js

• OWIN (.NET)

require 'rack'

app = Proc.new do |env| # ENV HASH[

'200', # HTTP CODE{'Content-Type' => 'text/html'}, ['A barebones rack app.’] # BODY

]end

Rack::Handler::WEBrick.run app

MIDDLEWARE

var http = require('http');

var server = http.createServer(function (req, res) {

res.writeHead(200,

{'Content-Type': 'text/plain'});

res.end('Hello World\n');

})

server.listen(1337, '127.0.0.1');

MIDDLEWARE

var express = require('express')var app = express()

app.use(function (req, res, next) {console.log('Time:', Date.now());next();

});

MIDDLEWARE

//OWIN Implementation

using AppFunc = Func<

IDictionary<string, object>,

Task

>;

MIDDLEWARE

OWIN

public class Startup{

public void Configuration(IAppBuilder app){

app.Run(context => {return context

.Response.WriteAsync("Hi OWIN/Katana");});

}}

ASP.NET MVC

ASP.NET MVC LIFECYCLERouting

UrlRoutingModule -> IRouteHandler ->

IHttpHandler

Controller

Execute -> Filters -> Model Binding -> Action

Action

Your Code

Result

Views -> TypeFormater

ROUTE HANDLER

public class MyRouteHandler : IRouteHandler{

public IHttpHandler GetHttpHandler(RequestContext requestContext)

{var handler = new MyMVCHandler();handler.RequestContext = requestContext;return handler;

}}

ROUTE HANDLER• In case of dynamic routes

• CMS

• Blog with custom Slugs

MVC HANDLERpublic class MyMVCHandler : MvcHandler{

protected override void ProcessRequest(IHttpContexthttpContext)

{var controllerName = GetRequiredString(this.RequestContext.RouteData, "controller");

var controller = CreateController(controllerName);var controllerContext = new

ControllerContext(base.RequestContext, controller);controller.Execute(controllerContext);

}private IController CreateController(string controllerName){

return _controllerFactory.Create(controllerName);}

}

DEPENDENCY MGMT

public class CustomControllerFactory : IControllerFactory{public IController CreateController(RequestContext

requestContext, string name){

return _serviceLocator.Resolve<IController>(name);}}

DEPENDENCY MGMT//ASP.NET vNext has new way to inject dependencies

public class Startup{public void Configure(IBuilder app){var services = new ServiceCollection();services.AddTransient<IMessageGenerator,

HelloMessageGenerator>();

app.UseMiddleware(typeof(ContainerMiddleware));}

}

OK. CTRL

CONTROLLERFAT VS SKINNY

CONTROLLER[HttpPost, ActionName("Delete")]public async Task<ActionResult> DeleteConfirmed(int id){var album = await _storeContext.Albums.FindAsync(id);if (album == null){return HttpNotFound();

}

_storeContext.Albums.Remove(album);await _storeContext.SaveChangesAsync();

return RedirectToAction("Index");}

CONTROLLER

[HttpPost, ActionName("Delete")]public async Task<ActionResult> DeleteConfirmed(int id){

var removed = await _albumService.Remove(id);

return Status.NotFound == removed.Status? HttpNotFound(): RedirectToAction(“Index");

}

CONTROLLER

//vNext can host POCOs controllerspublic List<Data> GetData(){return null; //will return 204 (NoContent)

}

def {action_name}( {params} )

app_res = {domain_service}.{call}( {params} )

return app_res

end

OK. VIEW

SEO OF SPA

SEO OF SPAMIDDLEWARE

Middleware

ApplicationGET /

User-Agent: Chrome

GET /

User-Agent: Google

JSON

Middleware

Application

GET /

User-Agent: Google

GET /

User-Agent: ChromeHTML

SEO OF SPASHARED TEMPLATES

SHARED TEMPLATES

Server Client

Template

http://mustache.github.io

{{#repo}}

<b>{{name}}</b>

{{/repo}}

{

"repo": [

{ "name": "resque" },

{ "name": "hub" },

{ "name": "rip" }

]

}

<b>resque</b>

<b>hub</b>

<b>rip</b>+ =

YET ANOTHER TEMPLATE

VIEW ENGINEpublic interface IViewEngine{

ViewEngineResult FindPartialView(ControllerContext ctx, stringname, bool useCache);

ViewEngineResult FindView(ControllerContext ctx, string viewName, string masterName, bool useCache);

void ReleaseView(ControllerContext ctx, IView view);}

public interface IView{void Render(ViewContext ctx, TextWriter writer);

}

http://buildstarted.com/2013/12/16/javascript-view-engine-for-aspnet/

VIEW ENGINE

services.AddMvc().Configure<MvcOptions>(options =>{

options.ViewEngines.Add(new MyCustomerViewEngine ());

});

COVERED TOPICS

Web Application

MVC

What and How

Controller

How do I write Controllers?

How do requests come to Controller?

View

How does ViewEngine render views?

Why do I need to change ViewEngine?

THANK

YOUVitaly Baum

@butaji