Enable attribute routing for Nancy project, and build route URL with compiled-time checked lambda expression.
PM> Install-Package Nancy.AttributeRoutingWith AttributeRouting, there is no need to write NancyModule, route and content negotiate are handled by attributes.
With AttributeRouting, you can write a clean MVVM (Model - View - View Model) approach with Nancy framework.
This tutorial walks through how to use AttributeRouting to build pages. For Full examples, please check examples folder.
First, we are going to create a page to list todo items in the /todo routing.
The following are the corresponding view and view model. (Note: you can use any view engine, I use the default Super Simple View Engine in my example.)
<!-- show todo list view, place as `/Views/TodoList.html` -->
<html>
<body>
<ul>
@Each.Items
<li>@Current</li>
@EndEach
</ul>
</body>
</html>// show todo list view model, place as `/ViewModels/TodoList.cs`
public class TodoList
{
private readonly ITodoDatabase database;
public TodoList(ITodoDatabase database) // Use IoC to inject dependencies to view model
{
this.database = database;
}
public IEnumerable<string> Items => this.database.TodoItems;
[Get("/todo")]
[View(nameof(TodoList))]
public TodoList Get() => this;
}Notice the Get and View attribute on Todo class methods:
- The
Getattribute register/todopath to Nancy routing table. - The
Viewattribute tells Nancy content negotiate which view template should pick up when browser requests HTML. - The
Viewattribute value (nameof(TodoList)) works with Nancy view location convention to find out the proper view template to render. That is/Views/TodoList.htmlin my example.
Next, we are going to create a page to add new Todo items. The new page is under route path /todo/add.
<!-- add todo item view, place as `/Views/TodoAdd.html` -->
<html>
<body>
<form method="post">
<input type="text" name="description" placeholder="Description..." />
<input type="submit" value="Submit" />
</form>
</body>
</html>// add todo item view model, place as `/ViewModels/TodoAdd.cs`
[RoutePrefix("todo")]
public class TodoAdd
{
private readonly ITodoDatabase database;
public TodoAdd(ITodoDatabase database)
{
this.database = database;
}
[Get("add")]
[View(nameof(TodoAdd))]
public TodoAdd Get() => this;
[Post("add")]
public Response Post(Form form)
{
this.database.TodoItems.Add(form.Description);
return new RedirectResponse("/todo");
}
public class Form
{
public string Description { get; set; }
}
}- This page shows a form to add a new todo item.
- The
RoutePrefixattribute prefixes routing every route in the class - The
Getattribute on theGetmethod is to responseTodoAddview to user. - The
Postattribute on thePostmethod is to handle the HTTP POST method request. - The
Postmethod parameter binds the request payload as a non-primitive class (Formclass here). - The
Postmethod returnsNancy.Responseinstance directly, so it will not do content negotiate.
The /todo is hard coded in both pages. With project grows up, it is hard to update all route strings even do simple refactor.
Nancy.AttributeRouting provides an interface IUrlBuilder to generate page URL in runtime.
For example, update the redirect URL code in TodoAdd view model:
// update TodoAdd view model in `/ViewModels/TodoAdd.cs`
public class TodoAdd
{
private readonly IUrlBuilder builder; // injected from constructor
public TodoAdd(IUrlBuilder builder, ITodoDatabase database)
{
// other codes keep the same...
this.builder = builder;
}
public Response Post(Form form)
{
// other codes keep the same...
string todoListUrl = this.builder.GetUrl<TodoList>(m => m.Get(null));
return new RedirectResponse(todoListUrl);
}
}- The
IUrlBuilderinterface is registered to Nancy IoC at bootstrap. It is out-of-box to inject to view models. - The
IUrlBuilderinterface providesGetUrl<TViewModel>method to generated view model URL in runtime. - The
GetUrllambda expression arguments will replace route variables when necessary.
We created two pages with Nancy and AttributeRouting. Following MVVM pattern, only models (the ITodoDatabase part), views and view models are created. In the view - view model part, we focus on how the view looks like, what functions we need to provide for the corresponding views.
Check examples folder to see a full MVVM approach to build website.
See Nancy.AttributeRouting.md file.
MIT License.