Как проверить один элемент в списке - PullRequest
4 голосов
/ 15 декабря 2011

У меня есть модель, которая имеет такую ​​форму:

public class GlobalSettingsViewModel
{
   public List<SettingViewModel> Settings{ get;set;}
}

public class SettingViewModel 
{
   public string Name{ get;set;}
   [Range(0,100)]
   public decimal SettingValue{ get;set;}
}

Мой просмотр вызывает Html.RenderPartial("SettingView") для каждого SettingViewModel.

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SettingViewModel>" %>
<% using (Html.BeginForm("Save", "GlobalSettings", FormMethod.Post))
   { %>
<table>
    <tr>
        <td width="150px">
            <%= Html.DisplayFor(m=>m.Name) %>
        </td>
        <td>
            <%= Html.TextBoxFor(m=>m.SettingValue) %>
        </td>
        <td>
            <input type="submit" value="Save" class="uiButton" />
            <%=Html.ValidationMessageFor(m=>m.SettingValue) %>
        </td>
    </tr>
</table>
   <%} %>

Каждый SettingView отображает форму, которая отправляет обратно в действие Сохранить.

SettingViewModel правильно повторно гидратируется из формы, и проверка корректно определяет, когда генерируется значение out или range.

Я вернул исходное Index представление с полным GlobalSettingsViewModel, которое требуется.

Однако, когда страница отображает каждые Валидатор для SettingValue показывает сообщение об ошибке, а не просто текстовое поле с неправильным значением?

Как правильно выполнить проверку на стороне сервера для PartialView, когда это страница коллекции элементов?


UPDATE

Так вот что у меня есть ... это кажется немного странным, но, кажется, работает ..

Я могу сохранить один параметр за раз и показать ошибки проверки при их возникновении. Но странный способ сохранения с использованием частичной модели кажется немного странным.

index.aspx

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/MVC.Master" Inherits="System.Web.Mvc.ViewPage<GlobalSettingsViewModel>" %>
<fieldset style="margin: 5px; width: 350px;">
        <legend>Global System Settings</legend>
        <div>
            <%= Html.EditorFor(m => Model.Settings)%>
        </div>
</fieldset>

SettingViewModel.ascx

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SettingViewModel>" %>
<% using (Html.BeginForm("Save", "GlobalSettings", FormMethod.Post))
   { %>
<table>
    <tr>
        <td width="150px">
            <%= Model.Name %>
        </td>
        <td>
            <%= Html.TextBoxFor(m => m.SettingValue) %>
        </td>
        <td>
            <input type="submit" value="Save" class="uiButton" />
        </td>
    </tr>
    <tr>
        <td colspan="3">
            <%=Html.ValidationMessageFor(m=>m.SettingValue) %>
        </td>
    </tr>
</table>
<%= Html.HiddenFor(m => m.SettingName)%>
<%= Html.HiddenFor(m => m.Name)%>

<%} %>

GlobalSettingsController.cs

public ActionResult Index()
        {
            var settings = GetSettings();

            if (TempData["Message"] != null)
            {
                settings.Message = TempData["Message"].ToString();
                settings.HasMessage = true;
            }

            return View(settings);
        }

        [AuthorizationFilter(true, null)]
        [HttpPost]
        public ActionResult Save(GlobalSettingsViewModel model)
        {
            if (ModelState.IsValid)
            {
                GlobalSettings.SetGlobalSetting(model.Settings[0].SettingName, model.Settings[0].SettingValue);
                TempData["Message"] = "Saved " + model.Settings[0].Name;
                return RedirectToAction("Index");
            }

            var settings = GetSettings();

            return View("Index", settings);            
    }

Ответы [ 2 ]

2 голосов
/ 15 декабря 2011

Одна из возможностей - использовать AJAX, чтобы вам не приходилось обновлять всю страницу.Таким образом, ваше действие Сохранить вернет частичное прохождение, передавая только текущий параметр:

[HttpPost]
public ActionResult Save(SettingViewModel model)
{
    // TODO: do some processing
    return PartialView("SettingView", model);
}

, затем обернет формы в некоторый контейнер div, чтобы мы могли легче узнать, какой раздел обновлять при успешном вызове AJAX:1004 *

<% foreach (var item in Model.Settings) { %>
    <div class="setting">
        <%= Html.Partial("SettingView", item) %>
    </div>
<% } %>

и, наконец, AJAXify этих форм в некотором отдельном файле JavaScript:

$(function () {
    $('.setting').delegate('form', 'submit', function() {
        $.ajax({
            url: this.action,
            type: this.method,
            data: $(this).serialize(),
            context: this,
            success: function (result) {
                $(this).closest('.setting').html(result);
            }
        });
        return false;
    });
});
1 голос
/ 15 декабря 2011

Ваша проблема в том, что RenderPartial генерирует одинаковые идентификаторы для каждой SettingsViewModel. Если вы посмотрите на ваш отрендеренный код, то увидите на странице повторяющиеся идентификаторы, и это недопустимый HTML.

Возможно, вам лучше использовать EditorTemplate для SettingsViewModel, и он будет иметь логику, необходимую для создания уникальных идентификаторов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...