模型绑定支持字段或属性两种方式,使用模型绑定,能够经过下面的方式实现绑定:git
// Properties public class Model{ public int Value { get; set; } }
// Fields public class Model{ public int Value; }
每一个类有本身的参数方式。使用属性意味着你须要后续的操做中使用数据验证或者加强的功能,你的代码已经经过get
访问器调用一个方法, 而且你能够改变这个方法的实现。 换一种说法, 当属性没有明确的使用方式 (就像上面示例中的-- 没有提供实际的 get
和set
访问器), C# 编译器根据名称经过隐含的操做自动地获取对应字段的值。 这个字段名须要惟一,以防止和其它成员名冲突。为了实现这个目的,不可以使用的C#特殊标识符。特别地如包含了尖括号。若是数据类型使用了 DataContractSerializer
, 将会引起这个结果,由于 DataContractSerializer
操做针对字段,而不是属性。它会使用相同的名字获取字段和尝试建立XML元素。由于XML元素不能包括 <
和>
字符,将会引起异常, 在内部的处理会对字段名进行转义。 (异常能够在运行使用DataContractSerializer的程序时经过调试输出查看,常见的状况一般是默认WCF绑定配置中。) 异常和转换并非必需要执行,你能够经过使用符合的XML标识的字段避免它。github
除非你的项目有外部组件引用了它,你使用那种方式可有可无,由于大多数.net访问属性和字段的语法彻底相同的。所以,在大多数状况下, 你能够更改你的模型类型,使用属性或者字段,编译时无需作其余修改。数组
对于自动模型绑定到复选框的布尔值,肯定设置了value="true"
在复选框中。dom
<input type="checkbox" name="rememberMe" value="true"/>
public class LoginModel{ public bool RememberMe; }
Nancy支持服务端提交列表形式的东东而且绑定他们,就像以前使用this.Bind<T>()的方式。async
Nancy使用两种方式支持绑定列表项(或者数组及其余能够实现可枚举的类型),做为你绑定到的那个对象的列表或通用对象的列表。ide
若是你有相似下面的表单:post
<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>
你能够绑定到下面的类:ui
public class Posts{ public string[] Tags; public int[] Ints; }
使用这样的语句:this
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.spa
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; public int Commits; }
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.)
Here's an end-to-end model binding example that shows the full model + view + module.
/// <summary> /// DTO for creating a new user /// </summary> public class NewUser { public string UserName { get; set; } public string Email { get; set; } public string Password { get; set; } }
ViewBag.Title = "AkkaChat - Register"; } @inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<AkkaChat.ViewModels.NewUser> <div class="container-fluid"> <div class="row-fluid"> <h1>Register an AkkaChat Account</h1> @if (ViewBag.ValidationError != null) { <div class="alert-error"> <p>Error! @ViewBag.ValidationError</p> </div> } <form class="form-horizontal" method="POST" action="~/register"> <div class="control-group"> <label class="control-label" for="UserName">Username</label> <div class="controls"> <input type="text" name="UserName" id="UserName" placeholder="Username"> </div> </div> <div class="control-group"> <label class="control-label" for="Email">Email</label> <div class="controls"> <input type="text" id="Email" name="Email" placeholder="Email"> </div> </div> <div class="control-group"> <label class="control-label" for="Password">Password</label> <div class="controls"> <input type="password" name="Password" id="Password" placeholder="Password"> </div> </div> <div class="control-group"> <div class="controls"> <button type="submit" class="btn">Register</button> </div> </div> </form> </div> </div>
/// <summary>/// Module responsible for handling authentication and account creation/// </summary>public class AuthModule : NancyModule{ private readonly IMembershipService _membership; public AuthModule(IMembershipService membership) { _membership = membership; Get["/register"] = _ => { //already logged in if (Context.CurrentUser.IsAuthenticated()) return Response.AsRedirect("~/"); return View["register"]; }; Post["/register", true] = async (x, ct) => { NewUser registerAttempt = this.Bind<NewUser>(); //model binding! var validationError = ""; var failedValidation = false; if (string.IsNullOrEmpty(registerAttempt.UserName)) { failedValidation = true; validationError += string.Format("Must provide a username!<br>"); } else { //check to see if a username is available var userNameAvailable = await _membership.IsUserNameAvailable(registerAttempt.UserName); if (!userNameAvailable) { validationError += string.Format("{0} is already taken. Please pick another username.<br>", registerAttempt.UserName); failedValidation = true; } } if (string.IsNullOrEmpty(registerAttempt.Password)) { failedValidation = true; validationError += string.Format("Must provide a password!<br>"); } if (string.IsNullOrEmpty(registerAttempt.Email)) { failedValidation = true; validationError += string.Format("Must provide an email!<br>"); } if (failedValidation) { ViewBag.ValidationError = validationError; return View["register"]; } var registerResult = await _membership.AddUser( registerAttempt.UserName, registerAttempt.Email, registerAttempt.Password); //success! if (!(registerResult is MissingUserIdentity)) { return this.LoginAndRedirect(registerResult.CookieId, DateTime.Now.AddDays(30), "~/"); } else //failure! { ViewBag.ValidationError = string.Format("Unable to register as {0} - server error.", registerAttempt.UserName); return View["register"]; } }; } }