我对 ASP.NET 还比较陌生,所以请耐心等待。
我正在尝试使用 MVC 5 和具有 Code-First 的 Entity Framework 为慈善机构编写一个简单的拍卖网站。
我已经创建了一个项目模型和 Controller 。 Item 模型包含标题、描述、起始出价、当前出价、出价数量、最高出价者等字段。
public class Item
{
public int ID { get; set; }
public string Code { get; set; }
public string Title { get; set; }
public string Description { get; set; }
[DisplayName("Starting Bid")] public int StartingBid { get; set; }
public int Increment {get; set;}
public int Bids { get; set; }
[DisplayName("Current Bid")] public int CurrentBid { get; set; }
public string HighBidder { get; set; }
public int CurrentOrStartingBid
{ // The price that is displayed next to an item
get
{
return Bids > 0 ? CurrentBid : StartingBid;
}
}
public int NextBid
{ // The minimum amount that is valid for a new bid
get
{
return Bids > 0 ? CurrentBid + Increment : StartingBid;
}
}
}
(我在上面的代码中尝试做的是添加这些属性 CurrentOrStartingBid 和 NextBid,它们不打算成为数据库记录的一部分,它们只是衍生属性而不是数据库中的列。所以希望拥有这些因为只读属性会这样做...)
我现在正在查看该项目的详细信息。这显示了商品描述,并且还具有用于出价的表单控件,类似于您在 eBay 上看到的内容。我的问题是如何正确连接出价按钮的逻辑。
我认为在 View 中我应该使用带有提交按钮的 HTML 表单来进行投标。当按下按钮时,这会执行一个 HTTP post,并允许我在 Item Controller 中编写一个当时被调用的方法。
所以我在 View 中的 Razor 代码当前如下所示:
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<div class="form-group">
<div class="input-group">
<span class="input-group-addon">£</span>
<input type="number" class="form-control" value="@Model.NextBid" id="CurrentBid" name="CurrentBid"/>
</div>
<br />
<button type="submit" class="btn btn-primary btn-lg">Place bid</button>
</div>
}
使用此代码允许我编写具有此签名的 Controller 方法:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Bid([Bind(Include = "ID,CurrentBid")] Item item)
到目前为止这种方法有效。但请注意,在服务器端验证之前,我必须传递项目的 CurrentBid 字段中已出价的金额。这对我来说感觉不太对劲。有没有一种方法可以编写该方法,使其只需要这样的签名?
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Bid(int itemID, int bidAmount)
也许有办法用查询字符串或其他东西来做到这一点?
无论如何,一旦进入该方法,事情又显得有点奇怪了。为了防止过度发布,item
变量中唯一有效的字段是 ID
和 CurrentBid
。因此,我然后在 DbContext 中进行查找,找到与该 ID 对应的实际项目并更新它:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Bid([Bind(Include = "ID,CurrentBid")] Item item)
{
if (ModelState.IsValid)
{
Item i2 = db.Items.Find(item.ID);
if (item.CurrentBid >= i2.NextBid)
{
i2.Bids++;
i2.CurrentBid = item.CurrentBid;
i2.HighBidder = HttpContext.User.Identity.Name;
db.Entry(i2).State = EntityState.Modified;
db.SaveChanges();
}
return View(i2);
}
return RedirectToAction("Auction");
}
这似乎有效。但感觉不对。我认为我在这里遗漏了一些重要的概念/模式。如果任何有经验的 MVC 人员能够勾勒出如何为这个简单的按钮连接客户端/服务器逻辑,那就太好了。 (您也将帮助一项公益事业!)
最佳答案
Is there a way of writing the method so it just takes a signature like this?
[HttpPost] [ValidateAntiForgeryToken]
public ActionResult Bid(int itemID, int bidAmount)
当然有办法,假设你有一个像这样的简单模型 -
public class Item
{
public int ID { get; set; }
public int NextBib { get; set; }
public int CurrentBid { get; set; }
public string Description { get; set; }
}
然后您的操作将创建一个项目并发送到 View ,如下所示 -
public ActionResult BidForm()
{
Item i = new Item();
i.ID = 100;
i.CurrentBid = 10;
return View(i);
}
您的观点如下 -
@model MVC.Controllers.Item
@{
ViewBag.Title = "BidForm";
}
<h2>BidForm</h2>
@using (Html.BeginForm("Bid", "sample", FormMethod.Post))
{
@Html.AntiForgeryToken()
<input type="hidden" name="itemId" value="@Model.ID" />
<input type="number" class="form-control" value="@Model.NextBib" id="CurrentBid" name="bidAmount" />
<input type="submit" value="Create" />
}
您的 NextBid 操作将是 -
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Bid(int itemID, int bidAmount)
{
return View();
}
如您所见,我们有一个名称= itemID
的隐藏字段和一个名称= `bidAmount 的输入类型=数字字段。这些被映射到操作的参数,如下所示 -
您可以考虑的一些建议 -
- 您可以使用 Ajax.BeginForm() 来代替常规的 HTml.BeginForm(),以提供更直观的用户体验。或者,您也可以使用 JQuery POST 操作。
- 为了防止过度发布,您需要为特定事件(例如提高出价、展示产品等)创建特定的 ViewModel。并且您只为所需事件发布所需的 viewModel,这样就可以防止表单过度发布。
关于asp.net - 如何使用 ASP.Net/MVC 5/EF 编写拍卖网站代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21904200/