The magic of Dynamic in Nancy Fx

Post on 21-May-2015

831 views 4 download

Tags:

description

A brief introduction of Dynamic Language Runtime, Nancy Fx and how dynamic features of .net framework are used in Nancy Fx.

Transcript of The magic of Dynamic in Nancy Fx

C# Unleashed

Michele Capra a.k.a. @piccoloaiutanteSoftware Contractor @ OrangeCodemichele@orangecode.it

The magic of Dynamic in Nancy FX

@dnlombardia#cunleashed

Who I am Software contractor :

- C# Asp.net mvc, Wpf, WinRT, Windows Phone..

- Python, Django

What are we talking about today

• Dynamic and DLR

• Introduction to Nancy FX

• Some dynamic features of Nancy FX

Dynamic Language Runtime (DLR)• .NET Framework 4 • It provides the infrastructure that supports the

dynamic type in C#, and also the implementation of dynamic programming languages.

• System.Dynamic:• DynamicObject

• IronPython and IronRuby.

Dynamic Language Runtime (DLR)

The dynamic keyword

• New keyword introduced in VS2010.

• Behaves like type object in most circumstances.

• Objects of type dynamic are neither resolved or type checked by the compiler.

What is Nancy FX

Nancy is a lightweight, low-ceremony, framework for building HTTP based services on .Net and Mono.

The goal of the framework is to stay out of the way as much as possible and provide a super-duper-happy-path to all interactions.

Nancy FX philosophy• Extensive use of defaults and conventions

• Designed to handle DELETE, GET, HEAD, OPTIONS, POST, PUT and PATCH request.

• Provides a simple, elegant, Domain Specific Language (DSL) for returning a response

• Built with .NET Framework Client Profile, can be hosted with Asp.Net, WCF, Azure, Umbraco, Nginx on Ubuntu with Mono, self hosted…

Nancy Fx – Basic Examplepublic class HelloModule: Nancy.NancyModule{ public HelloModule () { Get["/"] = _ => "Hello World!"; }}

Nancy Fx – Basic Examplepublic class HelloModule: Nancy.NancyModule{ public HelloModule () { Get["/"] = _ => "Hello World!"; }}

Sinatra (ruby)require 'sinatra'

get ’/' do "Hello World!"end

Flask (python)from flask import Flaskapp = Flask(“HelloApp”)

@app.route("/”)def hello(): return "Hello World!"

WebApi (controller)using System.Web.Http;

public class HelloWorldController : ApiController { public string Get() {

return "Hello World"; }

}

WebApi (global.asax.cs)public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { AreaRegistration.RegisterAllAreas();

GlobalConfiguration.Configuration.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } }

Example 1 – Post & QueryString parampublic class HelloModule : Nancy.NancyModule{ public HelloModule() { Get[“/hello/{name}”] = p => “Hello “ + p.name; }}

Example 1 – Post & QueryString parampublic class HelloModule : Nancy.NancyModule{ public HelloModule() { Get[“/hello/{name}”] = p => “Hello “ + p.name; }}

DynamicDictionary

Dynamic Dictionary from Nancy/// A dictionary that supports dynamic access.

public class DynamicDictionary : DynamicObject, IEquatable<DynamicDictionary>, IHideObjectMembers, IEnumerable<string>, IDictionary<string, object>{

…..}

Dynamic Dictionary from Nancy dynamic user = new DynamicDictionary();

user[”Years"] = 5;

int years = user.Years;

Example 1 – Post & QueryString parampublic class HelloModule : NancyModule{ public HelloModule() { Get[“/hello/{name}”] = p => “Hello “ + p.name; Post["/hello"] = p => “Hello “ + Request.Form.Name; }}

Example 2- Lambda structurepublic class HelloModule : NancyModule{ public HelloModule() { Get[“/hello/{name}”] = p => “Hello “ + p.name; }}

Example 2- Lambda structurepublic abstract class NancyModule : IHideObjectMembers{

….public RouteBuilder Get

{ get { return new RouteBuilder("GET", this); } }

….}

Example 2- Lambda structure public class RouteBuilder : IHideObjectMembers { /// Defines a Nancy route for the specified

/// <value>A delegate that is used to invoke the route.</value> public Func<dynamic, dynamic> this[string path] { set { this.AddRoute(path, null, value); } }

…}

Example 3 – Response type castpublic class DefaultRouteInvoker : IRouteInvoker { /// Invokes the route with the provided parameters. /// <returns>A Response instance.</returns> public dynamic Invoke(DynamicDictionary parameters) { return this.Action.Invoke(parameters); }}

Example 3 – Response type castpublic class DefaultRouteInvoker : IRouteInvoker { private Response InvokeRouteWithStrategy(dynamic result, NancyContext context) { var isResponse =(CastResultToResponse(result) != null);

return (isResponse) ? ProcessAsRealResponse(result, context) : this.ProcessAsNegotiator(result, context); }}

Example 3 – Response type castpublic class Response: IDisposable{ public string ContentType { get; set; } public Action<Stream> Contents { get; set; } public IDictionary<string, string> Headers { get; set; } public HttpStatusCode StatusCode { get; set; } public IList<INancyCookie> Cookies { get; private set; }}

Not Dynamic

Example 3 – Response type castpublic class DefaultRouteInvoker : IRouteInvoker { private Response InvokeRouteWithStrategy(dynamic result, NancyContext context) { var isResponse = (CastResultToResponse(result) != null);

return (isResponse) ? ProcessAsRealResponse(result, context) : this.ProcessAsNegotiator(result, context); }}

Example 3 – Response type cast private static Response CastResultToResponse(dynamic result) { try { return (Response)result; } catch (Exception e) { return null; } }

Example 3 – Response type cast public static implicit operator Response(HttpStatusCode statusCode) { return new Response { StatusCode = statusCode }; }

public static implicit operator Response(int statusCode) { return new Response { StatusCode = (HttpStatusCode)statusCode }; } public static implicit operator Response(string contents){ return new Response { Contents = GetStringContents(contents) }; }

public static implicit operator Response(Action<Stream> streamFactory){ return new Response { Contents = streamFactory }; }

Demo Time

Example 4 – Model binding public class Customer { public int Id { get; set; }

public string Name { get; set; }

public DateTime RenewalDate { get; set; }}

Example 4 – Model binding public class CustomersModule : NancyModule { public CustomersModule() : base("/customers") { Post["/"] = _ => { Customer model = this.Bind(); return 200; }; } }

Example 4 – Model bindingpublic static dynamic Bind(this NancyModule module, BindingConfig configuration, params string[] blacklistedProperties){ return new DynamicModelBinderAdapter(

module.ModelBinderLocator, module.Context, null, configuration,

blacklistedProperties);}

Example 4 – Model binding public class DynamicModelBinderAdapter : DynamicObject { … public DynamicModelBinderAdapter(IModelBinderLocator locator,…) { … this.locator = locator; … }

public override bool TryConvert(ConvertBinder binder, out object result) { var modelBinder = this.locator.GetBinderForType(binder.Type, this.context); if (modelBinder == null) { throw new ModelBindingException(binder.Type); } }}

Provides implementation for type conversion operations. Classes derived from the DynamicObject class can override this method to specify dynamic behavior for operations that convert an object from one type to another.

Example 4 – Model binding public class CustomersModule : NancyModule { public CustomersModule() : base("/customers") { Post["/"] = _ => { Customer model = this.Bind(); return 200; }; } }

Recap

• DLR and dynamic keyword

• How dynamic features are used in Nancy

• Little demo on type conversion from dynamic

That’s allSpecial thanks to Christian Horsdal and The Nancy Fx team !

Nancy repos:https://github.com/NancyFx/Nancy

Twitter:Http://twitter.com/piccoloaiutante