Нужна помощь, чтобы объяснить Readonly\ScaffoldColumn(false)

Помогите пожалуйста с таким вопросом и не судите строго так как я новичок в MVC: у меня есть модель хранения имен пользователей по ID в моей БД

public class Names
    {
public int NameId { get; set; }
public string Username { get; set; }
}

, контролер

[HttpPost]
        public ActionResult EditforModel(Names Name)
        {
            if (ModelState.IsValid)
            {
                db.Entry(Name).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(Name);
        }

добавление и редактирование добавления представления работает хорошо, вопрос о редактировании, которым я пользуюсь

    @using (Html.BeginForm())
    {
        @Html.ValidationSummary(true)
        <fieldset>
        <legend> legend </legend>
        @Html.EditorForModel()
        <p>
                <input type="submit" value="Save" />
            </p>
    </fieldset>
    }

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

для редактирования моей модели. при попытке перейти в это представление я вижу редактор как для идентификатора, так и для имени пользователя, но если я заполняю идентификатор - у меня ошибка, потому что в БД нет записи с таким идентификатором. Хорошо. Давайте поищем атрибуты, чтобы скрыть редактор. [ScaffoldColumn(false)] — это что-то вроде маркера, отображать ли редактор для Id или нет. применив его к моей модели, у меня есть публикация идентификатора «0» из моего представления. Попробуйте другой атрибут. [ReadOnly(true)] делает поле доступным только для чтения. Но при этом у меня в постинге "0". Изменяя представление, я разместил редакторы для каждого поля в модели.

@Html.HiddenFor(model => model.NameId)
@Html.EditorFor(model => model.Username)

но использовать его опасно, потому что какой-то пользователь может опубликовать неправильный идентификатор через пост-запрос.

Я не могу использовать [ScaffoldColumn(false)] с применением идентификатора в действии [Httppost] контроллера, выполнив поиск соответствующей пользовательской записи в БД, потому что имя было изменено. Я не могу поверить, что @Html.HiddenFor - это единственный выход.но не могу найти :(


person versus    schedule 15.03.2012    source источник
comment
На самом деле не опасно публиковать идентификатор в скрытом параметре метода ввода или действия. Опасно НЕ проверять, что текущий пользователь действительно может изменить переданный идентификатор.   -  person dotjoe    schedule 12.12.2013


Ответы (1)


Как вы упомянули, «[ScaffoldColumn (false)] - это что-то вроде маркера, отображать ли редактор для Id или нет», а [ReadOnly (true)] означает, что это свойство будет исключено связывателем модели по умолчанию при привязке вашей модели.

Проблема в том, что протокол HTTP является протоколом без сохранения состояния, а это означает, что когда пользователь отправляет форму редактирования в контроллер MVC, этот контроллер не знает, какой объект он редактировал, если только вы не включили какой-либо идентификатор в свой объект в полученном запросе. от пользователя, хотя включение реального идентификатора объекта не является хорошей идеей по причине, которую вы упомянули (что кто-то может опубликовать другой идентификатор).

Возможным решением может быть отправка модели представления с зашифрованным идентификатором в представление и расшифровка этого идентификатора в контроллере.

Модель представления для вашего объекта может выглядеть так:

public class UserViewModel
{
    [HiddenInput(DisplayValue = false)]
    public string EncryptedId { get; set; }
    public string Username { get; set; }
}

Таким образом, ваш метод действия HttpGet будет

    [HttpGet]
    public ActionResult EditforModel()
    {
        // fetching the real object "user"
        ...

        var userView = new UserViewModel
        {
            // passing the encrypted Id to the ViewModel object
            EncryptedId = new SimpleAES().EncryptToString(user.NameId.ToString()),
            Username = user.Username
        };

        // passing the ViewModel object to the View
        return View(userView);
    }

Не забудьте изменить модель вашего представления на ViewModel.

@model UserViewModel

Теперь метод действия HttpPost будет получать UserViewModel.

    [HttpPost]
    public ActionResult EditforModel(UserViewModel Name)
    {
        if (ModelState.IsValid)
        {
            try
            {
                var strId = new SimpleAES().DecryptString(Name.EncryptedId);
                var id = int.Parse(strId);
                // select the real object using the decrypted Id
                var user = ...Single(p => p.NameId == id);
                // update the value from the ViewModel
                user.Username = Name.Username;
                db.Entry(user).State = EntityState.Modified;
            }
            catch (CryptographicException)
            {
                // handle the case where the encrypted key has been changed
                return View("Error");
            }

            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(Name);
    }

Когда пользователь попытается изменить зашифрованный ключ, расшифровка завершится ошибкой, вызвав CryptographicException, где вы сможете обработать его в блоке catch.

Здесь вы можете найти класс шифрования SimpleAES (не забудьте исправить значения массивов ключей и векторов): Простая небезопасная двусторонняя обфускация для C#

PS: этот ответ основан на следующем ответе Генри Мори: Asp.net MVC 3 Шифрование скрытых значений

person Ahmad Ibrahim    schedule 05.12.2013