Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/svn/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在自定义属性中正确获取数据库值以验证IdentityRole?_C#_Validation_Razor_Mvvm - Fatal编程技术网

C# 如何在自定义属性中正确获取数据库值以验证IdentityRole?

C# 如何在自定义属性中正确获取数据库值以验证IdentityRole?,c#,validation,razor,mvvm,C#,Validation,Razor,Mvvm,我正在开发一个具有多个角色和用户的Web应用程序。我在.NETCore2中使用了个人用户帐户结构和web应用程序选项(不是mvc,所以我将MVVM与Razor页面一起使用) 目前,每当我在数据表/网格视图中为显示的用户点击“编辑”按钮时,它都会在同一视图中的表单中使用旁边表单中的AJAX调用,使用数据库中的所有对应值填充该表单 它还会填充角色的下拉列表,它将是: 填充下拉列表 这解决了我的问题,但是硬编码的,感觉很脏。我想将其与数据库值进行比较。一个自定义属性应该可以完成这个任务,但是其他帖子上

我正在开发一个具有多个角色和用户的Web应用程序。我在.NETCore2中使用了个人用户帐户结构和web应用程序选项(不是mvc,所以我将MVVM与Razor页面一起使用)

目前,每当我在数据表/网格视图中为显示的用户点击“编辑”按钮时,它都会在同一视图中的表单中使用旁边表单中的AJAX调用,使用数据库中的所有对应值填充该表单

它还会填充角色的下拉列表,它将是:

填充下拉列表 这解决了我的问题,但是硬编码的,感觉很脏。我想将其与数据库值进行比较。一个自定义属性应该可以完成这个任务,但是其他帖子上给出的所有示例都不能满足我在本例中的需要。它们都显示了MVC模式的示例,但没有显示MVVM模式。我知道这可能是一种代码结构,但我对mvc不太熟悉,因此无法在mvvm上下文中转换这些示例

企图 到目前为止,我所尝试的:

我的视图模型 棋盘格属性 同样,我使用的是MVVM模式,而不是MVC模式

编辑1 编辑2
[ValidateAntiForgeryToken]
公共异步任务OnPostEditAsync(用户模型模型,字符串id)
{
var user=await\u userManager.FindByIdAsync(id);
任务角色用户=_userManager.GetRolesAsync(用户);
IdentityRole currentRole=await_roleManager.FindBynameSync(RoleUser.Result.First());
字符串selectedRole=model.RoleId;
if(user==null | |!ModelState.IsValid)
{
返回页();
}
...
if(selectedRole!=currentRole.Name)
{
wait_userManager.RemoveFromRoleAsync(用户,currentRole.Name);
wait_userManager.AddToRoleAsync(用户,selectedRole);
}
wait_userManager.UpdateAsync(用户);
返回到Topage(…);
}

IoC是什么意思?就我对.net core webapplication(mvvm)和razor页面和identitystores的理解而言,我使用的是依赖注入是的!
<label>Role</label>
<select class="form-control" id="roles" name="RoleId" asp-for="Input.RoleId">
    <option value="Admin">User</option>
    <option value="Manager">Manager</option>
    <option value="User">User</option>
</select>
public class UsersModel : PageModel
{
    ... 

    private readonly ApplicationDbContext _dbContext;
    public List<IdentityRole> Roles { get; set; }


    public UsersModel(ApplicationDbContext dbContext)
    {
        _dbContext = dbContext;
    } 

    public async Task<IactionResult> OnGet()
    {
       Roles = _dbContext.Roles.ToList();
    }

    public class UserModel
    { 
        ...

        [Required]
        [Display(Name = "Role")]
        public string RoleId { get; set; }
        ...
    }

}
[ValidateAntiForgeryToken]
public async Task<IActionResult> OnPostEditAsync(UserModel model, string id)
{
    ...

   var user = await _userManager.FindByIdAsync(id);
   Task<IList<string>> rolesUser = _userManager.GetRolesAsync(user);
   IdentityRole currentRole = await _roleManager.FindByNameAsync(rolesUser.Result.First());
   string selectedRole = model.RoleId;


   if (selectedRole != currentRole.Name)
   {     
       await _userManager.RemoveFromRoleAsync(user, currentRole.Name);
       await _userManager.AddToRoleAsync(user, selectedRole);
   }

   await _userManager.UpdateAsync(user);
   return RedirectToPage(...);

   ...
}
<option value="Not existing">Example</option>
[RegularExpresson("^(Admin|Manager|User)*$)]
 public class UserModel
 {  
      ... 

      [Required]
      [CheckRole(typeof(IdentityRole))]
      [Display(Name = "Role")]
      public string RoleId { get; set; }

      ...
 }
public class CheckRoleAttribute : ValidationAttribute
{
    public Type ObjectType { get; private set; }
    public CheckRoleAttribute(Type type)
    {
        ObjectType = type;
    }

    protected override ValidationResult IsValid(
        object value, ValidationContext validationContext)
    {
        // I understand passed value is the given option from the option        to validate
        // I'd like to obtain my available roles here that are available from the database, so I can validate it and return the correct error message.
    }

 }
 // My Attribute
 protected override ValidationResult IsValid(
        object value, ValidationContext validationContext)
    {
        var context = (ApplicationDbContext)validationContext.GetService(typeof(ApplicationDbContext));

        if (!context.Roles.Any(p => p.Name == value)) // changed 'p => p' to 'p => p.Name'
        {
            return ValidationResult.Success;
        }           

        return new ValidationResult($"The selected {value} doesn't exist.");


    }

    //My model
    [Required]
    [ValidateRole]
    [Display(Name = "Role")]
    public string RoleId { get; set; }
}
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> OnPostEditAsync(UserModel model, string id)
    {
        var user = await _userManager.FindByIdAsync(id);
        Task<IList<string>> rolesUser = _userManager.GetRolesAsync(user);
        IdentityRole currentRole = await _roleManager.FindByNameAsync(rolesUser.Result.First());
        string selectedRole = model.RoleId;



        if (user == null || !ModelState.IsValid)
        {
            return Page();
        }

        ...

         if (selectedRole != currentRole.Name)
        {

            await _userManager.RemoveFromRoleAsync(user, currentRole.Name);
            await _userManager.AddToRoleAsync(user, selectedRole);

        }

        await _userManager.UpdateAsync(user);

        return RedirectToPage(...);

    }