【问题标题】:ViewModel base model is null on create action postback with MVC3ViewModel 基本模型在使用 MVC3 创建操作回发时为空
【发布时间】:2012-01-24 14:48:57
【问题描述】:

让我的 ViewModel 在控制器的创建操作回发中的基本模型属性中返回非空对象时遇到了一些问题。我目前有另一个页面在另一个模型上执行完全相同的操作,该模型具有几乎相同的属性并且该表单运行良好,所以我觉得我缺少一些基本的东西,尽管我无法放置错误。

这是我的 ViewModel 和我的 Base 类:

public class SystemFailureActionViewModel
{
    /// <summary>
    /// View model class for adding and modifying SystemFailureActions
    /// </summary>
    public SystemFailureAction action { get; set; }

    //properties
    public int TypeID { get; set; }
    public string TypeDescription { get; set; }
    public bool Assigned { get; set; } 

    public SystemFailureActionViewModel() { }

    public SystemFailureActionViewModel(SystemFailureAction action)
    {
        this.action = action;
    }

    //Collections for views
    public IEnumerable<SelectListItem> EditSystemFailiureTypesList { get { return ModelListProvider.FilteredSystemFailureTypeList; } }
    public IEnumerable<SelectListItem> DetailsSystemFailiureTypesList { get { return ModelListProvider.FullSystemFailureTypeList; } }
}

[MetadataType(typeof(SystemFailureActionMetadata))]
public partial class SystemFailureAction
{
    private class SystemFailureActionMetadata
    {
        /// <summary>
        /// ID for this failure action
        /// </summary>
        public int ID { get; set; }

        /// <summary>
        /// Action Description
        /// </summary>
        [Required]
        [StringLength(200)]
        [DisplayName("Action Description")]
        public string Description { get; set; }
    }
}

这是我的控制器添加和添加回发方法:

public ActionResult Add()
    {
        SystemFailureAction action = new SystemFailureAction();
        action.Description = "";
        populateSystemFailureActionData(action);
        return PartialView("Form", new SystemFailureActionViewModel(action));
    }


    [HttpPost]
    public ActionResult Add(SystemFailureActionViewModel viewModel, string[] selectedTypes, FormCollection collection)
    {
        SystemFailureAction newAction = viewModel.action;

        if (!ModelState.IsValid)
        {
            populateSystemFailureActionData(newAction);
            return PartialView("Form", new SystemFailureActionViewModel(newAction));
        }

        try
        {
            //Insert the new failure action type 
            context.SystemFailureActions.InsertOnSubmit(newAction);
            context.SubmitChanges();

            //Insert the failure type mappings
            updateSystemFailureAssociationData(newAction, selectedTypes);
            context.SubmitChanges();

            //Return the new data
            populateSystemFailureActionData(newAction);
            return PartialView("Done", new SystemFailureActionViewModel(newAction));
        }
        catch (Exception ex)
        {
            ModelState.AddModelError("", ex.Message);
            populateSystemFailureActionData(newAction);
            return PartialView("Form", new SystemFailureActionViewModel(newAction));
        }           
    }      

最后这是我的表单,它被加载到 Jquery 对话框中,并且通过 Ajax 完成回发。

  @using (Ajax.BeginForm(new AjaxOptions
{
    HttpMethod = "Post",
    UpdateTargetId = "formDialog",
    InsertionMode = InsertionMode.Replace,
    OnSuccess = "onDialogDone()"
}))
{
    @Html.ValidationSummary(true)
    <div>
        <div class="editor-label">
            @Html.LabelFor(model => model.action.Description)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.action.Description)
        </div>
    </div>
    <div class="categoryFieldSet">
        <fieldset>
            <legend>Mechanical System Failure Categories</legend>
            <div class="editor-field">
                <table>
                    <tr>
                        @{
                            int count = 0;
                            List<ManageMAT.ViewModels.SystemFailureActionViewModel> types = ViewBag.Types;

                            foreach (var type in types)
                            {
                                if (count++ % 3 == 0)
                                {
                                    @: </tr> <tr>
                                }
                                @: <td>
                                    <input type="checkbox"
                                           id="selectedTypes + @type.TypeID"
                                           name="selectedTypes"
                                           value="@type.TypeID"
                                           @(Html.Raw(type.Assigned ? "checked=\"checked\"" : "")) />
                                    <label for="selectedTypes + @type.TypeID">@type.TypeDescription</label>
                                @:</td>
                            }
                        @:</tr>
                        }
                </table>
            </div>
        </fieldset>
    </div>
}

如果您想知道 ViewBag.Types 逻辑是什么形式,它与我之前提出的this 问题有关。

编辑:

我检查了 ModelState 错误,我得到的异常是

"The parameter conversion from type 'System.String' to type Models.SystemFailureAction' failed because no type converter can convert between these types."

我还删除了添加失败类型的逻辑,但我仍然收到同样的问题。因此,问题似乎来自将 Viewmodel.action.Description 映射到操作。

【问题讨论】:

    标签: asp.net-mvc-3 c#-4.0 razor controller viewmodel


    【解决方案1】:

    问题是您的SystemFailureActionViewModel 上的以下属性:

    public SystemFailureAction action { get; set; }
    

    在 ASP.NET MVC 中,actioncontroller 是保留字。它们是每条路线的一部分。如果你有一个以这种方式调用的属性,它与指向动作名称的字符串值冲突,显然不能绑定到复杂的 SystemFailureAction 类型。

    所以要解决这个问题,只需在你的视图模型上重命名这个属性:

    public SystemFailureAction FailureAction { get; set; }
    

    【讨论】:

    • 太好了,我什至没有想到这是问题所在。这解决了我的问题。我想知道为什么这不会引发某种编译时错误,甚至不会在 VS 中显示为保留关键字?
    猜你喜欢
    • 1970-01-01
    • 2016-02-13
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-04
    • 1970-01-01
    • 2011-11-27
    相关资源
    最近更新 更多