Need help explaining Readonly \ ScaffoldColumn (false)

Please help with a question like this and don't judge strictly, because I'm new to MVC: I have a model for storing usernames by ID in my DB

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

      

, controller

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

      

Adding and editing a view adding works well, the question is editing I am using

    @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>

      

to change my model. when trying to go to this view I see an editor for both Id and Username, but if I fill in Id - I have an error because there is no such id in DB. Ok.Let look for attributes to hide the editor. [ScaffoldColumn (false)] is something like a marker, whether the editor should be displayed for Id or not. by attaching it to my model, I have the message "0" id from my View.Try another attr. [ReadOnly (true)] makes the field read-only. But at the same time, I have a "0" when submitting an id. Change view I have placed editors for each field in the model

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

      

but using this is dangerous because some user might post the wrong Id after being requested.

I cannot use the [ScaffoldColumn (false)] with the Id applied in the [Httppost] controller action by looking up the corresponding user record in the database because the name has been changed .. I cannot believe @ Html.HiddenFor is the only way out. But he cannot find one :(

+3


source to share


1 answer


As you mentioned, "[ScaffoldColumn (false)] is something like a marker, whether the editor should be rendered for Id or not," and [ReadOnly (true)] means that this property will be excluded by the nexus by default when linking your model.

The problem is that the HTTP protocol is a stateless protocol, which means that when a user submits an edit form to an MVC controller, that controller has no idea what object he was editing unless you included any id in your object in the request received from the user, although it contains the ID of the real object, is not a good idea for the reason you mentioned (that someone might post a different ID).

A possible solution would be to send the View View with an encrypted id to the view and decrypt that id in the controller.

The view model for your object might look like this:

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

      

So your HttpGet action method would be

    [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);
    }

      



Don't forget to change the model for your view as the ViewModel

@model UserViewModel

      

Now the HttpPost action method will receive 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);
    }

      

When the user tries to change the encrypted key, the decryption will not throw a CryptographicException, where you can handle it in the catch block.

Here you can find the SimpleAES encryption class (remember to correct the values โ€‹โ€‹of the Key and Vector arrays): Simple unsafe two-way "obfuscation". for c #

PS: This answer is based on the following answer by Henry Morey: Asp.net MVC 3 Encrypts Hidden Values

+5


source







All Articles