Принудительная проверка на стороне сервера при сбое ненавязчивой проверки на стороне клиента с ASP.NET MVC3 - PullRequest
1 голос
/ 19 января 2012

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

Мы используем POCO в Entity Framework 4 для сохранения данных обратно в базу данных. Мы используем аннотации данных, чтобы попытаться уменьшить количество повторяющихся проверок, которые мы должны сделать (что было проблемой с нашим старым классическим решением ASP, где у нас была ЖЕ проверка на трех разных уровнях приложения).

Мы хотим включить в нашу модель бизнес-правила, в том числе убедиться, что поля, проверенные по другим таблицам, действительны (в нашей модели не используются раскрывающиеся списки, поэтому пользователи могут вводить что угодно). Например, мы храним информацию о помещении в здании. В комнате есть поле под названием «Тип комнаты». Допустимые типы номеров определены в другой таблице.

Мы также хотим получить немедленную проверку на стороне клиента. Например, у нас есть числовые поля, которые должны быть в диапазоне от 0 до 32767. Если пользователь вводит -1, мы используем проверку на стороне клиента, чтобы немедленно ответить пользователю, чтобы сообщить ему, что -1 недействительно. Мы делаем это путем включения проверки на стороне клиента и использования аннотаций данных.

Web Config:

<appSettings>
    <add key="webpages:Version" value="1.0.0.0" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>

Модель:

public class Room : IValidatableObject
{
    // I'm only showing the relevant properties...

    // this is a field that's validated based on another table in the database.
    // (In the model we are using autocomplete instead of a dropdown -- it's a long 
    // story --, so potentially invalid data can be passed through the form...
    [DisplayName("Room Type"), MaxLength(5)]        
    public String RoomType { get; set; }

    // A number field, with a range.
    [Range(0, 32767), DisplayName("Maximum Seats")]
    public Int16? MaxStudents { get; set; }

    // do server side validation for this entity.
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        var validateErrors = new List<ValidationResult>();

        // make sure room type is a valid type
        if(!String.IsNullOrEmpty(RoomType)) {
            // hit database, which is a little weird since we need to create a context,
            // and I know that might make some people's brains explode
        }

        // return all of the errors
        return validateErrors;
    }
}

Контроллер:

    // I didn't include all the actions, just edit

    public ActionResult Edit(Int32 Building, String RoomID)
    {
        // return a single room and show the detail information in edit mode.
        Room room = findRoom(Building, RoomID);
        return View(room);
    }

    [HttpPost]
    public ActionResult Edit(Int32 Building, String RoomID, FormCollection collection)
    {
        // get the current room from the database.
        Room room = findRoom(Building, RoomID);

        // save the room being edited, but don't touch the key fields.
        if (TryUpdateModel(room, null, null, new string[] {"Building", "RoomID"}))
        {
            // if the entity changed, audit and save
            if (db.Entry(room).State == EntityState.Modified)
            {
                db.setLastUpdate(room); // this is a function in our context for auditing
                db.SaveChanges();
            }                
        }
        return View(room);
    }

Вид: (не надо показывать JavaScript, использованный для создания автозаполнения ...)

@using (Html.BeginForm()) {
    @Html.ValidationSummary(false, "The following errors occured when attempting to save this Room:")
    <fieldset>
        <legend>Room</legend>
        <div class="field-block">
            <div class="editor-label">
                @Html.LabelFor(model => model.Building)
            </div>
            <div class="editor-field">
                @Html.DisplayFor(model => model.Building)
            </div>
        </div>
        <div class="field-block">
            <div class="editor-label">
                @Html.LabelFor(model => model.RoomID)
            </div>
            <div class="editor-field">
                @Html.DisplayFor(model => model.RoomID)
            </div>
        </div>
        <div class="field-block">
            <div class="editor-label">
                @Html.LabelFor(model => model.RoomType)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.RoomType)
            </div>
        </div>

        <div class="field-block">
            <div class="editor-label">
                @Html.LabelFor(model => model.MaxStudents)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.MaxStudents)
                @Html.ValidationMessageFor(model => model.MaxStudents)
            </div>
        </div>
        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

Что я замечаю, так это то, что если пользователь введет -1 в поле Maximum Seats, проверка на стороне клиента будет запущена, и пользователь узнает, что значение должно быть в диапазоне от 0 до 32767.

Если пользователь нажимает кнопку «Отправить», проверка клиента запускается снова и отображается в сводке проверки в верхней части формы.

Если пользователь вводит допустимое значение в Maximum Seats, но вводит неверное значение в поле Тип комнаты, проверка на стороне клиента не указывает на ошибки (как я понимаю, поскольку Тип комнаты не проверяется на клиенте), и если пользователь нажимает кнопку «Отправить», во время вызова TryUpdateModel() вызывается функция IValidateObject.Validate, которая возвращает ошибку проверки, которая затем отображается на странице в сводке проверки в верхней части формы.

НО, если пользователь вводит как неправильный номер (-1), так и недопустимый тип помещения и нажимает кнопку Отправить, проверка на стороне клиента будет запускаться, НО проверка на стороне сервера не будет выполняться, поэтому он будет видеть только связанную на стороне клиента ошибки.

Есть ли в JavaScript какая-либо настройка или хитрость, которую я могу использовать, чтобы вызвать ОБА на стороне клиента и на сервере?

Если нет, я думаю, что моя единственная альтернатива - сделать все на стороне сервера валидации, что даст пользователю меньше обратной связи при переходе от поля к полю или проверку типа комнаты (проверьте значение находится в таблице Тип комнаты через вызов ajax) на стороне клиента, что будет дублировать усилия.

Есть идеи?

1 Ответ

2 голосов
/ 19 января 2012

Я думаю удаленная проверка - это то, что вы ищете. С этим вы можете сделать то, что вы упомянули об использовании ajax для проверки. Вы выполняете проверку номера на клиенте и проверку помещения на сервере, результаты которого сообщаются с проверкой на стороне клиента.

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