在我的ASP.NET MVC应用程序中,我有一个动态的行式表单,当用户点击一个按钮时,在本例中是 "添加",它将在表单中添加一个新的行,其中包含所需的字段。我试图让它与ASP.Net Identity一起工作,但没有任何运气。
我相信这将类似于有一个列表,然后在列表中做一个for循环来注册用户,但是在实践中证明是很混乱的。
<input name="__RequestVerificationToken" type="hidden" value=""> <div class="row">
<div class="form-group mx-1">
<label class="control-label" for="Email">Email</label>
<input name="Email" class="form-control" data-val="true" data-val-email="The Email field is not a valid e-mail address." data-val-required="The Email field is required." id="Email" placeholder="Email" type="text" value="">
</div>
<div class="form-group mx-1">
<label class="control-label" for="User_Role">User Role</label>
<select name="UserRoles" class="form-control" data-val="true" data-val-required="The UserRoles field is required." id="UserRoles" ><option value="">Role</option>
<option value="Employee">Employee</option>
<option value="Manager">Manager</option>
</select>
</div>
<div class="form-group mx-1">
<label class="control-label" for="Password">Password</label>
<input name="Password" class="form-control valid validate-equalTo-blur" data-val="true" data-val-length="The Password must be at least 6 characters long." data-val-length-max="100" data-val-length-min="6" data-val-required="The Password field is required." id="Password" placeholder="Password" type="password" value=""aria-describedby="Password-error" aria-invalid="false">
</div>
<div class="form-group mx-1">
<label class="control-label" for="ConfirmPassword">Confirm password</label>
<input class="form-control valid" name="ConfirmPassword" data-val="true" data-val-equalto="The password and confirmation password do not match." data-val-equalto-other="*.Password" id="ConfirmPassword" placeholder="Confirm Password" type="password" value="" aria-describedby="ConfirmPassword-error" aria-invalid="false">
</div>
<button type="button" class="btn btn-sm btn-info add_button form-control col-md-1" style="margin-top: 37px"><i class="fas fa-plus"></i></button>
<div class="field_wrapper">
<div class="form-group row">
<fieldset class="form-group mx-1">
<label class="control-label" for="Email">Email</label>
<input name="Email" class="form-control" data-val="true" data-val-email="The Email field is not a valid e-mail address." data-val-required="The Email field is required." id="Email" placeholder="Email" type="text" value="">
</fieldset>
<fieldset class="form-group mx-1">
<label class="control-label" for="User_Role">User Role</label>
<select name="UserRoles" class="form-control" data-val="true" data-val-required="The UserRoles field is required." id="UserRoles" ><option value="">Role</option>
<option value="Employee">Employee</option>
<option value="Manager">Manager</option>
</select>
</fieldset>
<fieldset class="form-group mx-1">
<label class="control-label" for="Password">Password</label>
<input name="Password" class="form-control" data-val="true" data-val-length="The Password must be at least 6 characters long." data-val-length-max="100" data-val-length-min="6" data-val-required="The Password field is required." id="Password" placeholder="Password" type="text" value="">
</fieldset>
<fieldset class="form-group mx-1">
<label class="control-label" for="ConfirmPassword">Confirm password</label>
<input name="ConfirmPassword" class="form-control" data-val="true" data-val-equalto="The password and confirmation password do not match." data-val-equalto-other="*.Password" id="ConfirmPassword" placeholder="Confirm Password" type="text" value="">
</fieldset>
<a href="#" class="btn btn-sm btn-danger remove_button form-control col-md-1" style="margin-top: 37px"><i class="fas fa-times center"></i></a>
</div>
</div>
<div class="row">
<button type="submit" class="btn btn-info my-2">Submit</button>
<a type="button" class="btn btn-warning my-2 ml-1" href="/Home">Back</a>
</div>
Jquery Form.My AccountController方法
$(document).ready(function () {
var max_fields = 10; //maximum input boxes allowed - change as needed
var wrapper = $(".field_wrapper"); //Fields wrapper
var add_button = $(".add_button"); // class add button
var remove_button = $('.remove_button'); // class remove button
var html = `
<div class="form-group row">
<fieldset class="form-group mx-1">
@Html.LabelFor(m => m.Email, new { @class = "control-label" })
@Html.TextBoxFor(m => m.Email, new { @class = "form-control", placeholder="Email" })
</fieldset>
<fieldset class="form-group mx-1">
@Html.Label("User Role", new { @class = "control-label" })
@Html.DropDownList("UserRoles", (SelectList)ViewBag.Name, "Role", new { @class = "form-control"})
</fieldset>
<fieldset class="form-group mx-1">
@Html.LabelFor(m => m.Password, new { @class = "control-label" })
@Html.TextBoxFor(m => m.Password, new { @class = "form-control", placeholder="Password" })
</fieldset>
<fieldset class="form-group mx-1">
@Html.LabelFor(m => m.ConfirmPassword, new { @class = "control-label" })
@Html.TextBoxFor(m => m.ConfirmPassword, new { @class = "form-control", placeholder="Confirm Password" })
</fieldset>
<a href="#" class="btn btn-sm btn-danger remove_button form-control col-md-1" style="margin-top: 37px"><i class="fas fa-times center"></i></a>
</div>`;
var x = 1; //initlal count
$(add_button).click(function (e) { //on add button click
e.preventDefault();
if (x < max_fields) { //max input box allowed
x++; // increment value of x
$('.counter').text(x);
$(wrapper).append(html); //add html
}
});
$(wrapper).on("click", remove_button, function (e) { // runs when a user clicks on anything with the class 'remove_button'
e.preventDefault(); // prevent default, duh
$(this).parent('div').remove(); // get parent of each element and remove it
x--; // decrement the value of x
$('.counter').text(x); // update text with the count only after value of x has been changed
})
});
我的AccountController方法--我有一个雇员类,它继承了身份模型,也使用自己的视图模型。
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> RegisterEmployees(EmployeeViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
return RedirectToAction("Index", "Home");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
我很确定之前的答案是可行的,但你评论了以下内容 我的另一个答案 要求看这个问题,所以在这里你去。
我已经尽量保持它的简单性,所以你必须添加你自己的额外标记,样式,数据注释等。
很自圆其说,我们只是为视图建立了一个模型,这个模型有一个用户模型列表。
public class RegisterLotsModel
{
public List<UserToRegister> UsersToRegister { get; set; }
}
public class UserToRegister
{
public string UserName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
只是一个简单的表单,里面有一些输入字段,用来注册用户。周围的divs在JS中被引用,并在我们为额外的用户添加HTML时使用。
@model BulkRegister.Models.RegisterLotsModel
@using (Html.BeginForm("BulkRegister"))
{
<div class="users-to-register">
<div class="user-container">
<input type="text" name="UsersToRegister[0].UserName" />
<input type="email" name="UsersToRegister[0].Email" />
<input type="password" name="UsersToRegister[0].Password" />
</div>
</div>
<input type="button" id="add-user-button" value="Add another user" />
<input type="submit" value="Register the users" />
}
@section scripts {
<script src="~/Scripts/bulk-reg.js"></script>
}
我把它放在一个单独的文件中,但如果你喜欢的话,你可以直接把它弹到视图的底部。我们计算有多少 user-container
类来计算我们要添加的 HTML 的索引应该是什么。这意味着我们不需要用一个单独的变量来跟踪。
$(function () {
$('#add-user-button').click(function () {
// how many users are there already
var userContainerCount = $('.user-container').length;
// this count is used for the index for the next user container
var nextIndex = userContainerCount;
// build up some html. it's far simpler to just use regular html here, rather than razor.
// if you really want to use razor then look into partial views and fetching via ajax.
// you could use es6 backticks here to create a multi line string, but there seemed to
// be a little confusion in the comments, so this is just a plain concatenated string.
var html = '<div class="user-container">' +
'<input type="text" name="UsersToRegister[' + nextIndex + '].UserName" />' +
'<input type="email" name="UsersToRegister[' + nextIndex + '].Email" />' +
'<input type="password" name="UsersToRegister[' + nextIndex + '].Password" />' +
'</div>';
// append the html
$('.users-to-register').append(html);
});
});
得到。没有什么花哨的。
public ActionResult BulkRegister()
{
return View();
}
POST: 在模型中循环用户,然后向UserManager注册他们 你需要添加验证和任何你想做的事情来报告成功和失败。
[HttpPost]
public async Task<ActionResult> BulkRegister(RegisterLotsModel model)
{
// do whatever validation you want
if (!ModelState.IsValid)
return View(model);
// loop over your users and register them in the regular way
var successful = new List<string>();
var failed = new List<string>();
foreach (var toRegister in model.UsersToRegister)
{
var user = new ApplicationUser { UserName = toRegister.UserName, Email = toRegister.Email };
var result = await UserManager.CreateAsync(user, toRegister.Password);
if (result.Succeeded)
successful.Add(toRegister.UserName);
else
failed.Add(toRegister.UserName);
}
// do whatever you want to do with failures
if (failed.Any())
return RedirectToAction("FailedRegistration", new { failed });
// maybe register some more users?
return RedirectToAction("BulkRegister");
}
就这样了。如果你有很多用户要注册,你可能想只建立用户模型和 在一个事务中把它们直接插入数据库中。.
EmployeeListViewModel
;public class EmployeeListViewModel{
public List<EmployeeViewModel> UsersToRegister {get;set;}
}
@model EmployeeListViewModel
Model.UsersToRegister[0].Email
;// please edit with your parameters
@Html.BeginForm(){
// add validate forgery token html helper
<div class="form-group mx-1">
<label class="control-label" for="Email">Email</label>
<input name="Model.UsersToRegister[0].Email" class="form-control" data-val="true" data-val-email="The Email field is not a valid e-mail address." data-val-required="The Email field is required." id="Email" placeholder="Email" type="text" value="">
</div>
<div class="form-group mx-1">
<label class="control-label" for="User_Role">User Role</label>
<select name="Model.UsersToRegister[0].UserRoles" class="form-control" data-val="true" data-val-required="The UserRoles field is required." id="UserRoles" >
<option value="">Role</option>
<option value="Employee">Employee</option>
<option value="Manager">Manager</option>
</select>
</div>
<div class="form-group mx-1">
<label class="control-label" for="Password">Password</label>
<input name="Model.UsersToRegister[0].Password" class="form-control valid validate-equalTo-blur" data-val="true" data-val-length="The Password must be at least 6 characters long." data-val-length-max="100" data-val-length-min="6" data-val-required="The Password field is required." id="Password" placeholder="Password" type="password" value=""aria-describedby="Password-error" aria-invalid="false">
</div>
<div class="form-group mx-1">
<label class="control-label" for="ConfirmPassword">Confirm password</label>
<input class="form-control valid" name="Model.UsersToRegister[0].ConfirmPassword" data-val="true" data-val-equalto="The password and confirmation password do not match." data-val-equalto-other="*.Password" id="ConfirmPassword" placeholder="Confirm Password" type="password" value="" aria-describedby="ConfirmPassword-error" aria-invalid="false">
</div>
<button type="button" class="btn btn-sm btn-info add_button form-control col-md-1" style="margin-top: 37px"><i class="fas fa-plus"></i></button>
}
x
作为一个计数器。计数器将指示某个输入字段属于哪个索引(在对象列表中)。<script>
var x = 1; //initlal count
$(add_button).click(function (e) { //on add button click
e.preventDefault();
if (x < max_fields) { //max input box allowed
var html = "
<div class='field_wrapper'>
<div class='form-group row'>
<fieldset class='form-group mx-1'>
<label class='control-label' for='Email'>Email</label>
<input name='Model.UsersToRegister["+x+"].Email' class='form-control' data-val='true' data-val-email='The Email field is not a valid e-mail address.' data-val-required='The Email field is required.' id='Email' placeholder='Email' type='text' value=''>
</fieldset>
<fieldset class='form-group mx-1'>
<label class='control-label' for='User_Role'>User Role</label>
<select name='Model.UsersToRegister["+x+"].UserRoles' class='form-control' data-val='true' data-val-required='The UserRoles field is required.' id='UserRoles' ><option value=''>Role</option>
<option value='Employee'>Employee</option>
<option value='Manager'>Manager</option>
</select>
</fieldset>
<fieldset class='form-group mx-1'>
<label class='control-label' for='Password'>Password</label>
<input name='Model.UsersToRegister["+x+"].Password' class='form-control' data-val='true' data-val-length='The Password must be at least 6 characters long.' data-val-length-max='100' data-val-length-min='6' data-val-required='The Password field is required.' id='Password' placeholder='Password' type='text' value=''>
</fieldset>
<fieldset class='form-group mx-1'>
<label class='control-label' for='ConfirmPassword'>Confirm password</label>
<input name='Model.UsersToRegister["+x+"].ConfirmPassword' class='form-control' data-val='true' data-val-equalto='The password and confirmation password do not match.' data-val-equalto-other='*.Password' id='ConfirmPassword' placeholder='Confirm Password' type='text' value=''>
</fieldset>
<a href='#' class='btn btn-sm btn-danger remove_button form-control col-md-1' style='margin-top: 37px'><i class='fas fa-times center'></i></a>
</div>
</div>
";
x++; // increment value of x
$('.counter').text(x);
$(wrapper).append(html); //add html
}
});
</script>
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> RegisterEmployees(EmployeeListViewModel model)
{
if (ModelState.IsValid)
{
foreach(var u in model.UsersToRegister){
var user = new ApplicationUser { UserName = u.Email, Email = u.Email };
var result = await UserManager.CreateAsync(user, u.Password);
if(!result.Succeeded){
break; // depends on you if you want to stop creating users if one failed
// continue; // depends on you if you want to continue creating users if one failed
}
}
if (result.Succeeded)
{
return RedirectToAction("Index", "Home");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}