为什么忽略在 Begin.Form 中指定的输入

本文关键字:输入 Form Begin 为什么 | 更新日期: 2023-09-27 18:27:23

下面是一个非常简单的MVC三元组,用于尝试这些东西。

除了 View 中new { id = Model.StatusCode }位之外,它似乎有效,它应该获取 Model.StatusCode 的当前值并将其作为参数传递给控制器。它总是传递"200",即状态代码的初始值("Model.StatusCode"的数值(,尽管我在点击提交按钮之前更改了输入字段中的值。如何更改代码以修复它?

我需要将参数作为string id传递给控制器,因为该控制器的操作也用于路由。

public class ErrorModel
{
    [DisplayName("Status Code")]
    public string StatusCode { get; set; }
    public ErrorModel(string statusCode)
    {
        HttpStatusCode code;
        if (! Enum.TryParse(statusCode, out code))
        {
            code = HttpStatusCode.NotFound;
        }
        StatusCode = ((int)code).ToString();
    }
    public ErrorModel(HttpStatusCode statusCode = HttpStatusCode.OK)
    {
        StatusCode = ((int)statusCode).ToString();
    }
}

视图

@using WebApplication1.Models
@model WebApplication1.Models.ExcelModel
@using (Html.BeginForm("StatusCode", "Error", 
                     new { id = Model.StatusCode }, FormMethod.Post, null))
{
    <p>
        <div class="editor-label">
            @Html.LabelFor(model => model.StatusCode)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.StatusCode)
        </div>
        <input type="submit" value="Submit" />
    </p>
}

控制器

public class ErrorController : Controller
{
    static readonly List<HttpStatusCode> ErrorCodes = new List<HttpStatusCode>(){
        HttpStatusCode.Unauthorized, HttpStatusCode.Forbidden, HttpStatusCode.NotFound, HttpStatusCode.InternalServerError};
    public ActionResult StatusCode(string id)
    {
        ViewBag.Message = "";
        if ((id == null) || (ErrorController.AreEqual(HttpStatusCode.OK, id)))
        {
            return View("StatusCode", new ErrorModel(HttpStatusCode.OK));
        }
        foreach (HttpStatusCode errorCode in ErrorCodes)
        {
            if (ErrorController.AreEqual(errorCode, id))
            {
                return View("HttpError", new ErrorModel(errorCode));
            }
        }
        ViewBag.Message = "Exception " + id
            + @" is not supported, see https://msdn.microsoft.com/en-us/library/system.net.httpstatuscode(v=vs.110).aspx for further details";
        return View("HttpError", new ErrorModel(HttpStatusCode.InternalServerError));
    }
    static private bool AreEqual(HttpStatusCode httpCode, string statusCode)
    {
        return (statusCode == ((int)httpCode).ToString());
    }
}

为什么忽略在 Begin.Form 中指定的输入

您使用的重载Html.BeginForm会将路由值追加到表单action属性值。所以你的表单的标记将是这样的

<form action="Error/StatusCode/200">
  <input type="text" name="StatusCode" />
</form>

发布表单时,模型绑定器/路由引擎会将200值映射到 Id 参数,因为它与我们的默认路由配置{controllername}/{actionname}/{id}匹配。这就是您从表单中获取初始值而不是更新值的原因。

你应该做的是使用更改由Html.EditorFor帮助程序方法呈现的输入字段的名称,以匹配操作参数名称(Id(,以便它将覆盖 URL 中的值。为此,您可以使用不同的 EditorFor 方法重载。您可以从BeginForm调用中完全摆脱路由值参数,因为您的表单将发布名称为 Id 的字段。

@using (Html.BeginForm("StatusCode", "Home" ,FormMethod.Post, null))
{
    @Html.EditorFor(model => model.Name,null,"Id")
    <input type="submit" />
}

这将呈现具有名称属性值"Id"的输入字段,当您发布表单时,此字段的当前值将映射到您的操作方法参数。