如何让我的购买类映射到特定的ApplicationUser

时间:2017-06-13 15:12:45

标签: asp.net-mvc-4 entity-framework-6 asp.net-identity

这是理念。当管理员登录时,他们可以提取所有用户的列表。它会提供编辑,详细信息,删除等正常选项,但我已经添加了一个购买链接,如下所示:

    @model IEnumerable<IdentitySample.Models.ApplicationUser>

    @{
ViewBag.Title = "Index";
    }
      <div class="col-12 backgroundImg">
        <div class="navbarSpace">
    <div class="col-12 formBackground">
       <h2 class="formHeader">List of Users</h2>

        <h4 class="formText">
            @Html.ActionLink("Create New ", "Create")
        </h4>
        <table class="table">
            <tr>
                <th>
                    @Html.DisplayNameFor(model => model.Email)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.UserName)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.FavStrain)
                </th>
                <th>

                </th>
            </tr>

            @foreach (var item in Model)
        {
                <tr>
                    <td>
                        @Html.DisplayFor(modelItem => item.Email)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.UserName)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.FavStrain)
                    </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 }) |
                        @Html.ActionLink("Purchases", "PurchaseIndex", new { 
        id = item.Id})

                    </td>
                </tr>
            }
             </table>
          </div>
        </div>
             </div>enter code here

当您单击“购买”链接时,它会将您带到PurchaseIndex页面,如下所示: Purchase List

       @model IEnumerable<IdentitySample.Models.Purchases>

        @{
ViewBag.Title = "Index";
      }
      <div class="col-12 backgroundImg navbarSpace">
        <div class="col-12 formBackground">
    <h2 class="formHeader">Index</h2>
    <hr />
    <div class="formHeaderSmall">
        Total Points <br />
        @Model.Sum(i => i.Points) </div>
    <p class="formText">
        @Html.ActionLink("Create New", "CreatePurchase")
    </p>
    <table class="table">
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Name)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Points)
            </th>

            <th></th>
        </tr>

        @foreach (var item in Model)
        {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.Name)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Points)
                </td>

                <td></td>
            </tr>
        }
     </table>
    <p class="formText">
        @Html.ActionLink("Back to List", "Index")
    </p>
     </div>
     </div>

它给出了一个购买列表,并给出了我没有包含详细信息页面的总分。除了购买不映射到特定用户之外,一切正常。如果我创建一个新用户并单击“购买”,则会显示所有购买的列表,而不仅仅是针对该用户的特定购买。如何将购买映射到特定用户?

我创建了一个如下所示的Purchases类:

  public class Purchases
{
    [Key]
    public int PurchaseId { get; set; }


    [Required]
    [Display(Name = "Product Name")]
    [DataType(DataType.Text)]
    public string Name { get; set; }

    [Required]
   [Range(0,5)]
    [Display(Name = "Points")]
    [DataType(DataType.Text)]
    public int Points { get; set; }

    public string ApplicationUserId { get; set; }
    public virtual ApplicationUser Users { get; set; }
}

我的ApplicationUser类看起来像这样:

 public class ApplicationUser : IdentityUser
{
    [Display(Name ="Favorite Strain")]
    [DataType(DataType.Text)]
    public string FavStrain { get; set; }
    public virtual List<Purchases> Purchase { get; set; }

到目前为止,数据库正在按照预期的方式将Purchases类的外键注册到ApplicationUser类。

我可以创建一个新的购买并将它们显示在列表中,并且所有Crud操作都可以正常工作。 问题是,当我创建一个新的购买时,它不会在数据库中包含ApplicationUserId,它会返回Null。

Null Database

我很确定问题出在我的控制器中。我已经尝试了所有的东西,所以我不想包括失败的尝试,所以这里是控制器,因为它们现在正在工作。

我不需要包含编辑或详细信息,因为我不会向用户提供访问权限。

 public ActionResult CreatePurchase()
    {

        return View();
    }
    private ApplicationDbContext db = new ApplicationDbContext();

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult CreatePurchase([Bind(Include = "PurchaseId,Name,Points,Id")] Purchases purchases)
    {
        if (ModelState.IsValid)
        {
            db.Purchases.Add(purchases);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(purchases);
    }

    // GET: Purchases/Edit/5
    public ActionResult PurchaseIndex()
    {

        var userDetails = db.Purchases.Include(u => u.Users);
        return View(db.Purchases.ToList());
    }

这是我关于Stack Overflow的第一个问题,如果有些事情不对,请原谅我。

********* ********更新****************************

这是我的PurchaseIndexController。现在,这仅返回与购买相关联的用户。但是它始终为0,因为没有UserID。如果我尝试使用int?型或Guid?它给出了一个错误。无法将int类型隐式转换为字符串。

           public ActionResult PurchaseIndex(string ID)
    {
        //this gets all purchases for a certain individual
        ApplicationDbContext db = new ApplicationDbContext();
        var userDetails = db.Purchases.Where(x => x.ApplicationUserId == 
   ID).ToList();
        return View(userDetails);

    }

这是CreatePurchase View

    @model IdentitySample.Models.Purchases

@{
ViewBag.Title = "Create";
}
 <div class="col-12 backgroundImg navbarSpace">
<div class="col-12 formBackground">
    <h2 class="formHeader">Add a New Purchase</h2>
    <hr />
    @using (Html.BeginForm())
    {

        @Html.AntiForgeryToken()
      @*@Html.Hidden("id", (string)ViewBag.UserID)*@
        @Html.HiddenFor(model => model.ApplicationUserId)
        <div class="form-horizontal">


            <div class="col-12">
                @Html.LabelFor(model => model.Name, htmlAttributes: new { 
          @class = "formText col-12" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Name, new { 
        htmlAttributes = new { @class = "col-12" } })
                    @Html.ValidationMessageFor(model => model.Name, "", new 
      { @class = "text-danger" })
                </div>
            </div>

            <div class="col-12">
                @Html.LabelFor(model => model.Points, htmlAttributes: new { 
      @class = "formText col-12" })
                <div class="col-md-10">
                    @Html.EditorFor(model => model.Points, new { 
      htmlAttributes = new { @class = "col-12" } })
                    @Html.ValidationMessageFor(model => model.Points, "", 
      new { @class = "text-danger" })
                </div>
            </div>

            <div class="col-12">
                <div class="col-md-offset-2 col-md-10">
                    <input type="submit" value="Create" class="btn btn-
           default" />
                </div>
            </div>
        </div>
    }

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

我还在管理部分中有链接,供用户查看积分和购买但我不知道如何为此创建ActionLink以获取与用户相关的购买。                   这是控制器

   public ActionResult WeedPoints(string ID)
    {
        ApplicationDbContext db = new ApplicationDbContext();
        var userDetails = db.Purchases.Where(x => x.ApplicationUserId == 
    ID).ToList();
        return View(userDetails);

      }

现在是Action Link。

<div class="col-12 formHeaderSmall">@Html.ActionLink("My 
 Purchases/Points", "WeedPoints", "Manage")</div>

**********更新************* ***************************

以下是带有View Bag参考的控制器。创建购买视图具有ViewBag我刚刚取消注释它。

 [Authorize(Roles = 
"Admin,DispensaryManager,DispensaryEmployee,DispensaryEastEmployee")]
    public ActionResult CreatePurchase(string Id)
    {
        ViewBag.UserID = Id;

        //ApplicationDbContext db = new ApplicationDbContext();
  //var userDetails = db.Purchases.Where(x => x.ApplicationUserId == Id;

        return View();

    }
    private ApplicationDbContext db = new ApplicationDbContext();
    //POST: Purchases/Create

    [HttpPost]
    [Authorize(Roles = 
      "Admin,DispensaryManager,DispensaryEmployee,DispensaryEastEmployee")]
    [ValidateAntiForgeryToken]
    public ActionResult CreatePurchase([Bind(Include = 
      "PurchaseId,Name,Points,ApplicationUserId")] Purchases 
    purchases,string id)
    {
        if (ModelState.IsValid)
        {

            db.Purchases.Add(purchases);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(purchases);
    }

    [Authorize(Roles = 
   "Admin,DispensaryManager,DispensaryEmployee,DispensaryEastEmployee")]
    public ActionResult PurchaseIndex(string Id)
    {
        //this gets all purchases for a certain individual
        ApplicationDbContext db = new ApplicationDbContext();
        var userDetails = db.Purchases.Where(x => x.ApplicationUserId == 
    Id).ToList();
        ViewBag.UserID = Id;
        return View(userDetails);

    }

*************************** Total Refactor ****************** *************** 8

这是完整的新控制器。

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

    // GET: Purchases
    public ActionResult Index()
    {
        var purchases = db.Purchases.Include(p => p.Users);
        return View(purchases.ToList());
    }

    // GET: Purchases/Details/5
    public ActionResult Details(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Purchases purchases = db.Purchases.Find(id);
        if (purchases == null)
        {
            return HttpNotFound();
        }
        return View(purchases);
    }

    // GET: Purchases/Create
    public ActionResult Create()
    {
        ViewBag.Users = new SelectList(db.Users, "Id", "UserName");


        List<SelectListItem> selectListItems = new List<SelectListItem>();

        foreach (ApplicationUser user in db.Users)
        {
            SelectListItem selectListItem = new SelectListItem
            {
                Text = user.UserName,
                Value = user.Id.ToString()
            };
            selectListItems.Add(selectListItem);
        }
        //ViewBag.ApplicationUserId = new SelectList(db.Users, "Id", 
   "UserName");
        return View();
    }

    // POST: Purchases/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]
    public ActionResult Create([Bind(Include = 
 "PurchaseId,Name,Points,TotalPoints,ApplicationUserId")] Purchases 
 purchases)
    {
        if (ModelState.IsValid)
        {
            var totalPoints = db.Purchases.Sum(x => x.Points);
            purchases.TotalPoints = totalPoints;
            db.Purchases.Add(purchases);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        ViewBag.ApplicationUserId = new SelectList(db.Users, "Id", 
     "UserName", purchases.ApplicationUserId);
        return View(purchases);
    }

    // GET: Purchases/Edit/5
    public ActionResult Edit(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Purchases purchases = db.Purchases.Find(id);
        if (purchases == null)
        {
            return HttpNotFound();
        }
        ViewBag.ApplicationUserId = new SelectList(db.Users, "Id", 
      "UserName", purchases.ApplicationUserId);
        return View(purchases);
    }

    // POST: Purchases/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]
    public ActionResult Edit([Bind(Include = 
  "PurchaseId,Name,Points,TotalPoints,ApplicationUserId")] Purchases 
  purchases)
    {
        if (ModelState.IsValid)
        {


            db.Entry(purchases).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        ViewBag.ApplicationUserId = new SelectList(db.Users, "Id", 
      "UserName", purchases.ApplicationUserId);
        return View(purchases);
    }

    // GET: Purchases/Delete/5
    public ActionResult Delete(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        Purchases purchases = db.Purchases.Find(id);
        if (purchases == null)
        {
            return HttpNotFound();
        }
        return View(purchases);
    }

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

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

}

现在,您可以在创建新购买时从下拉列表中选择用户。这是创建视图。

        <div class="col-12 backgroundImg navbarSpace scrollBar">
  <div class="formBackground col-12">
    <h2 class="formHeader">Edit Puchase</h2>
    <hr />
    @using (Html.BeginForm())
    {
        @Html.AntiForgeryToken()

        <div class="form-horizontal">


            @Html.ValidationSummary(true, "", new { @class = "text-danger" 
     })
            @Html.HiddenFor(model => model.PurchaseId)
            @Html.HiddenFor(model => model.TotalPoints)

            <div class="col-12">
                @Html.LabelFor(model => model.Name, htmlAttributes: new { 
    @class = "formText col-12" })
                <div class="col-12">
                    @Html.EditorFor(model => model.Name, new { 
     htmlAttributes = new { @class = "col-12" } })
                    @Html.ValidationMessageFor(model => model.Name, "", new 
   { @class = "text-danger" })
                </div>
            </div>

            <div class="col-12">
                @Html.LabelFor(model => model.Points, htmlAttributes: new { 
     @class = "formText col-12" })
                <div class="col-12">
                    @Html.EditorFor(model => model.Points, new { 
    htmlAttributes = new { @class = "col-12" } })
                    @Html.ValidationMessageFor(model => model.Points, "", 
    new { @class = "text-danger" })
                </div>
            </div>

            @*<div class="col-12">
                    @Html.LabelFor(model => model.TotalPoints, 
     htmlAttributes: new { @class = "formText col-12" })
                    <div class="col-12">
                        @Html.EditorFor(model => model.TotalPoints, new { 
  htmlAttributes = new { @class = "col-12" } })
                        @Html.ValidationMessageFor(model => 
  model.TotalPoints, "", new { @class = "text-danger" })
                    </div>
                </div>*@

   <div class="col-12">@Html.LabelFor(model => model.ApplicationUserId, 
   "Users", htmlAttributes: new { @class = "formText col-12" })
    <div class="col-12"> @Html.DropDownList("Users", null, htmlAttributes: 
    new { @class = "col-12" })
     @Html.ValidationMessageFor(model => model.ApplicationUserId, "", new { 
          @class = "text-danger" })
                </div>
            </div>

     <div class="col-12">
         <div class="col-md-offset-2 col-md-10">
           <input type="submit" value="Save" class="btn btn-default" />
                </div>
            </div>
        </div>
    }

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

这会创建一个显示其用户名的用户下拉列表。当我选择一个用户并点击保存时,我得到一个错误说 没有类型&#39; IEnumerable&#39;的ViewData项目。这有关键&#39; Id&#39;。

2 个答案:

答案 0 :(得分:0)

传递给此方法的'Id'是否为null?

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult CreatePurchase([Bind(Include = "PurchaseId,Name,Points,Id")] Purchases purchases)
    {
        if (ModelState.IsValid)
        {
            db.Purchases.Add(purchases);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(purchases);
    }

如果为null,则应在您发布的表单中包含userID(作为隐藏字段)。然后(一旦在数据库中填充了userID),您应该只能获得与userID相关联的购买,执行以下操作:

 var userDetails = db.Purchases.Where(x=>x.ApplicationUserId == ID).ToList();

答案 1 :(得分:0)

您遇到的问题是“创建新购买”&#39; action没有传递用户ID,它当前是:

@Html.ActionLink("Create New", "CreatePurchase")

然而需要传递一个id:

@Html.ActionLink("Create New", "CreatePurchase", new { 
    id = Model.Id})

然而,这假设ID已经传递到该页面的模型中的购​​买索引视图,这可能不是这种情况,但我不能告诉我,因为我无法看到您的购买索引操作。为您传递它的最简单方法是通过一个视图包,但如果您打算认真使用它,我建议不要将它用于您的网站。在视图中处理数据的正确方法是使用viewmodels。有很多可用的教程,例如https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions/mvc-music-store/mvc-music-store-part-3

使用CRUD实现,您可以使用弱类型的视图包将id传递给页面。您的购买索引操作应如下所示:

public ActionResult Index(string id)
        {
//this checks to see if an id has been passed to the action
if (id != null){
//this gets all purchases for a certain individual
var purchases = db.purchases.Where(i => i.ApplicationUserId == id).ToList()

//this gets the user id passed to the action and sticks it in a viewbag you can retrieve later on the page
ViewBag.UserID == id;

//returns the view with the list above
return View(purchases);
}
else{
//no id was passed to the action so the list is for all purchases
var purchases = db.purchases.ToList();

return View(purchases);
}

}

现在,在您的视图中,您需要修改创建新的购买操作以包含viewbag项目:

@Html.ActionLink("Create New", "CreatePurchase", new { 
    id = ViewBag.UserID})

更改您的创建购买操作以接受您传递的用户ID:

 public ActionResult CreatePurchase(string id)
{
//puts the id in a viewbag to again be used by the view
ViewBag.UserID == id;

    return View();
}

然后在您的创建购买视图中,您需要将视图包项目传递到模型中,您可以通过在表单内的某个位置隐藏字段来执行此操作:

@Html.Hidden("id", (string)ViewBag.UserID)

我将viewbag转换为字符串,因为假设您正在使用ASP NET标识,用户ID是一个字符串而ViewBag是一个动态对象,因此需要先将其转换为字符串,然后才能将其放入model.id空间有效。然后,这会将用户ID传递给后期操作,并且将创建特定于id的购买。

请记住,这是一种可怕的方式,这是一种可靠的方式,默认的CRUD东西虽然方便,但对于生产来说并不是很好,因为你直接访问模型而你需要使用弱类型的ViewBags来传输数据。它容易出错并且不安全。