-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Model binding
Data can be sent to your Nancy application in many ways, for instance as part of the query string, as captured parameters on a route or as the body of a request. Manually working with the data spread out over several places is perfectly fine in some scenarios, but there are times where you want to unify that into something richer - a model
- which is where Nancy’s “model binding” capabilities come into play.
Nancy, with a single line of code, can collect information from all of the above sources, including richer request bodies such as JSON
and XML
, and convert them into an instance of a type of your model.
Although Nancy ships with quite a lot of default binders out of the box, the binding system is easily extensible if you need to support different content types or more complex binding scenarios. It’s as easy as including a namespace.
Nancy’s model binding is defined as a single extension method on the NancyModule
type. The extensions are located in the Nancy.ModelBinding
namespace and adds Bind() and BindTo() methods:
Foo f = this.Bind();
var f = this.Bind<Foo>();
var f = this.BindTo(instance);
All three have the exact same functionality, they just provide different ways of doing the same thing. The first two Bind() overloads will create a new instance of the Foo
type and bind to that, while BindTo() will bind to an existing instance.
Sometimes you want the model binder to ignore certain information when populating the model from all the various sources (to prevent ‘over posting’ attacks for example). To accommodate this, the model binder can be called with an optional list of blacklisted properties on the model:
var f = this.Bind<Foo>(f => f.id, f => f.creator, f => f.createddate);
The blacklist is a “params” array of Expressions on the model type, where the expressions specify the name of the model properties that should be ignored by the model binder.
or:
var f = this.Bind<Foo>("id", "creator", "createddate");
The blacklist is a “params” array of strings, where the strings represents the name of the model properties that should be ignored by the model binder.
When binding to an typed- array, list or ienumerable. The blacklist is maintained for the elements in the sequence.
Sometimes you want to send structured data, such as JSON
and XML
; in the request body and bind it to your model. The model binder in Nancy supports the notion of body deserializers that provide the functionality required for this.
Out of the box, Nancy ships with two body deserializers, one for JSON and one for XML. The model binder will use the Content-Type
HTTP header to determine which deserializer should be used for the attached request body.
By default, the standard JSON deserializer will be used to deserialize any "json based" content types such as application/json
, text/json
and application/vnd....+json
. Similarly, the standard XML deserializer will be used for “XML based” content types: application/xml
, text/xml
and application/vnd....+xml
.
As with the other model binders, you can author your own body deserializers and Nancy will automatically detect them and any user defined binders take priority over the built in ones.
NOTE: If you encounter the Nancy.Json.JsonSettings.MaxJsonLength Exceeded error because your payload is too high, change that limit in your Bootstrapper in ApplicationStartup
to be Nancy.Json.JsonSettings.MaxJsonLength = int.MaxValue;
For auto model binding checkbox to boolean value, make sure to set the value="true"
in the checkbox.
<input type="checkbox" name="rememberMe" value="true"/>
public class LoginModel
{
public bool RememberMe { get; set; }
}
Nancy supports posting in lists of things and binding to them, on the server-side, as before with this.Bind<T>();
.
Nancy supports binding against lists of items (or arrays or anythings else that implements IEnumerable) in two different ways; as a list on the object your binding against or as a list of objects.
If you have a form like this:
<form action="/ArrayOnObject" method="post">
<input type="text" name="Tags" value="Tag1,Tag2,Tag3"/>
<input type="text" name="Ints" value="1,2,3,4,4,5,6,3,2,21,1"/>
<input type="submit" value="Submit"/>
</form>
Then you can bind to this class:
public class Posts
{
public string[] Tags { get; set; }
public int[] Ints { get; set; }
}
with this simple statement:
var listOfPosts = this.Bind<Posts>();
Imagine you have a system to enter who commits the most to a OSS-framework. You allow the users of the site to post a bunch of users-names and their number of commits at once.
Here's an example form with random dummy data:
<form action="/SimpleListDemo" method="post">
User 1:<input type="text" name="Name[0]" value="thecodejunkie" />
Commits <input type="text" name="Commits[0]" value="1068"/>
<br />
User 2:<input type="text" name="Name[1]" value="grumpydev" />
Commits <input type="text" name="Commits[1]" value="1049"/>
<br />
User 3:<input type="text" name="Name[2]" value="jchannon" />
Commits <input type="text" name="Commits[2]" value="109"/>
<br />
User 4:<input type="text" name="Name[3]" value="prabirshrestha" />
Commits <input type="text" name="Commits[3]" value="75"/>
<br />
User 5:<input type="text" name="Name[4]" value="phillip-haydon" />
Commits <input type="text" name="Commits[4]" value="40"/>
<br />
<input type="submit" value="Test the binding thingy"/>
</form>
This can then be bound (with this.Bind<List<User>>();
) to a list of object of this class:
public class User
{
public string Name { get; set; }
public int Commits { get; set; }
}
Nancy supports two kind of list delimiters for the name of the items in the HTML-form;
- underscores (
Name_1
,Name_2
etc.) - brackets (
Name[1]
,Name[2]
etc.)
[<< Part 5. The before and after module hooks](The before and after module hooks) - Documentation overview - Part 7. Bootstrapper >>
- Introduction
- Exploring the Nancy module
- Routing
- Taking a look at the DynamicDictionary
- Async
- View Engines
- Using Models
- Managing static content
- Authentication
- Lifecycle of a Nancy Application
- Bootstrapper
- Adding a custom FavIcon
- Diagnostics
- Generating a custom error page
- Localization
- SSL Behind Proxy
- Testing your application
- The cryptography helpers
- Validation
- Hosting Nancy with ASP.NET
- Hosting Nancy with WCF
- Hosting Nancy with Azure
- Hosting Nancy with Suave.IO
- Hosting Nancy with OWIN
- Hosting Nancy with Umbraco
- Hosting Nancy with Nginx on Ubuntu
- Hosting Nancy with FastCgi
- Self Hosting Nancy
- Implementing a Host
- Accessing the client certificate when using SSL
- Running Nancy on your Raspberry Pi
- Running Nancy with ASP.NET Core 3.1