这是想法。 当管理员登录时,他们可以提取所有用户的列表。它将像往常一样提供编辑、详细信息、删除选项,但我添加了购买链接,如下所示:
@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
当您单击"购买"链接时,它会将您带到"购买索引"页面,如下所示: 购买清单
@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>
它给出了购买列表并给出了总积分,这就是我没有包含详细信息页面的原因。 一切正常,除了购买不映射到特定用户的事实。 如果我创建一个新用户并单击"购买",它会显示所有购买的列表,而不仅仅是特定于该用户的购买。如何让购买项目映射到特定用户?
我创建了一个如下所示的购买类:
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; }
}
我的应用程序用户类如下所示:
public class ApplicationUser : IdentityUser
{
[Display(Name ="Favorite Strain")]
[DataType(DataType.Text)]
public string FavStrain { get; set; }
public virtual List<Purchases> Purchase { get; set; }
到目前为止,数据库正在将购买类的外键注册到 ApplicationUser 类,就像它应该的那样。
我可以创建一个新的购买并将它们显示在列表中,并且所有 Crud 操作都运行良好。 问题是当我创建新的购买时,它不包含数据库中的应用程序用户 ID,它返回一个 Null。
空数据库
我很确定问题出在我的控制器上。 我已经尝试了几乎所有方法,所以我不想包括失败的尝试,所以这里是控制器,因为它们现在正在工作。
我不需要包含编辑或详细信息,因为我不会为用户提供访问权限。
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());
}
这是我关于堆栈溢出的第一个问题,所以如果有什么不对劲,请原谅我。
**************************************更新************************************
这是我的PurchaseIndexController。 现在,这将仅返回与购买关联的用户。 但是,它始终为 0,因为没有用户 ID。 如果我尝试使用 int?类型还是指导?它给出一个错误。 不能将 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);
}
这是创建购买视图
@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);
}
这是现在的操作链接。
<div class="col-12 formHeaderSmall">@Html.ActionLink("My
Purchases/Points", "WeedPoints", "Manage")</div>
*********************************更新****************************************
下面是带有视图包参考的控制器。 创建购买视图有我刚刚取消注释的 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);
}
******
这是整个新控制器。
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>
这将创建一个显示其用户名的用户下拉列表。 当我选择一个用户并点击保存时,我收到一条错误消息,指出 没有类型为"IEnumerable"的 ViewData 项具有键"Id"。
传递给此方法的"Id"是否为空?
[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,则应在要发布的表单中包含用户 ID(作为隐藏字段)。然后(一旦用户 ID 填充到数据库中),您应该只能获得与用户 ID 关联的购买,执行以下操作:
var userDetails = db.Purchases.Where(x=>x.ApplicationUserId == ID).ToList();
您遇到的问题是"创建新购买"操作没有传递用户 ID,它目前是:
@Html.ActionLink("Create New", "CreatePurchase")
而传递 id 需要这样:
@Html.ActionLink("Create New", "CreatePurchase", new {
id = Model.Id})
但是,这假设 id 已传递到该页面模型中的购买索引视图,情况可能并非如此,但我无法判断,因为我看不到您的购买索引操作。为您传递它的最简单方法是通过 viewbag,但是如果您打算认真使用它,我不建议您将其用于您的网站。 跨视图处理数据的正确方法是使用视图模型。 有很多可用的教程,例如 https://learn.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();
}
然后在创建购买视图时,您需要将 viewbag 项目传递到模型中,您可以通过在窗体中的某个位置放置一个隐藏字段来执行此操作:
@Html.Hidden("id", (string)ViewBag.UserID)
我正在将 viewbag 转换为字符串,因为假设您使用的是 ASP NET 标识,则用户 ID 是一个字符串,而 ViewBag 是一个动态对象,因此需要将其转换为字符串,然后才能有效地将其放入 model.id 空间。 然后,这会将用户 ID 传递给发布操作,并将创建特定于该 ID 的购买。
请记住,这是一种糟糕的方式,默认的 CRUD 内容虽然方便,但对于生产来说并不是那么好,因为您直接访问模型,并且需要使用弱类型的 ViewBag 来传输数据。 它容易出错且不安全。