Можно ли как нибудь отменить действие валидации Remote на определённой странице представления?
Подробней:
Есть валидация на поле Name
[Required]
[StringLength(15, MinimumLength = 3)]
[Remote(action: "CheckName", controller: "Validation", ErrorMessage = "Эй! Уф, нэ пеши сюда ето имя:-[ Оно уже есь же, эсь жи!!")]
[Display(Name = "Название компании")]
public string Name { get; set; }
так же есть страница Create для чего собственно и нужна валидация!
И ещё я сделал страницу Edit!
И при редактировании компании, даже если её не меняешь, приложение отказывается сохранять изменения, пока не изменишь имя, так как оно уже существует. Можно ли как нибудь отменить действие валидации для этой страницы?
Вот что получилось Но в companyM._mode
прилетает null, так что сравнивать нечего.
вот, метод валидации
[AcceptVerbs("Get", "Post")]
public IActionResult CheckName(string name, Company companyM)
{
List<Company> companies = _context.Companies.ToList();
// var companies = _context.Companies.Include(c => c._Company);
if (companyM._mode != "Edit")
{
foreach (var company in companies)
{
if (company.Name == name)
{
return Json(false);
}
}
}
return Json(true);
}
Вот модель
public class Company
{
public int Id { get; set; }
[Required]
[StringLength(15, MinimumLength = 3)]
[Remote(action: "CheckName", controller: "Validation", ErrorMessage = "Эй! Уф, нэ пеши сюда ето имя:-[ Оно уже есь же, эсь жи!!")]
[Display(Name = "Название компании")]
public string Name { get; set; }
[EmailAddress]
[Display(Name = "Почта компании")]
public string _emailCompany { get; set; }
//[Range(typeof(DateTime), "01/01/1975 01:01", "01/01/2019 01:01")]
[DataType(DataType.DateTime)]
[Display(Name = "Дата создания компании")]
public DateTime _dataCreateCompany { get; set; }
public int? _CompanyId { get; set; }
public Company _Company { get; set; }
public string _mode { get; set; }
public IEnumerable<Company> CompaniesEnumerable { get; set; }
public IEnumerable<Phone> Phones { get; set; }
}
Вот представление Edit
@model Company
@{
ViewData["Title"] = "Edit";
}
<h2>Edit</h2>
<h4>Company</h4>
<hr/>
@using (Html.BeginForm("Edit", "Company", FormMethod.Post))
{
@Html.HiddenFor(x => x._mode, "Edit")
<div class="row">
<div class="col-md-4">
<form asp-action="Edit">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Id"/>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control"/>
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="_emailCompany" class="control-label"></label>
<input asp-for="_emailCompany" class="form-control"/>
<span asp-validation-for="_emailCompany" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="_dataCreateCompany" class="control-label"></label>
<input asp-for="_dataCreateCompany" class="form-control"/>
<span asp-validation-for="_dataCreateCompany" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="_CompanyId" class="control-label"></label>
<select asp-for="_CompanyId" class="form-control" asp-items="ViewBag._CompanyId"></select>
<span asp-validation-for="_CompanyId" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" type="hidden" name="Mode" value="Save" class="btn btn-default"/>
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
}
@section Scripts {
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}
Вот представление Create
@model MyFirstMVC.Models.Company
@{
ViewData["Title"] = "Create";
}
<h2>Create</h2>
<h4>Category</h4>
<hr/>
@using (Html.BeginForm("Create", "Company", FormMethod.Post))
{
@Html.HiddenFor(x => x._mode, "Create")
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control"/>
<span asp-validation-for="Name" class="text-danger"></span>
</div>
@* Email *@
<div class="form-group">
<label asp-for="_emailCompany" class="control-label"></label>
<input asp-for="_emailCompany" class="form-control"/>
<span asp-validation-for="_emailCompany" class="text-danger"></span>
</div>
@* Data *@
<div class="form-group">
<label asp-for="_dataCreateCompany" class="control-label"></label>
<input asp-for="_dataCreateCompany" class="form-control"/>
<span asp-validation-for="_dataCreateCompany" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" type="hidden" name="Mode" value="Create" class="btn btn-default"/>
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
}
@section Scripts {
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}
Вообще-то самый правильный вариант — сделать две разных модели (одну для Create, другую - для Edit) и оставить атрибут [Remote] только для Create.
Но если же очень хочется оставить одну модель — то можете поправить свой action CheckName, выполняющий проверку, чтобы он для метода Edit возвращал всегда true (А для Create - отрабатывайте логику как есть).
Как в этом случае узнать, какой метод работает? Просто добавьте в модель ещё одно свойство Mode:
public class SomeModel
{
...
[Required]
[StringLength(15, MinimumLength = 3)]
[Remote(action: "CheckName", controller: "Validation", ErrorMessage = "Эй! Уф, нэ пеши сюда ето имя:-[ Оно уже есь же, эсь жи!!")]
[Display(Name = "Название компании")]
public string Name { get; set; }
...
public string Model { get; set; }
...
}
И в представлении Create заполняйте его значением Create:
@model SomeModel
<h1>Create</h1>
@using (Html.BeginForm("Create", "Enity", FormMethod.Post))
{
@Html.HiddenFor(x => x.Mode, "Create")
...
}
А в представлении Edit — значением Edit:
@model SomeModel
<h1>Edit</h1>
@using (Html.BeginForm("Edit", "Enity", FormMethod.Post))
{
@Html.HiddenFor(x => x.Mode, "Edit")
...
}
Разумеется, поле должно быть невидимым (hidden) input'ом, вариант html если вы форму генерируете вручную:
<input type="hidden" value="Create" name="Mode">
Ну и в вашем action на валидацию пишете:
if(model.Mode == "Create} { ... }
Ну или полностью:
[AcceptVerbs("Get", "Post")]
public IActionResult CheckName(string name, Company companyM, string mode)
{
List<Company> companies = _context.Companies.ToList();
// var companies = _context.Companies.Include(c => c._Company);
if (mode == "Edit")
{
// Не проверяем для Edit
return Json(true);
}
// Проверяем для Create
// NB: Это выражение можно заменить на LINQ
foreach (var company in companies)
{
if (company.Name == name)
{
return Json(false);
}
}
return Json(true);
}
Я на вашем месте предпочёл бы первый вариант. Хорошее приложение - это приложение, которое легко поддерживать. Во втором варианте у вас усложняется логика на стороне контроллера, а в первом варианте не усложняется. В первом варианте у вас один класс несёт одну отвественность, а во втором случае две.
PS. Я часто сталкиваюсь с людьми, которые боятся продублировать лишнюю строчку кода и не понимают, что в данном случае это дублирование кода является хорошим дублированием, которое упрощает жизнь.
Давайте вспомним, почему вообще настоятельно рекомендуют избегать дублирования кода и считают плохой практикой? Вот допустим, код который делает "создание сущности" и код, который делает "редактирование сущности".
Допустим, они похожи, но чуть-чуть различаются. Волевым усилием, потратив полчаса времени мы придумываем, как написать этот максимально одинаковым способом и восторгаясь закрываем IDE. Здорово? Нет!
Дело в том, что когда у нас возникнет необходимость поправить код для редактирования - мы потратим пять минут на переделку и ещё три часа будем перепроверять, а не поломается ли при этом создание. (Даже если вы пишете тесты на каждый чих)
В данном случае нет необходимости придумывать, как объединять код. У него просто разная ответственность. Ввспоминаем Single Responsibility Principle: у каждого класса должна быть только одна причина для изменения. Если класс отвечает и за создание и за редактирование - этот класс нарушает SPR.
Любое дублирование кода в данном случае является случайным совпадением, отражающим логику того, что ваши модели (ViewModel, Dto) отражают одну и ту же единственную сущность (Entity, Model).
Приведу примеры.
У меня есть Entity "Пользователь" (User), у которой есть поле "Пароль" (Password). И у меня есть модель создания пользователя (с полями UserName, Email, Password, ConfirmationPassword), смены логина (c полем UserName) и модель для сброса пароля (с полями UserId, OldPassword, NewPassword, ConfirmationNewPassword). Наборы полей примерно одинаковые во всех случаях (это всегда подмножества полей сущности), иногда дублируются (Password + Confirmation), но ведь вам из-за этой похожести не приходит в голову "А давайте мы создадим ОДНУ МОДЕЛЬ НА ВСЁ!!", верно? Это очень разные действия.
И у меня в реальных приложениях много подобных примеров. Например, при создании сущности я могу спросить только 2-3 поля, хотя в модели на редактирование полей будет два десятка. Зачем? Чтобы упростить процесс создания. Например, при редактировании заказа есть поле "статус", но при создании оно не нужно - все заказы создаются в статусе New. Зачем тогда выводить его на экран, чтобы оно только место занимало и пугало пользователя "смотри, какая длинная форма, у нас не абы какое приложение - а настоящий энтерпрайз!"
Также помимо моделей Create и Edit (действительно, часто во многом совпадающих) мне приходится делать модель для Clone - и это тоже отдельная модель, которая немного похожа на Create, а немного - на Edit.
Так что не следуйте слепо рекомендациям, а понимайте для чего они сделаны и применимо ли это в конкретном случае.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Имеется данный кусочек интерфейса, нужно его отрисовать, но не знаю как, подскажитеБыл бы благодарен если ещё и с объяснением, сфера новая,...
Нашел скрипт на просторах сети, конвертер cookies файлов формата Netscape в формат JSONНо почему-то у меня вместо JSON Cookies в файл cookies
у меня возникла проблема и она заключается в том, что при передачи изображении на базу данных, где находится ее поле пишет слово Array - массив...