请帮助解决这个问题并且不要严格判断,因为我是MVC的新手: 我有一个模型用于在我的数据库中按ID存储用户名称
public class Names
{
public int NameId { get; set; }
public string Username { get; set; }
}
, 一个conrtoller
[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>
编辑我的模型。 当我试图转到这个视图时,我看到了Id和用户名的编辑器,但是如果我填写Id - 我有错误,因为DB中没有带有这样ID的条目。 好的。让我们寻找隐藏编辑器的属性。 [ScaffoldColumn(false)]类似于标记是否为Id呈现编辑器。 将它推荐给我的模型我从我的View中发布了“0”id。尝试另一个attr。 [ReadOnly(true)]使字段成为只读字段。但同时我在发布Id时得到“0”。 修改视图我为模型
中的每个字段放置了一个编辑器@Html.HiddenFor(model => model.NameId)
@Html.EditorFor(model => model.Username)
但使用它很危险,因为有些用户可能会在发布请求后发布错误的ID。
我无法使用[ScaffoldColumn(false)]在控制器的[Httppost]操作中应用Id,通过在DB中搜索适当的用户条目,因为名称已更改。 我无法相信@ Html.HiddenFor是唯一的出路。但是找不到一个:(
答案 0 :(得分:5)
正如你所提到的那样“[ScaffoldColumn(false)]就像是一个标记,是否为Id编写一个编辑器”,而[ReadOnly(true)]意味着绑定时默认模型绑定器将排除此属性你的模特。
问题是HTTP协议是无状态协议,这意味着当用户将编辑表单发布到MVC控制器时,此控制器不知道他正在编辑哪个对象,除非您在对象中包含一些标识符从用户收到的请求,虽然包含真实对象ID不是一个好主意,因为你提到的原因(有人可以发布另一个Id)。
可能的解决方案可能是将带有加密ID的视图模型发送到View,并在控制器中解密此Id。
对象的视图模型可能如下所示:
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);
}
不要忘记将View的模型更改为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加密类(不要忘记修复Key和Vector数组的值): Simple insecure two-way "obfuscation" for C#
PS: 这个答案基于Henry Mori的以下答案: Asp.net MVC 3 Encrypt Hidden Values