【问题标题】:ASP.NET MVC Form - What is the proper way to return to a view with the previous form values?ASP.NET MVC 表单 - 返回到具有先前表单值的视图的正确方法是什么?
【发布时间】:2016-10-28 05:24:39
【问题描述】:

我有一个任务是实现 WCF 服务并从任何类型的客户端调用它。我已经有一些控制台、winform、WPF 应用程序的经验,所以我想借此机会学习 ASP.NET MVC。

我知道我还没有正确实现它的“M”部分,但我想知道在表单上处理数据以更新显示结果的正确方法是什么,而不是我所拥有的(工作)到目前为止:

查看:

@using (Html.BeginForm("UseSimpleMathClient", "Home"))
{
    <div style="width:450px">
        <table style="width:100%">
            <tr><td><h4>@Html.Label("First number", new { @for = "num1" })</h4></td> <td> @Html.TextBox("num1", ViewData["num1"])</td></tr>
            <tr><td><h4>@Html.Label("Second number", new { @for = "num2" })</h4></td> <td> @Html.TextBox("num2", ViewData["num2"])</td></tr>
            <tr>
                <td colspan="2">
                    <h2 style="text-align:center">
                        <input type="submit" name="operation" value="+" />
                        <input type="submit" name="operation" value="-" />
                        <input type="submit" name="operation" value="*" />
                        <input type="submit" name="operation" value="÷" />
                    </h2>
                </td>
            </tr>
            <tr>
                <td colspan="2"><b>@Html.Label("Result")</b> &nbsp; @Html.TextBox("result", ViewData["result"], new {disabled = "disabled", style="min-width:80%;text-align:center" })</td>
            </tr>
            </table>
    </div>
}

控制器:

      public ActionResult USeSimpleMathClient(char operation)
    {
        float num1, num2;
        float? result = null;

        if (!float.TryParse(Request.Form[0], out num1) || !float.TryParse(Request.Form[1], out num2))
        {
            ViewData["result"] = "Please enter valid numbers before selecting an operation.";
        }
        else
        {
            switch (operation)
            {
                case '+':
                    result = mathClient.Add(num1, num2);
                    break;
                case '-':
                    result = mathClient.Subtract(num1, num2);
                    break;
                case '*':
                    result = mathClient.Multiply(num1, num2);
                    break;
                case '÷':
                    if (num2 != 0)
                        result = mathClient.Divide(num1, num2);
                    break;
                default:
                    break;
            }

            ViewData["result"] = result != null ? String.Format("{0} {1} {2} = {3}", num1, operation, num2, result) : "You can't divide by zero!";
        }

        ViewData["num1"] = Request.Form[0];
        ViewData["num2"] = Request.Form[1];
        return View("Index");
    }

【问题讨论】:

  • 嗨@Dinerdo,你提到你以前使用过WPF。您熟悉使用 ViewModel 吗?
  • 不要使用 Request.Form 来获取值,而是按照 Geoff James 的建议创建一个 ViewModel。然后,您在控制器操作中使用该模型来获取所有值。因此,不要传入“char operation”,而是传入“SimpleMathVM model”。您只需使用所需的任何表单值创建 SimpleMathVM 类(确保表单值的名称与模型属性名称匹配)。如果你想用以前的表单值返回表单,那么只需将视图模型传回视图。所以你的最后一行是:return View("Index", ViewModel).
  • @firecape:为什么不让它成为答案而不是评论?
  • @GeoffJames 是的,在一定程度上。我在 Xamarin 中对此有更多经验,但我相信这几乎都是一样的。 @firecape 谢谢。我同意这可以作为答案发布。

标签: c# html asp.net asp.net-mvc razor


【解决方案1】:

好的,所以我使用了您的代码并使用视图模型快速实现了您的控制器操作。请注意,我在一些视图模型属性的顶部有数据注释属性,这样我们就不必手动验证 num1 和 num2 是否实际上是数字。

视图模型:

public class SimpleMathVM
{
    [Required(ErrorMessage = "Please enter valid numbers before selecting an operation.")]
    [Display(Name = "First number")]
    public float Num1 { get; set; }


    [Required(ErrorMessage = "Please enter valid numbers before selecting an operation.")]
    [Display(Name = "Second number")]
    public float Num2 { get; set; }

    public string Result { get; set; }

    public char Operation { get; set; }

}

控制器(GET 和 POST 操作):

    public ActionResult USeSimpleMathClient()
    {
        return View("Index");
    }


    [HttpPost]
    public ActionResult USeSimpleMathClient(SimpleMathVM viewModel)
    {

    //I moved the checking for zero up here, that way you could immediately return the view. 
    //I kept your version where you populate the Result textbox with the error message,
    //but really you should probably only add the error message to the ModelState.

        if (viewModel.Num2 == 0 && viewModel.Operation == '÷')
        {
            ModelState.AddModelError(string.Empty, "You can't divide by zero!");
            viewModel.Result = "You can't divide by zero!";

        //You can pick which one of the above two lines work better for you.
        //Usually adding error messages to the ModelState is the way to go.
        }

        if (!ModelState.IsValid)
        {
            return View("Index", viewModel);
        }

        switch (viewModel.Operation)
        {
            case '+':
                viewModel.Result = mathClient.Add(viewModel.Num1, viewModel.Num2).ToString();
                break;
            case '-':
                viewModel.Result = mathClient.Subtract(viewModel.Num1, viewModel.Num2).ToString();
                break;
            case '*':
                viewModel.Result = mathClient.Multiply(viewModel.Num1, viewModel.Num2).ToString();
                break;
            case '÷':
                viewModel.Result = mathClient.Divide(viewModel.Num1, viewModel.Num2).ToString();
                break;
            default:
                break;
        }

        return View("Index", viewModel);
    }

查看:

//must bring in the View Model so you can access the MVC lambda helpers below
@model WebApplication11.Models.SimpleMathVM

@using (Html.BeginForm("UseSimpleMathClient", "Home"))
{
//You can use ValidationSummary to display object level model errors,
//such as the division by zero error we directly added to the ModelState
//in the controller
@Html.ValidationSummary(true);

<style type="text/css">
    .navbar {
        display: none !important;
    }

    body {
        padding: 0px 0px 0px 0px !important;
    }
</style>
<div style="width:450px">
    <table style="width:100%">
        <tr><td><h4>@Html.LabelFor(x => x.Num1)</h4></td> <td> @Html.TextBoxFor(x => x.Num1)</td><td> @Html.ValidationMessageFor(x => x.Num1)</td></tr>
        <tr><td><h4>@Html.LabelFor(x => x.Num2)</h4></td> <td> @Html.TextBoxFor(x => x.Num2)</td><td> @Html.ValidationMessageFor(x => x.Num2)</td></tr>
        <tr>
            <td colspan="2">
                <h2 style="text-align:center">
                    <input type="submit" name="operation" value="+" />
                    <input type="submit" name="operation" value="-" />
                    <input type="submit" name="operation" value="*" />
                    <input type="submit" name="operation" value="÷" />
                </h2>
            </td>
        </tr>
        <tr>
            <td colspan="2">
                <b>@Html.LabelFor(x => x.Result)</b> &nbsp; @Html.TextBoxFor(x => x.Result, new { disabled = "disabled", style = "min-width:80%;text-align:center" })
                @Html.ValidationMessageFor(x => x.Result)
            </td>
        </tr>
    </table>
</div>
}

请注意,现在您的表单字段可以强类型化到表单中的视图模型。 ASP.NET MVC 的模型绑定系统简单地将您发布的表单字段填充到您的视图模型实例中的 post 控制器操作。您甚至不必进行手动匹配字段的工作。而且您也不必再使用 Viewbag。

还要注意,在后控制器操作中,我检查了第二个数字是否为零,将错误直接添加到 ModelState 和结果视图中,因此您会看到错误消息在看法。您最初将错误消息放在结果视图中(所以我保留了它),但您可能会考虑仅通过 ModelState 对象添加任何错误处理消息,而不是填充结果文本框。您还可以在 WCF 服务中检查除以零。另一种选择是创建自定义数据注释以检查除以零。希望这会有所帮助。

【讨论】:

  • 非常感谢您的解释和详细程度。这正是我一直在寻找的东西。
猜你喜欢
  • 1970-01-01
  • 2014-08-29
  • 1970-01-01
  • 2011-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-01
相关资源
最近更新 更多