为什么我的mvc3 viewmodel无法正确更新?

时间:2011-12-15 15:39:05

标签: asp.net-mvc asp.net-mvc-3

我正在使用ASP.NET MVC 3编写图像上传表单。

在视图中,请注意我将@Model.ImagePath显示为文字和@Html.TextBoxFor(model => model.ImagePath)

查看:

@using (Html.BeginForm(null, null, FormMethod.Post, new { enctype="multipart/form-data" }))
{
    @Html.HiddenFor(model => model.BannerSlideId)
    @Html.HiddenFor(model => model.Key)
    <p>
    Image Path:@(Model.ImagePath)<br />
    Image Path in TextBoxFor: @Html.TextBoxFor(model => model.ImagePath)
    </p>
    <p>
        <label class="styled">Upload Slide Image</label>
        <input type="file" name="image" />
    </p>
    <p>
        <button type="submit">Save</button> @Html.ActionLink("Back to List", "Index")
    </p>
}

然后我使用文件输入选择图像,然后将表单提交给Controller。

控制器操作:

[HttpPost]
public ActionResult Create(BannerSlide model, HttpPostedFileBase image)
{
    if (image != null)
        model.ImagePath = image.FileName;
    return View("Edit", model);
}

当我使用断点进行调试时,image.FileName字符串分配给model.ImagePath。但是,当我回到视图时,我会从ImagePath获得两个不同的值。

结果

Image Path:@(Model.ImagePath)<br />

正确返回已分配的图像文件名。但是,

Image Path in TextBoxFor: @Html.TextBoxFor(model => model.ImagePath)

错误地返回空白!

有关为何发生这种情况的任何想法?

3 个答案:

答案 0 :(得分:4)

如果您打算在POST控制器操作中修改它,则应该从ModelState中删除ImagePath属性,或者TextBoxFor等HTML帮助器在绑定时首先在ModelState中查找值,然后在模型中查找:

if (image != null)
{
    ModelState.Remove("ImagePath");
    model.ImagePath = image.FileName;
}

答案 1 :(得分:2)

TextBoxFor HtmlHelper方法以及所有输入辅助方法,将输入控件的值设置为ModelState中保存的值,而不是立即绑定到ViewModel的属性。由于ImagePath中的ImagePath存在于Create方法中,因此它将在后续响应中显示为空白值。

答案 2 :(得分:0)

我建议对此类操作使用以下属性

public class ModelStateFixAttribute : ActionFilterAttribute
{
    public ModelStateFixAttribute()
    {

    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        ModelStateDictionary modelState = filterContext.Controller.ViewData.ModelState;

        String[] arrKeys = new string[modelState.Keys.Count];
        modelState.Keys.CopyTo(arrKeys, 0);
        foreach (string key in arrKeys)
        {
            if (modelState.IsValidField(key))
                modelState.Remove(key);
        }
    }
}