试图创建一个跑步总数,作为大学作业的一部分,为我的网站计算卡路里。一切都结束了,除了这一部分,它一直让我绊倒。理论上,它应该取一个值,并将其添加到一个正在运行的总数中,然后显示这个总数,但我认为每次按下按钮计算这个值时,它都会运行我用来计算这个值的模型的一个新实例。操作有3个文件相互作用
-
卡路里计数.cs-包含数据和计算的模型
using System.Collections.Generic; using System.Linq; using System.Web; using System.ComponentModel.DataAnnotations; namespace BlairMackenzie_CalorieCount.Models { public class CalorieCount { // Stores user input for calculating calorie count [Required] [Display(Name = "Calories Consumed")] public int CalorieIntake { get; set; } // Stores the running total [Display(Name = "Total Calories Consumed Today")] public int TotalCalorieCount { get; set; } // This method calculates total calorie count public void CalculateTotalCalorieCount() { // Add CalorieIntake to TotalCalorieCount TotalCalorieCount += CalorieIntake; } } }
-
卡路里计数器cshtml-向用户显示所有这些并获取输入的网页
@{
ViewBag.Title = "CalorieCounter";
}
<h2>Calorie Counter</h2>
<br />
<hr />
@using (Html.BeginForm())
{
<div class="table-responsive">
<table class="table table-lg">
<tr>
<!-- Displays label and input box for CalorieIntake -->
<td>@Html.LabelFor(m => m.CalorieIntake)</td>
<td>@Html.EditorFor(m => m.CalorieIntake)</td>
</tr>
<tr>
<!-- Displays label and display for TotalCalorieCount -->
<td>@Html.LabelFor(m => m.TotalCalorieCount)</td>
<td>@Html.DisplayFor(m => m.TotalCalorieCount)</td>
</tr>
<tr>
<td></td>
<td>
<!-- Submit button triggers calculation -->
<input type="submit" value="Calculate New Total Calories" class="btn btn-lg btn-success" />
</td>
</tr>
</table>
</div>
}
- HomeController.cs-处理加载页面和调用模型以处理计算
// Loads Calorie Count Page
// Sets up empty form
[HttpGet]
public ActionResult CalorieCounter()
{
return View();
}
// This action is called when the user clicks the submit button
// The completed form is sent to the back end
[HttpPost]
public ActionResult CalorieCounter(CalorieCount model)
{
if (ModelState.IsValid)
{
model.CalculateTotalCalorieCount();
}
return View(model); // Return the model to the view with all values calculated
}
如果有人能发现这个问题并提出解决方案,那将非常感谢。
这里存在一些根本性的误解。ASP。NET MVC本质上是一个";"无国籍";系统因此,当您从浏览器向服务器发出请求时,服务器上的所有都是全新的、未初始化的内存。它是"newing up";用于处理请求和发送响应的所有对象。
因此,如果您有一点数据想要在请求之间保持不变,那么您有两个选项:
- 确保您需要的所有数据都是";"往返跳闸";每次。这通常意味着你需要在页面中隐藏
<input />
字段来包含表单中的数据。只要这些输入设置正确(我建议使用HtmlHelper,即Html.HiddenFor<T>()
(,框架就会匹配值,并在POST处理程序中设置模型对象的属性 - 将数据存储在服务器上的数据库中。每个请求加载当前数据,向其中添加新的数量,并保存它,然后在页面上显示它需要的任何内容
更新
在根据您的示例创建了一个可工作的MVC站点并复制了该问题之后,我做了一些研究,发现HtmlHelpers在查看传递给视图的模型之前先查看ModelState。这就是该值从不更新的原因。我还注意到有一个验证错误,因为int TotalCalorieCount
暗示需要一个值,可能0还不够好。
以下是我为使其发挥作用所做的:
- 在视图中的提交按钮之前立即添加
@Html.HiddenFor(m => m.TotalCalorieCount)
- 将
CalorieCount.TotalCalorieCount
设为int?
,而不是int
(这删除了要存在的DataAnnotations隐含要求( - 在
HomeController
中的if (ModelState.IsValid)
块内立即添加了对ModelState.Clear()
的调用
它现在像你对我的期望一样工作。
HomeController.cs
// Loads Calorie Count Page
// Sets up empty form
[HttpGet]
public ActionResult CalorieCounter()
{
return View();
}
// This action is called when the user clicks the submit button
// The completed form is sent to the back end
[HttpPost]
public ActionResult CalorieCounter(CalorieCount model)
{
if (ModelState.IsValid)
{
ModelState.Clear();
model.CalculateTotalCalorieCount();
}
return View(model); // Return the model to the view with all values calculated
}
卡路里计数.cs
using System.ComponentModel.DataAnnotations;
namespace WebApplication1.Models
{
public class CalorieCount
{
// Stores user input for calculating calorie count
[Required]
[Display(Name = "Calories Consumed")]
public int CalorieIntake { get; set; }
// Stores the running total
[Display(Name = "Total Calories Consumed Today")]
public int? TotalCalorieCount { get; set; }
// This method calculates total calorie count
public void CalculateTotalCalorieCount()
{
// Add CalorieIntake to TotalCalorieCount
TotalCalorieCount = (TotalCalorieCount ?? 0) + CalorieIntake;
}
}
}
卡路里计数器cshtml
@model CalorieCount
@{
ViewBag.Title = "CalorieCounter";
}
<h2>Calorie Counter</h2>
<br />
<hr />
@using (Html.BeginForm())
{
<div class="table-responsive">
<table class="table table-lg">
<tr>
<!-- Displays label and input box for CalorieIntake -->
<td>@Html.LabelFor(m => m.CalorieIntake)</td>
<td>@Html.EditorFor(m => m.CalorieIntake)</td>
</tr>
<tr>
<!-- Displays label and display for TotalCalorieCount -->
<td>@Html.LabelFor(m => m.TotalCalorieCount)</td>
<td>@Html.DisplayFor(m => m.TotalCalorieCount)</td>
</tr>
<tr>
<td></td>
<td>
<!-- Submit button triggers calculation -->
@Html.HiddenFor(m => m.TotalCalorieCount)
<input type="submit" value="Calculate New Total Calories" class="btn btn-lg btn-success"/>
</td>
</tr>
</table>
</div>
}
最后一件事。如果你不想让CalorieCount.TotalCalorieCount
成为一个可以为null的int,你可以在GET中向你的视图返回一个模型,就像这样:
// Loads Calorie Count Page
// Sets up empty form
[HttpGet]
public ActionResult CalorieCounter()
{
return View(new CalorieCount() { TotalCalorieCount = 0 });
}
这也解决了这部分问题。
最终通过为CalorieCount模型创建DbSet来解决此问题,并将每次计算都存储在该数据库中。控制器将循环浏览该数据库,直到找到显示其为最新计算的最大id,并将TotalCalorieCount存储在本地变量中,添加CalorieIntake并将本地变量发送到模型,以便在网页上显示。