【问题标题】:MVC 4 @HTML.HiddenFor are not updating on a postback [duplicate]MVC 4 @HTML.HiddenFor 不会在回发时更新 [重复]
【发布时间】: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; }

【问题讨论】:

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


    【解决方案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" />
        

        【讨论】:

        【解决方案7】:

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

        [Key]
        Myproperty {get;set;}
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-12-29
          • 1970-01-01
          • 1970-01-01
          • 2016-05-23
          • 1970-01-01
          相关资源
          最近更新 更多