MVC 4 @HTML.HiddenFor 不会在回发时更新 [重复]

Posted

技术标签:

【中文标题】MVC 4 @HTML.HiddenFor 不会在回发时更新 [重复]【英文标题】:MVC 4 @HTML.HiddenFor are not updating on a postback [duplicate] 【发布时间】:2014-01-06 14:31:48 【问题描述】:

在一系列页面视图上的视图状态存在问题 - 在 Razor 中页面的初始视图中,我使用 html.HiddenFor,如下所示:

    @Html.HiddenFor(x => Model.err)
    @Html.HiddenFor(x => Model.errField)
    @Html.HiddenFor(x => Model.errMessage)
    @Html.HiddenFor(x => Model.IsMove)

这似乎工作正常。我隐藏的输入标签包含正确的值。但是,当我提交表单 [HTTPPost] 并在我的控制器操作中更新模型时......

       model.err = transHelper.err;
       model.errField = transHelper.errField;
       model.errMessage = transHelper.errMessage;
       return View(model);

隐藏字段似乎没有更新,它们包含初始视图中的原始值。但是,当我在这样的同一剃刀视图中的另一个上下文中使用这些字段时......

     @*      
        this seems to not update correctly...

    @Html.HiddenFor(x => Model.err)
    @Html.HiddenFor(x => Model.errField)
    @Html.HiddenFor(x => Model.errMessage)
    @Html.HiddenFor(x => Model.IsMove)

        *@
        <input type="hidden" id="err" value="@Model.err" />
        <input type="hidden" id="errField" value="@Model.errField" />
        <input type="hidden" id="errMessage" value="@Model.errMessage" />
        <input type="hidden" id="IsMove" value="@Model.IsMove" />

    </div>

然后输入字段正确更新。我什至创建了一个 View Helper 来帮助调试,并且在所有情况下,模型似乎在 HtmlHelper&lt;TModel&gt; 中都有正确的数据——我什至将模型返回为 return Json(model); 并且数据很好。

此时我正在处理工作,但有人知道为什么@Html.HiddenFor 很脏。

更新:这是我的控制器操作

  [HttpPost]
   public ActionResult Index(HomePageModel model)
   


       // process transaction
       Transactionr transr = new Transactionr();
       transr.Process(model);

       model.err = transr.err;
       model.errField = transr.errField;
       model.errMessage = transr.errMessage;

       return View(model);
   

这是我的看法:

        @model App.Models.HomePageModel
    @
        ViewBag.Title = "Product Categorizer";
    
    <form id="formData" method="post" action="/Home/Index">
        @Html.AntiForgeryToken()
        <fieldset>
            <div>

            @Html.HiddenFor(model => model.err)
            @Html.HiddenFor(model => model.errField)
            @Html.HiddenFor(model => model.errMessage)
            @Html.HiddenFor(model => model.IsMove)

            <input type="hidden" id="myerr" value="@Model.err" />
            <input type="hidden" id="myerrField" value="@Model.errField" />

            </div>

           <div class="section group">
                <div class="col span_2_of_2">
                     <div class="message" id ="message">
                         @if (Model.err < 0)
                         
                             <span style="color: purple;">@Model.errMessage (@Model.err) - (@Model.errField)</span>
                         
                         else if (Model.err > 0)
                         
                             <span style="color:red;">@Model.errMessage (@Model.err) (@Model.errField)</span>
                          else 
                            <span>@Model.errMessage (@Model.err) (@Model.errField)</span>
                         
                         </div>
                     </div>
            </div>

            <div class="section group" id="workspace">
                  @Html.Partial("_WorkspacePartial", Model)
            </div>
              <div class="section group" id="details">
                  @Html.Partial("_DetailPartial", Model)
              </div>


        </fieldset>
        </form>

这是我的模型:

 public class HomePageModel
 
    public int FromStore  get; set; 

    //  the "To" part of the copy/move transaction
    public int ToStore  get; set; 

    // a list of the copy/move transaction
    public List<int> Details  get; set; 


    // true is move false is copy
    public bool IsMove  get; set; 

    // current message
    public int err  get; set; 
    public int errField  get; set; 
    public string errMessage  get; set; 

【问题讨论】:

【参考方案1】:

默认的 HtmlHelpers 行为(@Html.HiddenFor 等)的行为与您描述的完全一样。

即您对帖子上的 ViewModel 所做的任何更改都会被执行,您从帖子返回的任何更改都会被视图接收,但是在使用 HTMLHELPERS 重新渲染时,之前的 Post-values 优先于更改后的 ViewModel 值。

想要以快速 + 肮脏的方式“修复”此行为,请在从 HttpPost ActionMethod 返回之前清除 ModelState.Clear() !

【讨论】:

这很脏,因为所有的验证消息都被清除了,所以要注意! 我以为我快疯了。 我不明白。模型的任何属性都没有 Required 属性。为什么返回视图会使 ONE 属性的 HiddenFor 为空?在完成 ModelState.Clear 之后,我得到了正确的值!!! WHY _ 在从 HttpPost ActionMethod 返回之前清除 ModelState.Clear()_? 奇怪的行为(仍然存在于 Razor 页面中)。这似乎是因为By default, the validation system treats non-nullable parameters or properties as if they had a [Required] attribute. 根据文档(docs.microsoft.com/en-us/aspnet/core/mvc/models/…),但即使是用作隐藏输入(通过asp-for)的单个string 类型(可为空)模型属性也会受到此行为的影响,并且其值会默默地恢复到以前的值。【参考方案2】:

正如 joedotnot 所提到的,这是预期的行为。另一个“快速修复”是为隐藏字段编写 html 代码并仅更新模型中的值,例如:

<input type="hidden" id="ErrMessage" name="ErrMessage" value="@Model.ErrMessage">

使用相同的idname 作为模型属性,更新后的值将在回发后呈现。

【讨论】:

这很有魅力,谢谢!【参考方案3】:

我最近遇到了类似的问题,最终编写了新的简单辅助方法 + 2 个重载。我在这里分享它,以防有人仍在寻找解决方法,因为这个“功能”有时很烦人。

public static class CustomExtensions

    public static MvcHtmlString HiddenFor2<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
    
        ReplacePropertyState(htmlHelper, expression);
        return htmlHelper.HiddenFor(expression);
    

    public static MvcHtmlString HiddenFor2<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
    
        ReplacePropertyState(htmlHelper, expression);
        return htmlHelper.HiddenFor(expression, htmlAttributes);
    

    public static MvcHtmlString HiddenFor2<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, IDictionary<string, object> htmlAttributes)
    
        ReplacePropertyState(htmlHelper, expression);
        return htmlHelper.HiddenFor(expression, htmlAttributes);
    

    private static void ReplacePropertyState<TModel, TProperty>(HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
    
        string text = ExpressionHelper.GetExpressionText(expression);
        string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(text);
        ModelStateDictionary modelState = htmlHelper.ViewContext.ViewData.ModelState;

        if (modelState.ContainsKey(fullName))
        
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            ValueProviderResult currentValue = modelState[fullName].Value;
            modelState[fullName].Value = new ValueProviderResult(metadata.Model, Convert.ToString(metadata.Model), currentValue.Culture);
        
    

然后,您只需在视图中照常使用它:

@Html.HiddenFor2(m => m.Id)

值得一提的是它也适用于集合。

【讨论】:

【参考方案4】:

我认为您应该像这样使用它们:

@Html.HiddenFor(x => x.Err)
@Html.HiddenFor(x => x.ErrField)
@Html.HiddenFor(x => x.ErrMessage)
@Html.HiddenFor(x => x.IsMove)

没有看到你的模型,我假设它看起来像这样:

public class ErroViewModel

  public string Err  get; set; 
  public string ErrField  get; set; 
  public string ErrMessage  get; set; 
  public bool IsMove  get; set; 

如果不是,它应该与上面的公共属性类似。

更新

在你的get中你有以下吗?

public ActionResult Index(HomePageModel model)

   var model = new HomePageModel();
   return View(model);

我也会改变你的表格:

 <form id="formData" method="post" action="/Home/Index">

到这里:

@using (Html.BeginForm("Index", "Home", FormMethod.Post))

  // rest of form

【讨论】:

我的模型正在使用公共属性。在表达方面,包括你的建议,我都试过了,似乎没有任何影响。 是的,我正在创建 HomePageModel 的一个实例.. 至于表单.. 我正在使用 jquery 进行一些表单操作,所以我已经这样编码了。 嗯,不知道问题出在哪里,因为这一切对我来说都很好。还是个问题? ModelState 造成的。查看其他答案。 为什么不使用[HttpPost]属性【参考方案5】:

我遇到了类似的问题,然后就这样解决了。

@Html.TextBoxFor(m => m.Email, new  onclick = "this.select()", Value = Model.Email, Placeholder = "E-Mail" )

【讨论】:

【参考方案6】:

你可以试试

<input type="hidden" id="SomeFieldID" name="SomeFieldID" value="@Model.SomeFieldID" />

【讨论】:

这看起来已经被覆盖了 maxscan's answer 两年前发布的【参考方案7】:

您的视图模型中需要一个键。如果您的视图模型中没有任何名为 Id 的属性,请使用 [Key] 将其中一个(预计为唯一标识符)设置为键。

[Key]
Myproperty get;set;

【讨论】:

以上是关于MVC 4 @HTML.HiddenFor 不会在回发时更新 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

ASP.Net MVC Html.HiddenFor 值错误

Html.HiddenFor 做啥?

Html.Hidden 和 Html.HiddenFor 有啥区别

MVC .NET 表单提交未命中控制器操作

MVC - 从 Jquery 传递到查看信息

mvc 个别字段无法赋值的问题