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

У меня есть объект с именем Visit со следующими свойствами:

Примечание DoctorID VisitTypeID CreatedBy Date VisitID PatientID StatusID Timestamp

В представлении «Редактировать» пользователь может редактировать только следующие два свойства: — Примечание DoctorID. Поэтому я добавил другие свойства в виде скрытого поля в моем представлении редактирования следующим образом: —

    @using (Html.BeginForm()) {
        @Html.ValidationSummary(true)
        <fieldset>
            <legend>Visit</legend>
            <div class="editor-label">
                @Html.LabelFor(model => model.Note)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => model.Note)
                @Html.ValidationMessageFor(model => model.Note)
            </div>

            <div class="editor-label">
                @Html.LabelFor(model => model.DoctorID)
            </div>
            <div class="editor-field">
                @Html.DropDownList("DoctorID", String.Empty)
                @Html.ValidationMessageFor(model => model.DoctorID)
            </div>

            <p>
              @Html.HiddenFor(model => model.VisitTypeID)
              @Html.HiddenFor(model => model.CreatedBy)
              @Html.HiddenFor(model => model.Date)
              @Html.HiddenFor(model => model.VisitID)
              @Html.HiddenFor(model => model.PatientID)
              @Html.HiddenFor(model => model.StatusID)
              @Html.HiddenFor(model => model.timestamp)

            <input type="submit" value="Create" />

Я должен включить все свойства в свое представление редактирования, так как я передаю объект «Посещение» моему методу действия редактирования публикации, который выглядит следующим образом:

  [HttpPost]
            public ActionResult Edit(Visit visit)
            {
                if (!(visit.Editable(User.Identity.Name)))
                {
                    return View("NotFound");
                }
                try
                {
                    if (ModelState.IsValid)
                    {
                        repository.UpdateVisit(visit);
                        repository.Save();
                        return RedirectToAction("Index");
                    }
                }
                catch (DbUpdateConcurrencyException ex)
                {
    var entry = ex.Entries.Single();
                    var clientValues = (Visit)entry.Entity;

                    ModelState.AddModelError(string.Empty, "The record you attempted to edit "
                    + "was modified by another user after you got the original value. The "

    //code goes here

Поэтому я обеспокоен вышеуказанным подходом по следующим причинам: 1. Злоумышленник может изменить значения скрытых полей. 2. я не могу определить [Bind(Include = "....")] в моем классе модели Visit.

Поэтому я не могу решить, следует ли мне продолжать использовать этот подход ИЛИ есть лучший подход, которому можно следовать


person john Gu    schedule 25.04.2012    source источник
comment
но если я использую ViewModle, то как я могу отслеживать значение метки времени, поскольку ViewModel не будет иметь связанных значений метки времени в базе данных. Как и в моем методе действия, я проверяю исключение DbUpdateConcurrencyException, которое будет поднято, если нет метки времени значение было найдено в процессе редактирования...   -  person john Gu    schedule 26.04.2012
comment
Вы можете поместить метку времени в ViewModel   -  person SLaks    schedule 26.04.2012
comment
Спасибо за ответ; есть ли пример того, как я могу использовать viewModels вместо использования объектов Model для операций CRUD...   -  person john Gu    schedule 26.04.2012


Ответы (1)


Вы могли бы повторно получить объект Visit в своем контроллере, а затем перенести только два поля, которые вы хотите заполнить. Это гарантирует, что редактируются только эти два поля.

Visit existingVisit = /* retrieve Visit */;
existingVisit.Note = visit.Note;
existingVisit.DoctorID = visit.DoctorID;
repostistory.Update(existingVisit);
reposistory.SaveChanges();

Однако я могу сделать еще один шаг и создать модель представления для этого конкретного действия, которая будет включать только интересующие вас поля.

person Brad Christie    schedule 25.04.2012
comment
если я использую ваш подход для поиска объекта посещения и повторного извлечения его со значениями, то DbUpdateConcurrencyException никогда не будет поднято, поэтому мне нужно передать объект методу действия, чтобы иметь возможность поднять DbUpdateConcurrencyException при необходимости ... - person john Gu; 26.04.2012
comment
Вы не используете проверки дублирования на основе временных меток? Каждый раз, когда у нас когда-либо были многопользовательские изменения, мы использовали столбец lastupdated, который повторно проверяется при сохранении, чтобы определить, совпадает ли он с объектом, который мы пытаемся сохранить (затем, конечно, обновляется после отправки обновления). - person Brad Christie; 26.04.2012
comment
я не уверен, что вы имеете в виду, говоря, что вы не используете проверки дублирования на основе временных меток, но временная метка будет включена в предложение where для процесса редактирования, и если процесс редактирования не обновил какой-либо объект, будет поднято исключение DbUpdateConcurrencyException, которое означает, что объект был изменен другим пользователем после извлечения объекта... - person john Gu; 26.04.2012