4

ASP.NET MVCの学習を進めていると、質問が発生し、問題が発生しました。

これまでに学んだことをテストするために、簡単なブログを作成しようとしています。しかし、フィールドの編集と終了に関しては、問題が発生します。

ブログで既に送信された投稿を編集しようとしていますが、投稿にはいくつかのフィールドが含まれています。ID、ヘッドライン、メッセージ、作成者、送信日ですが、編集しないでください。そのままにしておきます。

ここにいくつかのコードがあります:

私の投稿モデル:

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)、同じ日付が提出されることを知っています。しかし、ソースコードの隠しフィールドとしてそれを持っている以外の方法があるに違いありませんか?別の例では、これはそれほど安全ではないということですか?だから私はここに隠されたフィールド以外のものが欲しいです。助けてくれませんか?

これをそのまま実行しようとすると。日付が設定されていないというエラーが発生します。これは、日付も更新するためのロジックです。しかし、私はそれを望んでいません。あなたがそれを言うことができるならば、私はそれをオプションのままにしておきたいです。

4

3 に答える 3

8

見知らぬ人からキャンディーを取らないでください

つまり、クライアントから情報を取得してDBを直接更新しないでください。サーバー側でビジネスルールを適用する必要があり、クライアントがそれを実行することを信頼しないでください。

[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メソッドに追加することにより、ドメインレイヤーでこのようなルールを適用します。

于 2013-03-24T19:51:10.923 に答える
0

DateTimeは値型であり、nullにすることはできません。したがって、オプションにすることはできません。

null許容型にする必要があります。すなわち。

public DateTime? Date {get;set;}

一般に、ViewModelのほとんどの値型はnull許容である必要があります。次に、必須属性を使用して、それらに値が含まれるようにします。これにより、値の入力に失敗したかどうか、またはデフォルト値であるかどうかを判断できます。

コントローラで、日付に値があるかどうかを確認し、値がある場合は日付Date.HasValueを保存します。

セキュリティに関しては、この場合、それはめったに問題ではありません。誰かがページにアクセスでき(承認を通過し)、日付を更新する権利があると仮定すると、ユーザーがそれをバイパスできるかどうかは問題ではありません。彼らができることは、有効な日付形式を提出することだけです。日付が特定の期間内にあることを確認するロジックを追加する場合を除いて、心配する必要はありません。ModelBinderは、無効な日付形式にバインドされません。

たとえば役割に基づいて、ユーザーが日付を更新できるかどうかを制御する場合は、コントローラーにロジックを追加して、日付に値があり、ユーザーが正しい役割にあるかどうかを確認できます。更新しない場合は、エラーが発生します。

アップデート:

ここでの最も簡単な解決策は、2つのことを行うことだと思います。1つ目は、前述のように、Dateをnull許容にすることです。ビューに日付のフォームフィールドがない場合、これは厳密には必要ありませんが、後でフォームフィールドを追加する場合、テキストボックスを空のままにすると検証エラーが発生します。可能であれば、将来のエラーが発生しないようにしたいです。また、誰かが手動で編集アクションに値を投稿していて、それらに空白の日付フィールドが含まれている場合、単に無視するのではなく、検証に失敗します。値をnull許容にすると、値に関係なく、値を完全に無視できます。

次に、@ pswgが提案することを実行し、更新するフィールドのみを更新します。データベースから投稿を取得し、IDと日付を除くすべてのフィールドを更新します。次に、を呼び出しますSaveChanges()

于 2013-03-24T20:00:07.977 に答える
0

ここにちょうど私の2セント。私はこれが単純な状況であることを知っています、そして与えられた答えは素晴らしくて簡単です。しかし、その属性のリストが増えるにつれて、それは難しくなる可能性があります。

したがって、これらの線に沿って別のアプローチがあります

    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();

ただし、いくつかのフィールドを実行しているだけの場合は、上記の意味があります。ノギンを使ってください!

于 2016-06-23T11:12:24.307 に答える