Dissecting DynaServer
References
- Nancy
- Nancy.Hosting.Self
Projects
ServerLibrary
Class Library project
File: WebServer.cs
namespace ServerLibrary
{
public class WebServer
{
private const string DEFAULT_URL_BASE = "http://localhost:1234";
private NancyHost server;
public WebServer()
{
var serverConfig = new HostConfiguration();
serverConfig.UrlReservations.CreateAutomatically = true;
server = new NancyHost(serverConfig, new Uri(DEFAULT_URL_BASE));
}
public void Start()
{
server.Start();
Process.Start("http://localhost:1234");
Console.WriteLine("Server has now started." + Environment.NewLine);
}
public void Stop()
{
server.Stop();
Console.WriteLine("Server has now stopped." + Environment.NewLine);
}
}
}
NancyServer
Console App
File: Program.cs | Using ServerLibrary, launch the web server |
space NancyServer
{
public class Program
{
static void Main(string[] args)
{
var server = new WebServer();
server.Start();
Console.WriteLine("Press any key to terminate server");
Console.ReadKey();
server.Stop();
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
Folder: Modules
File: IndexModule.cs | Server homepage |
using Nancy;
using System;
using System.Diagnostics;
namespace NancyServer
{
public class IndexModule : NancyModule
{
public IndexModule() : base("/")
{
Get["/"] = x => {
return "Hello, the server is now running. </br>" +
"It is now " + DateTime.Now.ToLongTimeString();
};
}
}
}
File: MathModule.cs | Define 4 routes |
- /math base route
- /math/pi returns PI
- /math/{number} returns the number. Define a private dynamic method
using Nancy;
using System;
namespace NancyServer
{
public class MathModule : NancyModule
{
public MathModule() : base("/math")
{
Get["/pi"] = x =>
{
return "Hello, PI is " + Math.PI;
};
Get["/echo/{number}"] = EchoNumber;
Get["/square/{number}"] = SquareNumber;
Get["/root/{number}"] = RootNumber;
}
private dynamic EchoNumber(dynamic parameters)
{
return "Your lucky number is " + parameters.number;
}
private dynamic SquareNumber(dynamic parameters)
{
double n;
try
{
if (!double.TryParse(parameters.number, out n)) throw new Exception();
}
catch (Exception)
{
return "Could not parse number";
}
return "The square number is " + Math.Pow(n, 2);
}
private dynamic RootNumber(dynamic parameters)
{
return "The root number is " + Math.Sqrt(parameters.number);
}
}
}
Return a json object
public TestModule() : base("/test")
{
Get["/json"] = parameters => {
var feeds = new string[] { "foo", "bar" };
return Response.AsJson(feeds);
};
}
Post something and return Html status (separate interface from implementation )
public TestModule() : base("/test")
{
Post["/users/{id}"] = Users;
}
private dynamic Users(dynamic parameters)
{
return "non va" + HttpStatusCode.OK;
}
Load an html page
Create a folder Views in NancyServer (the project where the server starts). Add the html files and set “Copy to output directory” to “Always”
Get["/"] = x =>
{
return Response.AsFile("Views/start.html", "text/html");
};
Add stylesheets
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css"></link>
<link rel='stylesheet prefetch' href='https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.css'></link>
<link rel='stylesheet prefetch' href='https://use.fontawesome.com/releases/v5.3.1/css/all.css'></link>
<link rel='stylesheet prefetch' href='https://cdnjs.cloudflare.com/ajax/libs/prism/1.14.0/themes/prism.min.css'></link>
<link rel="stylesheet" href="../css/cheatsheet.css"></link>
Add a textbox Input and a textbox Return to the html code
<!-- Add node to canvas -->
<div class="box">
<div class="columns">
<div class="column">
<h4 id="addnode" class="title is-3">Square number</h4>
Send the number to math/square/{number}
<br /> <br />
</div>
<div class="column">
<h6>Enter a number</h6>
<div class="field">
<input id="addNodeInput" class="input has-addons" type="text" placeholder="Type in name the number to square"></input>
<br></br>
<button class="button is-primary" onclick="addNode()">
<span>Square!</span>
</button>
<br></br>
<br></br>
<em>Result :</em>
<div class="notification">
<button class="delete"></button>
<div id="addNodeResult"></div>
</div>
</div>
</div>
</div>
</div>
Get the content of a textbox (addNodeInput). Send the GET request to the corresponding root
function addNode() {
var xhttp = new XMLHttpRequest();
var node = document.getElementById("addNodeInput").value;
xhttp.onreadystatechange = function () {
if (this.readyState == 4) {
document.getElementById("addNodeResult").innerHTML +=
this.responseText + "</br>";
}
};
var endpoint = "/Nodes/Add/" + node + "/";
xhttp.open("GET", endpoint, true);
xhttp.send();
}
Form
<div class="column is-12">
<div class="container content">
<h1>Family Instance By Face</h1>
<container>
<form>
<div class="form-group">
<legend for="inputAddress">Select Opening Family</legend>
<select type="text" class="form-control" id="inputAddress">
<option selected>Choose family...</option>
<option>Family 1</option>
<option>Family 2</option>
<option>Family 3</option>
</select>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<legend for="inputEmail4">Width</legend>
<input type="email" class="form-control" id="Width" placeholder="Enter the opening width">
</div>
<div class="form-group col-md-6">
<legend for="inputPassword4">Height</legend>
<input type="password" class="form-control" id="Height" placeholder="Enter the opening height">
</div>
</div>
<legend class="row-form-label row-sm-2 pt-0">Position along the beam</legend>
<div class="form-check form-check-inline row-md-6">
<input class="form-check-input" type="radio" name="inlineRadioOptions" id="inlineRadio1" value="Start Point">
<label class="form-check-label" for="inlineRadio1">Start Point</label>
</div>
<div class="form-check form-check-inline row-md-6">
<input class="form-check-input" type="radio" name="inlineRadioOptions" id="inlineRadio2" value="Mid Point">
<label class="form-check-label" for="inlineRadio2">Mid Point</label>
</div>
<div class="form-check form-check-inline row-md-6">
<input class="form-check-input" type="radio" name="inlineRadioOptions" id="inlineRadio3" value="End Point">
<label class="form-check-label" for="inlineRadio3">End Point</label>
</div>
<div class="form-group">
<legend for="inputAddress2">Offset</legend>
<input type="text" class="form-control" id="inputAddress2" placeholder="Opening offset">
</div>
<button type="submit" class="btn btn-primary">Place Void</button>
</form>
</div>
</div>
Written on November 19, 2018