0

私は次のモデルを持っています:

public class Expense
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }
    [Required]
    public string Name { get; set; }
    [Required]
    [Column(TypeName = "Money")]
    public decimal Limit { get; set; }
    [Required]
    [ForeignKey("UserProfile")]
    public int UserProfileId { get; set; }
    [Required]
    public virtual UserProfile UserProfile { get; set; }
}

[Table("UserProfile")]
public class UserProfile
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int UserId { get; set; }
    public string UserName { get; set; }
    public virtual ICollection<Expense> Expenses { get; set; }
}

ログインしているユーザーがいて、そのユーザーが新しい経費を追加できるようにしたいと考えています。create controller アクションは次のようになります。

    //
    // GET: /Expenses/Create

    public ActionResult Create()
    {

        return View();
    }

    //
    // POST: /Expenses/Create

    [HttpPost]
    public ActionResult Create(Expense expense)
    {            
        if (ModelState.IsValid)
        {
            UserProfile user = db.UserProfiles.Single(u => u.UserName == User.Identity.Name)
            user.Expenses.Add(expense);                
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(expense);
    }

ビューで:

@model MoneyDrainPlug.Models.Expense

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Expense</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Limit)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Limit)
            @Html.ValidationMessageFor(model => model.Limit)
        </div>        
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

ポストが発生すると、ModelState.IsValid はコントローラーで false になります。これは、経費に UserProfileId が設定されていないためです。ModelState.IsValid を呼び出す前に UserProfile や UserProfileId を設定しても役に立ちません。

これを処理する正しい安全な方法は何でしょうか? クライアントから送信された UserProfileId を信頼してはいけませんか?

問題がある場合は、asp.net MVC 4 を使用しています。

前もって感謝します

4

2 に答える 2

1

可能な解決策

Requiredon の属性を削除しますUserProfileId(DataAnnotation はビューに関連しているだけです。ビューに何かが必要ない場合は、DB 制約ではないというマークを付けないでRequiredください)RequiredAttribute

また

プロパティを削除しUserProfileIdます(プロパティがあり、UserProfileおそらく十分です)

また

プロパティViewModelなしで を作成するUserProfileId

編集:明確にするために:ViewModelを完全に使用できます。必須属性は DB とは直接関係がないことに注意してください。Expenseクラスをビューで直接使用しない場合は、ですべてのRequired属性を削除できますExpense。それらは使用されません。

于 2012-10-05T22:16:44.210 に答える
1

1つは、これらのページに許可されたユーザーのみがアクセスできるようにする必要があります(ユーザーのログインを必要とするコントローラーのすべてのメソッドの上に[Authorize]を追加します)

実際にこれを行うには、いくつかの方法があります。

1 つはUserProfileId という名前の非表示フィールドで、ログインしているユーザー Id の値です。これは、ID がクライアントからサーバーに送信されるため、クライアントによって操作される可能性があるため、最も安全でない方法です。

これらのフィールドには必須の注釈が付いているので、[Required] を削除して検証するか、 UserProfileId を必要とせずにこれらすべての属性を含む新しいビューモデルを作成します (明らかに、仮想属性はこれには必要ないため含めません)。場合)。

次のようになります。

public class ExpenseModel
{
    [Required]
    public string Name { get; set; }
    [Required]
    public decimal Limit { get; set; }
    public int UserProfileId { get; set; }
}

最後の仕上げとして、ビューが期待するモデルを変更します。

@model MoneyDrainPlug.Models.ExpenseModel

そして、コントローラーが投稿後に受信することを期待するモデル:

[Authorize]
[HttpPost]
    public ActionResult Create(ExpenseModel expense)
    {            
        if (ModelState.IsValid)
        {
            UserProfile user = db.UserProfiles.Single(u => u.UserName == User.Identity.Name)
            _expense = new Expense() { Name = expense.Name, Limit = expense.Limit, UserProfile = user };
            user.Expenses.Add(_expense);                
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(expense);
    }
于 2012-10-05T22:17:42.963 に答える