MVC5 애플리케이션:ID 사용자 생성 결과가 잘못된 모델 상태가 됩니까?
-
21-12-2019 - |
문제
ASP.Net ID를 활용하기 위해 개발 중인 응용 프로그램을 MVC4/EF5에서 MVC5/EF6으로 업그레이드하고 있습니다.사용자를 생성하려고 하면 코드에서 모델을 유효하지 않은 것으로 표시하고 사용자를 생성하지 않습니다.My View는 이메일을 입력할 수 있는 상자를 표시한 다음, 로그인한 관리자가 MemberOrganization 또는 Sponsor를 선택하여 일부 드롭다운을 통해 새 사용자 2를 할당할 수 있는 스위치를 표시합니다.
내 UserController의 Create() 메서드는 다음과 같습니다.
// GET: Admin/UserManagement/Create
public ActionResult Create()
{
ViewBag.headerTitle = "Create User";
ViewData["Organization"] = new SelectList(db.MemberOrganizations, "Id", "Name");
ViewData["Sponsor"] = new SelectList(db.SponsorOrganizations, "Id", "Name");
ViewBag.SwitchState = true;
ApplicationUser newUser = new ApplicationUser();
newUser.RegisteredDate = DateTime.Now;
newUser.LastVisitDate = DateTime.Now;
newUser.ProfilePictureSrc = null;
return View(newUser);
}
// POST: Admin/UserManagement/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([Bind(Include = "Property1, Property2, etc.")] ApplicationUser applicationUser)
{
if (ModelState.IsValid)
{
ViewBag.headerTitle = "Create User";
PasswordHasher ph = new PasswordHasher();
var password = ph.HashPassword("aR@nD0MP@s$w0r9");
var user = new ApplicationUser() { UserName = applicationUser.UserName, Email = applicationUser.Email, PasswordHash = password };
IdentityResult result = await UserManager.CreateAsync(user, user.PasswordHash);
if (result.Succeeded)
{
await db.SaveChangesAsync();
return RedirectToAction("Index", "UserManagement");
}
else
{
ModelState.AddModelError("", "Failed to Create User.");
}
}
ModelState.AddModelError("", "Failed to Create User.");
var errors = ModelState.Where(x => x.Value.Errors.Count > 0).Select(x => new { x.Key, x.Value.Errors }).ToArray();
var errors2 = ModelState.Values.SelectMany(v => v.Errors);
ViewData["Organization"] = new SelectList(db.MemberOrganizations, "Id", "Name", applicationUser.MemberOrgId);
ViewData["Sponsor"] = new SelectList(db.SponsorOrganizations, "Id", "Name", applicationUser.SponsorOrgId);
if (applicationUser.MemberOrgId != null)
{
ViewBag.SwitchState = true;
}
else
{
ViewBag.SwitchState = false;
}
ViewBag.OrganizationId = new SelectList(db.MemberOrganizations, "Id", "State", applicationUser.MemberOrgId);
// If we got this far, something failed, redisplay form
return View(applicationUser);
}
문제를 디버깅하려는 시도에서 다음을 추가했습니다. errors/errors2
제안된 변수 이것 우편.플래그가 지정되면 모델 상태 속성으로 내려가면 다음과 같은 메시지가 표시됩니다.
이 문제에 대해 생각이 있는 사람이 있나요?이전 코드는 제대로 작동했지만 여전히 ASP.Net Identity에 익숙해지고 있습니다.
편집하다:Rikard가 제안한 대로 SponsorOrgID와 MemberOrgID가 모두 필요하지 않은(1개만) 모델을 설정했습니다.이제 내 코드는 다음 세그먼트까지 처리됩니다.
var user = new ApplicationUser() { Name = applicationUser.Name, Email = applicationUser.Email, PasswordHash = password };
IdentityResult result = await UserManager.CreateAsync(user, user.PasswordHash);
if (result.Succeeded) // ERROR
{
await db.SaveChangesAsync();
return RedirectToAction("Index", "UserManagement");
}
값을 확인해 보면 result
드릴다운하여 Errors->[string[]]->[0]
오류 메시지는 다음과 같습니다 Name cannot be null or empty
.누구든지 이것에 대해 생각이 있습니까?새 사용자를 지정하기 위해 내 보기에 필드를 추가했습니다. Name
그리고 그것을 위의 내용에 포함시켰습니다. new ApplicationUser()
코드 라인.내가 어디에서 뭔가를 놓치고 있는지 완전히 확신할 수 없습니다.
편집2:Create() 뷰 [관련]:
@model PROJECTS.Models.ApplicationUser
@{
ViewBag.Title = "Create";
Layout = "~/Areas/Admin/Views/Shared/_LayoutAdmin.cshtml";
string cancelEditUrl = "/Admin/UserManagement/";
}
@using (Html.BeginForm("Create", "UserManagement", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.RegisteredDate)
<div class="container">
<div class="row">
<div class="editor-label">
@Html.LabelFor(model => model.Name)
</div>
<div class="editor-field" style="margin-bottom: 15px">
@Html.TextBoxFor(model => model.Name, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="row">
<div class="editor-label">
@Html.LabelFor(model => model.Email)
</div>
<div class="editor-field" style="margin-bottom: 15px">
@Html.TextBoxFor(model => model.Email, new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Email)
</div>
</div>
....
해결책
마지막 사진에서 볼 수 있듯이 속성에 오류가 있습니다. 스폰서 조직 ID 값은 string.Empty("")입니다.아마도 스폰서 조직 ID ~에 애플리케이션사용자 가지고있다 [필수] 기인하다.
편집하다
데이터베이스에 사용자를 추가하려고 할 때 발생하는 문제와 관련하여(UserManager.Create(user,password);를 호출할 때 발생했습니다.
IdentityResult result = await UserManager.CreateAsync(user, user.PasswordHash);
if (result.Succeeded)
{
await db.SaveChangesAsync();
return RedirectToAction("Index", "UserManagement");
}
else
{
var errors = string.Join(",", result.Errors);
ModelState.AddModelError("", errors);
}
그런 다음 "오류" 값을 디버깅하거나 ModelState에서 오류 메시지를 읽을 수 있습니다.
귀하의 편집에 관하여
이 부분에 이름을 추가하십시오:
var user = new ApplicationUser() { UserName = applicationUser.UserName, Email = applicationUser.Email, PasswordHash = password, Name = applicationUser.Name };
편집 2문제는 사용자 이름 없이는 사용자를 생성할 수 없다는 것입니다.하지만 사용자 이름에 사용자의 이메일을 추가할 수 있습니다.그런 다음 사용자가 지정한 사용자 이름으로 변경합니다.유효성 검사를 통과하려면 이 부분을 추가해야 합니다.
UserManager.UserValidator = new UserValidator<User>(UserManager) { RequireUniqueEmail = true };
다른 팁
답변이 늦었다는 것을 알고 있지만 이 문제를 해결하기 전에 이에 대한 4개의 스레드를 읽었습니다.완전히 명확하지는 않으며 사용자 정의 속성과 상속 충돌이 있는 것으로 보입니다.내 문제의 근본 원인은 FirstName + " " + LastName으로 정의하고 싶은 사용자 정의 속성(...또는 그렇게 생각함)인 UserName 속성을 생성한 것입니다.
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
// public new string UserName { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
...remainder removed for clarity.
사용자 지정 속성을 제거한 IdentityModels.cs에서 이 줄을 주석 처리하자마자, 펑! 문제:해결되었습니다.나는 IUser[TKey]까지 상속 정의를 자세히 조사한 결과 내(우리) 문제의 근본 원인이라고 생각되는 것을 발견했습니다.
namespace Microsoft.AspNet.Identity
{
// Summary:
// Minimal interface for a user with id and username
//
// Type parameters:
// TKey:
public interface IUser<out TKey>
{
// Summary:
// Unique key for the user
TKey Id { get; }
//
// Summary:
// Unique username
string UserName { get; set; }
}
}
ApplicationUser 클래스에 사용자 정의 속성을 추가할 수 있다는 것은 알았지만 이미 사용 중인 특정 속성 이름이 있다는 것은 몰랐습니다. 즉, 이 클래스에 정의되지 않았습니다.처음에는 UserName 필드를 공개 문자열로 추가한 후 다음을 받았습니다.
[...] warning CS0114: 'MyApp.Models.ApplicationUser.UserName' hides inherited member 'Microsoft.AspNet.Identity.EntityFramework.IdentityUser<string,Microsoft.AspNet.Identity.EntityFramework.IdentityUserLogin,Microsoft.AspNet.Identity.EntityFramework.IdentityUserRole,Microsoft.AspNet.Identity.EntityFramework.IdentityUserClaim>.UserName'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
저는 지침을 잘 따르기 때문에 'new' 키워드를 추가했습니다(위 줄을 주석 처리해야 했던 것을 기억하시나요...?).컴파일 시간 CS0114 경고를 해결했지만 IUser의 UserName을 방해했습니다.
OP(그리고 수많은 다른 사람들)도 그가 다음과 같이 썼을 때 같은 일을 했다고 믿습니다:
var user = new ApplicationUser() { UserName = applicationUser.UserName, Email = applicationUser.Email, PasswordHash = password };
applicationuser 클래스에 사용자 이름 및 이메일 속성이 있는 경우 이러한 속성은 실제 속성을 숨기고 있으므로 애플리케이션 클래스에서 해당 속성을 제거하면 문제가 해결됩니다.