2012-03-15 93 views
3

请帮助这样一个问题,而不是严格的判断,因为我是MVC的新手: 我有一个模型,用于通过ID在我的数据库中存储用户名需要帮助来解释Readonly ScaffoldColumn(false)

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 - 我有错误,因为没有这样的ID在数据库中的条目。 Ok.Let查找属性以隐藏编辑器。 [ScaffoldColumn(false)]类似于是否为Id提供编辑器的标记。 应用到我的模型我从我的View.Try另一个attr“0”ID发帖。 [ReadOnly(true)]使字段成为只读字段。但在同一时间,我在发布Id时得到了“0”。 修改视图我放在一个编辑的每个字段模型

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

但使用它是危险的,因为有些用户可以发表错误编号throgh请求后。

我不能使用[ScaffoldColumn(false)]在控制器的[Httppost]动作中应用Id,通过在DB中搜索适当的用户条目,因为名称已更改。 我不相信@ Html.HiddenFor是唯一的出路。但找不到一个:(

+1

将id发布到隐藏的输入或操作方法参数中确实不是危险的。什么是危险的是不验证当前用户实际上可以修改传递的ID。 – dotjoe 2013-12-11 21:02:16

回答

5

正如你所提到的“[ScaffoldColumn(false)]是像是一个标记是否呈现编辑器为Id或不”)和[ReadOnly (true)]意味着这个属性在绑定模型时会被默认模型绑定器排除

问题是HTTP协议是无状态协议,这意味着当用户将编辑表单发布到MVC控制器,这个控制器不知道他正在编辑哪个对象,除非你在从用户接收到的请求中包含一些标识符给你的对象,但包括真实对象Id不是你提到的原因的好主意(有人可以发布另一个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); 
    } 

不要忘记更改模型的视图是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块中处理它。

你可以在这里(不要忘记来解决关键和Vector数组的值)找到SimpleAES加密类: Simple insecure two-way "obfuscation" for C#

PS: 这个答案是基于亨利森如下回答: Asp.net MVC 3 Encrypt Hidden Values