2013-03-24 82 views
4

由於我在學習ASP.NET MVC的過程中,遇到了一個問題,並陷入了一些麻煩ASP.NET MVC:忽略編輯時的字段

我試圖創建一個簡單博客,只是爲了測試我迄今爲止學到的東西。但是當涉及到編輯和離開一個領域時,我遇到了一個問題。

我想編輯我的博客上已提交的帖子,該帖子包含幾個字段:標題,標題,消息,作者和提交日期不應編輯,只是保持原樣。

下面是一些代碼:

我樁模型:

namespace MyBlock.Models 
{ 
    public class Post 
    { 
     public int Id { get; set; } 

     [Required] 
     public string Author { get; set; } 

     [Required] 
     public string Headline { get; set; } 

     [Required] 
     public string Message { get; set; } 

     public DateTime Date { get; set; } 
    } 
} 

我編輯:

[HttpGet] 
public ActionResult Edit(int id = 0) 
{ 
    Post post = db.Posts.Find(id); 

    if (post != null) { 
     return View(post);   
    } 

    return HttpNotFound(); 
} 

[HttpPost] 
public ActionResult Edit(Post post) 
{ 
    if (ModelState.IsValid) { 
     db.Entry(post).State = EntityState.Modified; 
     db.SaveChanges(); 

     return RedirectToAction("Index", "Home"); 
    } 

    return View(post); 
} 

而且我對編輯觀點:

@model MyBlock.Models.Post 

@{ 
    ViewBag.Title = "Edit"; 
} 

<h2>Rediger "@Model.Headline"</h2> 

@using (Html.BeginForm()) { 
    @Html.LabelFor(u => u.Author) 
    @Html.TextBoxFor(u => u.Author) 

    @Html.LabelFor(u => u.Headline) 
    @Html.TextBoxFor(u => u.Headline) 

    @Html.LabelFor(u => u.Message) 
    @Html.TextAreaFor(u => u.Message) 

    <input type="submit" value="Gem" /> 
} 

我知道我可以投擲一個@HiddenFor(u => u.Date) a並提交相同的日期。但我敢打賭,還有另一種方式,而不是將它作爲源代碼中的隱藏字段?我的意思是這在另一個例子中並不安全?所以我想在這裏隱藏領域以外的東西。你們能幫我嗎?

如果我嘗試按原樣運行它。我得到一個錯誤,這是我的日期未設置,這是邏輯,因爲它想要更新那一個。但我不希望它。如果你能這樣說,我想讓它成爲可選項。

回答

8

不要拿陌生人

換句話說糖果,不從客戶端中獲取的信息,並直接更新數據庫。您應該在服務器端強制實施您的業務規則,並且不要相信客戶端爲您做到這一點。

[HttpPost] 
public ActionResult Edit(Post post) 
{ 
    if (ModelState.IsValid) { 
     var dbPost = db.Posts.FirstOrDefault(p => p.Id == post.Id); 
     if (dbPost == null) 
     { 
      return HttpNotFound(); 
     } 

     dbPost.Author = post.Author; 
     dbPost.Message = post.Message; 
     dbPost.Headline = post.Headline; 
     db.SaveChanges(); 

     return RedirectToAction("Index", "Home"); 
    } 

    return View(post); 
} 

[HttpPost] 
public ActionResult Add(Post post) 
{ 
    if (ModelState.IsValid) { 
     var dbPost = db.Create<Post>(); 
     dbPost.Author = post.Author; 
     dbPost.Message = post.Message; 
     dbPost.Headline = post.Headline; 
     dbPost.Date = DateTime.Now(); // Don't trust client to send current date 
     db.SaveChanges(); 

     return RedirectToAction("Index", "Home"); 
    } 

    return View(post); 
} 

在我自己的項目中,我通過添加自定義的驗證規則給ValidateEntity方法在領域層執行這樣的規則。

+0

這與提交相同,我的意思是創建/寫入數據到數據庫? – aventic 2013-03-24 19:54:24

+0

@KasperHyldalPedersen正確。 – 2013-03-24 19:55:18

+0

這是行之有效的。我對'寫入數據庫'有個疑問,我該怎麼做?我如何檢查用戶在視圖中寫入的內容?如果我不應該採取糖果:) 現在我有這個在我寫的ActionResult: '如果(ModelState.IsValid){ \t \t \t \t post.Date = DateTime.Now; \t \t \t \t db.Posts.Add(post); \t \t \t \t db.SaveChanges(); \t \t \t \t return RedirectToAction(「Index」,「Home」); \t \t \t}' – aventic 2013-03-24 20:40:42

0

DateTime是一個值類型,不能爲空。因此,它永遠不會是可選的。

您需要將它設爲可空類型。即。

public DateTime? Date {get;set;} 

一般來說,ViewModel中的大多數值類型應該是可以爲空的,然後使用Required屬性來強制它們包含一個值。這可以讓你判斷他們是否輸入了一個值,或者它是否是默認值。

在您的控制器中,您可以檢查日期是否具有Date.HasValue的值,如果是,則保存日期。

關於安全性,在這種情況下,它不是一個問題。假設有人可以訪問該頁面(他們通過授權),並且他們有權更新日期,那麼用戶是否可以繞過該日期並不重要。他們所能做的就是提交一個有效的日期格式。除非您想添加邏輯來確保日期在特定時間段內,否則您不必擔心。 ModelBinder不會綁定到無效的日期格式。

如果你想控制用戶是否可以更新日期,比如說基於角色,那麼你可以添加邏輯到你的控制器來檢查日期是否有值,用戶是否在正確的角色,否則發出一個錯誤。

UPDATE:

我覺得這裏最簡單的方法是做兩件事情。首先是使日期可以爲空,正如我上面提到的那樣。儘管如果您在視圖中沒有Date字段,那麼這並不是絕對必要的,但如果您稍後要添加表單字段,那麼如果您將文本框留空,則會出現驗證錯誤。如果可能的話,我喜歡防止將來發生錯誤。另外,如果有人將值手動發佈到您的編輯操作,並且它們包含空白的日期字段,它將無法驗證,而不是簡單地忽略它。使值可以爲空可以使該值完全忽略,而不管其值如何。

其次,是做什麼@ p.s.w.g建議,只更新您想要更新的字段。從數據庫中檢索帖子,然後更新除Id和Date之外的所有字段。然後致電SaveChanges()

+0

現在我明白你的意思了...... – 2013-03-24 20:01:04

+0

@ p.s.w.g - 咦?他的問題是他希望日期是可選的,這與問題有關。 – 2013-03-24 20:02:40

+0

@MystereMan是的我想這會解決錯誤,但我讀這個問題的方式,OP不希望在用戶編輯Post時''Date'字段被更新。用你的方法,如果'Date'字段沒有在表單中提供,它將被更新爲'null'。 – 2013-03-24 20:06:17

0

只是我的2cents在這裏。我知道這是一個簡單的情況,給出的答案很好,很直接。但隨着屬性列表的增長,它可能會變得困難。

所以不同approuch將沿着這些路線

var t = _db.Blog.Where(x => x.ID == id).FirstOrDefault(); 

    var info = typeof(Blog).GetProperties(); 
//properties you don't want to update 
    var properties = info.Where(x => x.Name != "xxx" && x.Name != "xxxx").ToList(); 
    foreach(var p in properties) 
    { 
     p.SetValue(t, p.GetValue(temp.Volunteer)); 
    } 


    _db.Entry(t).State = EntityState.Modified; 
    _db.SaveChanges(); 

但如果你只是做了幾個區,然後上面是有道理的。 只需使用你的頭巾!