Нужна помощь, чтобы объяснить Readonly \ ScaffoldColumn (false) - PullRequest
3 голосов
/ 15 марта 2012

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

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)] является чем-то вроде маркера, отображать ли редактор для идентификатора или нет. Применив его к моей модели, я получил сообщение "0" от моего View.Try другой attr. [ReadOnly (true)] делает поле доступным только для чтения. Но в то же время я получил "0" в идентификаторе. Изменяя вид, я поместил редакторы для каждого поля в модели

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

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

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

1 Ответ

5 голосов
/ 05 декабря 2013

Как вы упомянули, «[ScaffoldColumn (false)] является чем-то вроде маркера, отображать ли редактор для идентификатора или нет», а [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.

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

PS: Этот ответна основании следующего ответа Генри Мори: Asp.net MVC 3 Шифровать скрытые значения

...