在一系列网页浏览中遇到视图状态问题 - 在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<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);
}
以下是我的观点:
@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; }
答案 0 :(得分:32)
默认的HtmlHelpers行为(@ Html.HiddenFor等)的行为与您所描述的完全相同。
即。您对帖子上的ViewModel所做的任何更改都会被操作,您从Post返回的任何更改都会被视图接收,但在重新呈现WITH HTMLHELPERS时,之前的Post-values优先于更改的ViewModel值。
希望以快速+脏的方式“修复”此行为,在从HttpPost ActionMethod返回之前清除ModelState.Clear()!
答案 1 :(得分:6)
如joedotnot所述,这是预期的行为。另一个“快速修复”是为隐藏字段编写html代码并仅更新模型中的值,例如:
<input type="hidden" id="ErrMessage" name="ErrMessage" value="@Model.ErrMessage">
使用相同的id
和name
作为模型属性,更新后的值将在回发后呈现。
答案 2 :(得分: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);
}
}
}
然后你就像往常一样在你看来使用它:
@Html.HiddenFor2(m => m.Id)
值得一提的是它也适用于收藏品。
答案 3 :(得分:3)
我认为你应该像这样使用它们:
@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; }
}
如果不是,它应与上述公共财产类似。
<强>更新强>
在你的获取中你有以下几点吗?
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
}
答案 4 :(得分:1)
你可以尝试
cursorIndex
答案 5 :(得分:0)
我遇到了类似的问题并且解决了这个问题。
@Html.TextBoxFor(m => m.Email, new { onclick = "this.select()", Value = Model.Email, Placeholder = "E-Mail" })
答案 6 :(得分:-1)
您的视图模型中需要一个键。如果您在视图模型中没有任何名为Id的属性,请使用[Key]将其中一个(预期为uniqe identifyiyer)设置为键。
[Key]
Myproperty {get;set;}