使用同一表格注册多个用户的.net身份。

问题描述 投票:0回答:1

在我的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);
    }
c# asp.net asp.net-mvc asp.net-identity
1个回答
2
投票

我很确定之前的答案是可行的,但你评论了以下内容 我的另一个答案 要求看这个问题,所以在这里你去。

我已经尽量保持它的简单性,所以你必须添加你自己的额外标记,样式,数据注释等。

模型

很自圆其说,我们只是为视图建立了一个模型,这个模型有一个用户模型列表。

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>
}

JQuery

我把它放在一个单独的文件中,但如果你喜欢的话,你可以直接把它弹到视图的底部。我们计算有多少 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");
}

就这样了。如果你有很多用户要注册,你可能想只建立用户模型和 在一个事务中把它们直接插入数据库中。.


3
投票
  1. 创建一个View模型,它将容纳UserViewModel类型的列表。我使用了 EmployeeListViewModel;
public class EmployeeListViewModel{
   public List<EmployeeViewModel> UsersToRegister {get;set;}
}
  1. 将视图顶部的模型声明改为。
@model EmployeeListViewModel
  1. 将此用于你的表单。我们需要静态地定义输入字段,因为我们需要在名称上使用0索引,如 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>

}
  1. 更新你的脚本来使用这个,我们在这里使用的是 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>
  1. 然后在你的控制器动作中使用这个,我们用新的类替换了参数。
[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);
}
© www.soinside.com 2019 - 2024. All rights reserved.