Как выполнить проверку на стороне сервера без изменения ModelState при публикации AJAX в Controller в ASP.Net MVC
У меня есть контроллер Edit
который делает вставку и обновление в то же действие. Там я делаю проверку против Active Directory
, Приложение должно показывать ошибку проверки, если вставка не удалась из-за несоответствия имени пользователя, введенного пользователем и проверенного agaisnt. Active Directory
, Поскольку в действии происходит несколько записей, вставка должна быть остановлена для этого конкретного пользователя, даже если более поздние имена пользователей допустимы.
Проблема: Мой код в настоящее время использует проверку ModelState, но он не работает для передачи сообщения проверки в VIEW, потому что модель фактически не изменяла свое состояние в этом случае.
Вопрос: Как можно выполнить проверку на стороне сервера перед вставкой БД для определенного свойства модели (в данном случае имя пользователя)?
Предположение: Должен ли метод проверки имени пользователя возвращать само имя пользователя, которое затем может быть передано в представление для отображения сообщения об ошибке?
Ограничения: не могу использовать Annotation
на модели IsRequired
потому что это не обязательное поле. USer должен иметь возможность редактировать текущий список пользователей и сохранять его, даже если текстовое поле username пусто. Только когда имя пользователя введено в текстовое поле и вставка происходит, тогда требуется проверка. Не могу выполнить проверку на стороне клиента Active Directory
так как это было бы тяжело. Это не полевая проверка, а проверка того, что неверные данные не попадают в БД.
Модель:
public class User
{
[Key]
public string username { get; set; }
[Key]
public string role { get; set; }
}
Посмотреть:
@model List<Project.ViewModels.UserViewModel>
@using (@Html.BeginForm())
{
<table class="table">
<tr>
<th>User</th>
@for (int i = 0; i < Model[0].Roles.Count; i++)
{
<th>
@Model[0].Roles[i].RoleName
</th>
}
</tr>
@for (int i = 0; i < Model.Count; i++)
{
<tr>
<td>
@if (Model[i].UserName == null)
{
@Html.EditorFor(m=> m[i].UserName)
@Html.ValidationMessageFor(m=> m[i].UserName)
if (!ViewData.ModelState.IsValid)
{
<span class="field-validation-error">
@ViewData.ModelState["UserName"].Errors[0].ErrorMessage
</span>
}
}
else
{
@Html.HiddenFor(m => m[i].UserName)
@Model[i].UserName
}
</td>
@for (int j = 0; j < Model[i].Roles.Count; j++)
{
<td>
@Html.HiddenFor(m => m[i].Roles[j].RoleName)
@Html.CheckBoxFor(m => m[i].Roles[j].IsSelected)
</td>
}
</tr>
}
</table>
<div class="form-actions">
<button id="SubmitUserRoles" type="submit" class="btn btn-success submit" value="Save">Save</button>
</div>
}
<script>
$("#SubmitUserRoles").click(function () {
$.ajax({
url: '@Url.Action("Edit", "Users")',
type: 'POST',
cache: false,
data: JSON.stringify($('form').serialize()),
success: function (data) {
window.location.href = data
}, error: function (xhr, ajaxOptions, error) {
console.log(xhr.status);
console.log("Error: " + xhr.responseText);
}
});
});
});
контроллер:
[HttpPost]
public ActionResult Edit(List<UserViewModel> model)
{
var level = model[0].Level;
var location = model[0].Location;
for (int i = 0; i < model.Count; i++)
{
if (model[i].UserName != null)
{
var uName = model[i].UserName;
for (int j = 0; j < model[i].Roles.Count; j++)
{
var uRole = model[i].Roles[j].RoleName;
var uRoleSelected = model[i].Roles[j].IsSelected;
var userWithSpecificRole = db.Users.FirstOrDefault(m => m.username == uName && m.role == uRole);
if (uRoleSelected && userWithSpecificRole == null)
{
if (DoesUserExist(uName))
{
if (ModelState.IsValid)
{
db.Users.Add(new User
{
username = uName,
role = uRole,
});
db.SaveChanges();
}
}
else
ModelState.AddModelError("UserName", "Username does not exist!");
}
}
}
}
return Json(Url.Action("Index", "Users", new {level,location}));
}
Метод, который проверяет имя пользователя по Active Directory
как следует:
private bool DoesUserExist(string username)
{
PrincipalContext domain = new PrincipalContext(ContextType.Domain, "CompanyDomain", "DC=CompanyDomain,dc=com");
UserPrincipal foundUser = UserPrincipal.FindByIdentity(domain, IdentityType.SamAccountName, username);
return foundUser != null;
}