【问题标题】:MVC3 : Overriding the Model values in HTTPPost action methodMVC3:在 HTTPPost 操作方法中覆盖模型值
【发布时间】:2014-03-31 19:47:33
【问题描述】:

我正在尝试学习 MVC3。我已使用 TextBoxFor HTML 辅助控件将值保留在多个回发中。

令人惊讶的是,该值会持续存在,但不会反映在视图中。

我的模型类看起来像这样:

   public class FileViewModel
    {
        public string FileName { get; set; }
        public string ValidationMsg { get; set; }

    }

控制器中的我的 Actions 方法如下所示:

  public ActionResult DemoFormElements()
    {

    return View();
    }

[HttpPost]
public ActionResult DemoFormElements(FileViewModel fVM)
{
    fVM.FileName = "Overridden Text" + fVM.FileName ;

    return View(fVM);
}

我的视图如下所示:

@using (@Html.BeginForm())
{
    if (Model != null)
    {
        @Html.LabelFor(b => b.FileName)
        @Html.TextBoxFor(n => n.FileName, Model.FileName)
    }
    else
    {
        @Html.LabelFor(b => b.FileName)
        @Html.TextBoxFor(n => n.FileName)
    }        

    <input type="submit" id="SubmitBtn" value="Ok" />
}

当我通过单击“确定”按钮回帖时,我能够获取我在 文本框,但在控制器中,我试图将该值附加到“Hi”并期望在我的视图中附加值,这没有发生......

我看到控件的值保持不变(无论我输入了什么),但没有改变:( 如果它是预期的行为或者我在这里做错了什么,请帮助我提供一些线索?

【问题讨论】:

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


    【解决方案1】:

    这有几个问题。您不能在回发期间覆盖模型中的值,因为 MVC 将覆盖它并保留旧值,以便在出现错误时重新显示它们。一般来说,您也不应该从 POST 处理程序返回视图,您应该使用 PRG(Post - Redirect - Get)模式。这样做是为了如果用户在浏览器中单击刷新,它不会再次发布。所以,说了这么多,我将控制器更改如下:

    public ActionResult DemoFormElements()
    {
        var viewModel = new FileViewModel();
    
        if( TempData.ContainsKey( "UpdatedFilename" )
        {
            viewModel = TempData["UpdatedFilename"];
        }
    
        return View( viewModel );
    }
    
    [HttpPost]
    public ActionResult DemoFormElements(FileViewModel fVM)
    {
        TempData["UpdatedFilename"] = "Overridden Text" + fVM.FileName;
    
        return RedirectToAction( "DemoFormElements" );
    }
    

    这也将简化您的视图,因为您不必对模型进行空值检查,您将始终拥有一个模型。

    @using (@Html.BeginForm())
    {
        @Html.LabelFor(model => model.FileName)
        @Html.TextBoxFor(model => model.FileName)
    
        <input type="submit" id="SubmitBtn" value="Ok" />
    }
    

    【讨论】:

    • 另外,如果您要添加新文本,最好防止在多次发布增强文本的情况下重复连接(即,如果您不这样做,您可能会得到“覆盖文本覆盖文本...")
    • 当然,这是原始代码的另一个问题。即使 OP 已经采用了这种方法(可以通过弄乱 ModelState 来实现),用户敲击 F5 键也会导致重复连接。因为 TempData 只能在一个重定向中幸存下来,所以这也解决了这个问题。
    【解决方案2】:

    您的问题的直接解决方案可能是:

    1. 在控制器 Post 方法中,使用 ModelState.Remove("[Mode's Property Name]") 在控制器为其分配新值之前。这里应该是:ModelState.Remove("FileName");

    2. 或使用 ModelState.Clear():这会强制页面忘记所有先前的值并清除所有先前的条目。

    3. 或在视图页面上,将特定模型属性的 Html.TextBoxFor() 更改为 Html.TextBox()。

    4. 或者按照上面 Craig 的建议使用 PRG 模式:(Post-Redirect-Get 模式)。

    从这些替代解决方案中选择一个适合您需要的解决方案。

    【讨论】:

    • 太好了,它开始正常工作了...感谢提供所有可能的灵魂 :)
    【解决方案3】:

    我会为 get 操作返回一个 viewModel

        public ActionResult Index()
        {
            return View(new FileViewModel());
        }
    

    我会简化这个视图

    <span>@Model.FileName</span>
    @using (@Html.BeginForm())
    {
        @Html.LabelFor(m => m.FileName)
        @Html.TextBoxFor(m => m.FileName)
        <input type="submit" id="SubmitBtn" value="Ok" />
    }
    

    请同时阅读 MVC2 TextBoxFor value not updating after submit?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-25
      • 2014-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-14
      • 2021-12-14
      相关资源
      最近更新 更多