使用 MVC3 创建操作回发时 ViewModel 基本模型为 null
我在让 ViewModel 在控制器的创建操作回发的基本模型属性中返回非空对象时遇到一些问题。我目前有另一个页面正在另一个模型上执行完全相同的操作,该模型具有几乎相同的属性,并且该表单运行完美,所以我觉得我错过了一些基本的东西,尽管我无法找出问题所在。
这是我的 ViewModel 和我的基类:
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 逻辑的形式是什么,它与 这个问题是我之前问的。
编辑:
我检查了 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 映射到操作。
I'm having some trouble getting my ViewModel to return a non-null object in the base model property in my controller's Create action postback. I currently have another page that is doing the exact same operations on another model that has almost the same properties and that form is working perfectly, so I feel like I'm missing something basic, though I can't place what is wrong.
Here's my ViewModel with my Base class:
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; }
}
}
Here's my Controller Add and Add Postback methods:
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));
}
}
And finally here is my form, it is being loaded into a Jquery dialog and the postback is being done via 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>
}
If you're wondering what the ViewBag.Types logic is in the form it is related to this question I asked earlier.
Edit:
I checked the ModelState error and the exception I'm getting is
"The parameter conversion from type 'System.String' to type Models.SystemFailureAction' failed because no type converter can convert between these types."
I also removed the logic that adds the Failure types and I'm still receiving the same issue. So it appears the problem is coming from mapping the Viewmodel.action.Description to the action.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题出在
SystemFailureActionViewModel
上的以下属性:在 ASP.NET MVC 中,
action
和controller
是一种保留字。它们是每条路线的一部分。如果您有一个以这种方式调用的属性,它会与指向操作名称的字符串值冲突,并且该字符串值显然不能绑定到复杂的 SystemFailureAction 类型。因此,要解决该问题,只需在视图模型上重命名此属性即可:
The problem is the following property on your
SystemFailureActionViewModel
:In ASP.NET MVC
action
andcontroller
are kinda reserved words. They are part of every route. And if you have a property called this way it conflicts with the string value which is pointing to the action name and which obviously cannot be bound to a complexSystemFailureAction
type.So to fix the problem simply rename this property on your view model: