如何仅限EF 6 / ASP.NET MVC 5中的Sepcific用户限制用户条目

时间:2015-09-02 23:30:03

标签: c# asp.net-mvc-5 entity-framework-6

我正在尝试限制用户条目,以便只有该特定用户才能看到他们的条目,而不是其他任何人。换句话说,毕竟我已经完成了,我的应用程序仍会显示所有输入的条目;任何用户都可以看到这些条目。

我通过使用Entity Framework中的Code First约定将我的Expenses表中的外键引用到我的AspNetUsers的主键创建了一对多的关系,但是,当我以不同的用户身份登录时,我我仍然可以看到其他用户输入的条目(费用)。

我不确定问题是出在我的视图,模型还是控制器中。

以下是我目前的代码:

IdentityModel

 public class ApplicationUser : IdentityUser
{
    public ApplicationUser()
    {
        Expenses = new List<Expense>();
    }

    [Required]
    public string Fullname { get; set; }
    [Required]
    public string Province { get; set; }
    [Required]
    public string Company { get; set; }
    public virtual ICollection<Expense> Expenses { get; set; }

    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here
        return userIdentity;
    }


}

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
    public ApplicationDbContext()
        : base("PacificPetEntities", throwIfV1Schema: false)
    {
    }

    public IDbSet<Expense> Expenses { get; set; }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }



}

费用模型

public class Expense : IValidatableObject
{
    public Expense() { }

    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }
    [Required]
    public string Category { get; set; }
    public string Description { get; set; }

    [Required]
    [Display(Name = "Gross Amount")]
    public double GrossAmount { get; set; }
    [Required]
    [Display(Name = "Tax Amount")]
    public double TaxAmount { get; set; }
    [Required]
    [Display(Name = "Net Amount")]
    public double NetAmount { get; set; }
    public int Mileage { get; set; }
    [Display(Name = "Mileage Rate")]
    public double MileageRate { get; set; }

    [Required]
    [Display(Name = "Date Submitted")]
    public DateTime? DateSubmitted { get; set; }
    [Required]
    [Display(Name = "Expense Date")]
    public DateTime? ExpenseDate { get; set; }


    public string UserId { get; set; }
    [ForeignKey("UserId")]
    public virtual ApplicationUser ApplicationUser { get; set; }



    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (Category == "Auto - Mileage" && Mileage == 0)
        {
            yield return new ValidationResult("You must enter a mileage amount if the chosen category is mileage.");
        }
    }

}

控制器

public class ExpensesController : Controller
{
    private ApplicationDbContext db = new ApplicationDbContext();

    // GET: Expenses
    [Authorize]
    public ActionResult Index()
    {
        var expenses = db.Expenses.Include(e => e.ApplicationUser);
        return View(expenses.ToList());
    }

    // GET: Expenses/Details/5
    [Authorize]
    public ActionResult Details(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Expense expense = db.Expenses.Find(id);
        if (expense == null)
        {
            return HttpNotFound();
        }
        return View(expense);
    }

    // GET: Expenses/Create
    [Authorize]
    public ActionResult Create()
    {
        ViewBag.UserId = new SelectList(db.Users, "Id", "Fullname");
        return View();
    }

    // POST: Expenses/Create
    // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
    // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
    [HttpPost]
    [ValidateAntiForgeryToken]
    [Authorize]
    public ActionResult Create([Bind(Include = "ID,Category,Description,GrossAmount,TaxAmount,NetAmount,Mileage,MileageRate,DateSubmitted,ExpenseDate,UserId")] Expense expense)
    {
        if (ModelState.IsValid)
        {
            db.Expenses.Add(expense);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        ViewBag.UserId = new SelectList(db.Users, "Id", "Fullname", expense.UserId);
        return View(expense);
    }

    // GET: Expenses/Edit/5
    [Authorize]
    public ActionResult Edit(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Expense expense = db.Expenses.Find(id);
        if (expense == null)
        {
            return HttpNotFound();
        }
        ViewBag.UserId = new SelectList(db.Users, "Id", "Fullname", expense.UserId);
        return View(expense);
    }

    // POST: Expenses/Edit/5
    // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
    // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
    [HttpPost]
    [ValidateAntiForgeryToken]
    [Authorize]
    public ActionResult Edit([Bind(Include = "ID,Category,Description,GrossAmount,TaxAmount,NetAmount,Mileage,MileageRate,DateSubmitted,ExpenseDate,UserId")] Expense expense)
    {
        if (ModelState.IsValid)
        {
            db.Entry(expense).State = System.Data.Entity.EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        ViewBag.UserId = new SelectList(db.Users, "Id", "Fullname", expense.UserId);
        return View(expense);
    }

    // GET: Expenses/Delete/5
    [Authorize]
    public ActionResult Delete(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Expense expense = db.Expenses.Find(id);
        if (expense == null)
        {
            return HttpNotFound();
        }
        return View(expense);
    }

    // POST: Expenses/Delete/5
    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    [Authorize]
    public ActionResult DeleteConfirmed(int id)
    {
        Expense expense = db.Expenses.Find(id);
        db.Expenses.Remove(expense);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            db.Dispose();
        }
        base.Dispose(disposing);
    }
}

Index.cshtml

 @model IEnumerable<PacificPetExpenses.Models.Expense>

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.ApplicationUser.Fullname)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Category)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Description)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.GrossAmount)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.TaxAmount)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.NetAmount)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Mileage)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.MileageRate)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.DateSubmitted)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.ExpenseDate)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.ApplicationUser.Fullname)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Category)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Description)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.GrossAmount)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.TaxAmount)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.NetAmount)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Mileage)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.MileageRate)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.DateSubmitted)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ExpenseDate)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
            @Html.ActionLink("Details", "Details", new { id=item.ID }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.ID })
        </td>
    </tr>
}

</table>

请帮忙。

谢谢。

2 个答案:

答案 0 :(得分:1)

使用当前用户ID选择您的Expenses。像这样。

// GET: Expenses
[Authorize]
public ActionResult Index()
{
    var expenses = db.Expenses.Where(e => e.UserId == User.Identity.GetUserId());
    return View(expenses.ToList());
}

答案 1 :(得分:0)

我找到了答案。 Padhraic非常接近,但他的回答帮助我解决了我的问题。

在我的控制器中,我有:

jq -r 'if .StatusInfos != null then 
        .StatusInfos[] as $info | {
             RepStatus: $info.Status,
             RepStatusType: $info.StatusType,
             ReadReplicaSourceDBInstanceIdentifier,
             DBInstanceIdentifier }
    else . end'

相反,这应该是:

public ActionResult Index()
{
    var expenses = db.Expenses.Include(e => e.ApplicationUser);
    return View(expenses.ToList());
}

根据Stephen Muecke对我的问题的评论, db.Expenses.Include(e =&gt; e.ApplicationUser)正在返回我数据库中的所有行。相反,我需要将结果过滤到当前用户。