【问题标题】:ASP.NET-MVC - Website running total function not workingASP.NET-MVC - 网站运行总功能不起作用
【发布时间】:2021-06-03 08:51:05
【问题描述】:

作为大学作业的一部分,尝试创建一个计算我网站的卡路里的运行总计。一切都完成了,除了这一部分,它一直让我绊倒。从理论上讲,它应该接受一个值并将其添加到运行总计中并显示该总计,但我认为每次按下按钮来计算它时,它都会运行一个我用来计算它的模型的新实例。此操作有 3 个文件相互交互

  1. CalorieCount.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;
            }
        }
    }
    
    
  2. CalorieCounter.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>
}
  1. 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
        }

如果有人能发现此问题并提出修复建议,将非常感谢。

【问题讨论】:

    标签: c# html asp.net-mvc


    【解决方案1】:

    这里存在一些基本的误解。 ASP.NET MVC 本质上是一个“无状态”系统。因此,当您从浏览器向服务器发出请求时,服务器上的一切都是全新的、未初始化的内存。它正在“更新”所有用于处理请求和发送响应的对象。

    因此,如果您想在请求之间保留一些数据,您有几个选择:

    1. 确保您需要的所有数据每次都是“往返”的。这通常意味着您需要在页面中隐藏 &lt;input /&gt; 字段以在表单内包含该数据。只要这些输入设置正确(我建议使用 HtmlHelper,即Html.HiddenFor&lt;T&gt;()),框架就会匹配该值并在您的 POST 处理程序中设置模型对象的该属性。
    2. 将数据存储在服务器上的数据库中。每个请求都会加载当前数据,将新数据添加到其中并保存,然后在页面上显示它需要的任何内容。

    更新

    根据您的示例创建一个工作 MVC 站点并复制问题后,我进行了一些研究,发现 HtmlHelpers 在查看传递给视图的模型之前先查看 ModelState。这就是为什么值永远不会更新的原因。我还注意到有一个验证错误,因为 int TotalCalorieCount 暗示需要一个值,并且大概 0 还不够好。

    这就是我为使其正常工作所做的工作:

    1. 在视图中的提交按钮之前添加@Html.HiddenFor(m =&gt; m.TotalCalorieCount)
    2. CalorieCount.TotalCalorieCount int? 改为 int(删除了 DataAnnotations 隐含的要求。
    3. HomeControllerif (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 设为可为空的 int,则可以在 GET 中将模型返回到您的视图中,如下所示:

    // Loads Calorie Count Page
    // Sets up empty form
    [HttpGet]
    public ActionResult CalorieCounter()
    {
        return View(new CalorieCount() { TotalCalorieCount = 0 });
    }
    

    这也解决了这部分问题。

    【讨论】:

    • 谢谢,你认为你可以展示一个简单的例子来说明这些隐藏的输入字段在我的代码中可能是什么样子,只是不太确定它是如何工作的,但感谢你的建议。
    • 它实际上与您在代码中为 EditorFor 所做的相同。也许就在提交按钮附近(当然是在表单内部,否则不会提交),输入类似@Html.HiddenFor(m =&gt; m.TotalCalorieCount) 的内容。如果你使用EditorFor,ASP.NET MVC 会选择一个合适的可见输入控件,但HiddenFor 会在你的 html 中专门创建一个&lt;input type="hidden" ... /&gt;
    • 不幸的是,这没有用,现在输出总是 0,我想我应该能够为它创建一个数据库,所以希望它可以工作
    • 您是否检查过 HTML 中的内容以及属性和输入控件的名称是否匹配等? HTML表单中的隐藏输入是否会被提交?
    • 我进行了更新。我基本上复制了这种情况并找到了解决方法,所以我更新了我的答案以反映这一点。
    【解决方案2】:

    最终通过为 CalorieCount 模型创建一个 DbSet 来解决此问题,并将每次计算都存储在该数据库中。控制器将遍历这个数据库,直到找到最大的 id,表明它是最新的计算,它将 TotalCalorieCount 存储在局部变量中,并添加 CalorieIntake 并将局部变量发送到模型,以便它可以在网页上显示。

    【讨论】:

    • 那是不必要的。查看我对答案的更新。
    猜你喜欢
    • 2013-09-07
    • 1970-01-01
    • 2020-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-23
    • 1970-01-01
    相关资源
    最近更新 更多