MVC 4 @ HTML.HiddenFor没有在回发上更新

use*_*301 22 c# asp.net asp.net-mvc razor asp.net-mvc-4

在一系列页面视图中遇到视图状态问题 - 在Razor页面的初始视图中,我使用Html.HiddenFor如下:

    @Html.HiddenFor(x => Model.err)
    @Html.HiddenFor(x => Model.errField)
    @Html.HiddenFor(x => Model.errMessage)
    @Html.HiddenFor(x => Model.IsMove)
Run Code Online (Sandbox Code Playgroud)

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

       model.err = transHelper.err;
       model.errField = transHelper.errField;
       model.errMessage = transHelper.errMessage;
       return View(model);
Run Code Online (Sandbox Code Playgroud)

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

     @*      
        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>
Run Code Online (Sandbox Code Playgroud)

然后输入字段正确更新.我甚至创建了一个View Helper来帮助调试,并且在所有情况下,模型似乎都有正确的数据 HtmlHelper<TModel>- 我甚至返回模型,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);
   }
Run Code Online (Sandbox Code Playgroud)

这是我的观点:

        @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>
Run Code Online (Sandbox Code Playgroud)

这是我的模型:

 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; }
Run Code Online (Sandbox Code Playgroud)

joe*_*not 33

默认的HtmlHelpers行为(@ Html.HiddenFor等)的行为与您所描述的完全相同.

即,您对帖子上的ViewModel所做的任何更改都会被操作,您从Post返回的任何更改都会被视图接收,但在重新呈现WITH HTMLHELPERS时,之前的Post值优先于更改的ViewModel值.

想要以快速+脏的方式"修复"这种行为,在从HttpPost ActionMethod返回之前清除ModelState.Clear()!

  • 我以为我疯了. (8认同)
  • 这非常脏,因为所有验证消息都被清除了,所以要注意! (2认同)

小智 8

正如joedotnot所提到的,这是预期的行为.另一个"快速解决方法"是为隐藏字段编写html代码并仅更新模型中的值,例如:

<input type="hidden" id="ErrMessage" name="ErrMessage" value="@Model.ErrMessage">
Run Code Online (Sandbox Code Playgroud)

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


Rus*_*kiy 5

我最近遇到了类似的问题,最终编写了新的简单帮助方法+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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以像往常一样在你看来使用它:

@Html.HiddenFor2(m => m.Id)
Run Code Online (Sandbox Code Playgroud)

值得一提的是它也适用于收藏品.


hut*_*oid 3

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

@Html.HiddenFor(x => x.Err)
@Html.HiddenFor(x => x.ErrField)
@Html.HiddenFor(x => x.ErrMessage)
@Html.HiddenFor(x => x.IsMove)
Run Code Online (Sandbox Code Playgroud)

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

public class ErroViewModel
{
  public string Err { get; set; }
  public string ErrField { get; set; }
  public string ErrMessage { get; set; }
  public bool IsMove { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

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

更新

在你的get中有以下内容吗?

public ActionResult Index(HomePageModel model)
{
   var model = new HomePageModel();
   return View(model);
}
Run Code Online (Sandbox Code Playgroud)

我也会改变你的形式:

 <form id="formData" method="post" action="/Home/Index">
Run Code Online (Sandbox Code Playgroud)

对此:

@using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
  // rest of form
}
Run Code Online (Sandbox Code Playgroud)