使用我的模型显示页面工作正常,但帖子不返回绑定模型。 我的课程:
public class ContactManager
{
public Contact Contact { get; set; }
public SelectList SalutationList { get; set; }
}
public class Contact
{
public int Id{get;set;}
public string FirstName{get; set;}
public SalutationType SalutationType{get; set;}
}
public class SalutationType
{
public int Id { get; set; }
public string Name { get; set; }
}
我的观点:
@model ViewModels.ContactManager
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.Contact.Id)
@Html.DropDownListFor(model => model.Contact.SalutationType.Id, Model.SalutationList)
@Html.EditorFor(model => model.Contact.FirstName)
<input type="submit" value="Save" />
}
问题似乎出现在DropDownListFor中。下拉列表正确显示正确的值,但是当我发布此页面时,完整的模型为空白。如果我像这样简化DropDownListFor,则按预期发布值。
@html.DroDownListFor(model=>model.MyPlaceHolderProp, Model.SalutationList)
我的模型太复杂了吗?我没有正确地做某事吗?
模型基于我在单独项目中创建的使用EF的几个表。我试图避免创建更多的类/模型然后我必须。
答案 0 :(得分:1)
你也应该发布你的控制器动作,因为你的模型作为空白回来真的与此无关。以这种或那种方式更改DropDownListFor
定义不应影响任何其他值的发布。
那就是说,你最终会遇到另一个问题,所以无论如何你需要重新组合。您不能仅回发相关项的ID值。实体框架会抱怨已经存在具有该ID的对象,或者更糟糕的是,如果该对象附加,它将使用该Name
的新发布值更新具有该ID的行,在这种情况下什么都不是,所以它只是清除它。
当您使用单个项目(基本上是外键)创建关系时,如果您未指定用于保存该外键值的属性,则Entity Framework会在幕后为您创建一个跟踪关系的属性。在这种情况下,这意味着您的Contacts
表中有一个名为SalutationType_Id
的列。但是,您的班级无法直接访问此值。这就是为什么我建议你总是提供一个显式属性来处理这种关系:
[ForeignKey("SalutationType")]
public int SalutationTypeId { get; set; }
public SalutationType SalutationType { get; set; }
如果你这样做,那么你可以直接填充发布的id 那里,实体框架将创建关系。
@Html.DropDownListFor(m => m.Contact.SalutationTypeId, Model.SalutationList);
如果您坚持隐含密钥,那么您必须自己创建关系,方法是在视图模型上创建一个字段以保存已发布的值,然后使用该值从中查找SalutationType
实例数据库,然后最后将其添加到Contact
实例。
添加到您的视图模型
public int SalutationTypeId { get; set; }
在您的视图中
@Html.DropDownListFor(m => m.SalutationTypeId, Model.SalutationList)
在您的POST操作中
var salutationType = db.SalutationTypes.Find(model.SalutationTypeId);
contact.SalutationType = salutationType;
答案 1 :(得分:0)
你可以这样做。这可能是处理它的更“MVC最佳实践”方式。一切都在他们的模型中保持整洁,不需要手动ID。这些视图旨在表示它们所基于的底层模型。如果要创建具有表单的视图,请创建表示表单的模型并在视图中使用它。
修改您的模型,如:
public class PostModel
{
public int ContactID { get; set; }
public int SalutationID { get; set; }
public string FirstName { get; set; }
}
public class PostView
{
public ContactManager contact { get; set; }
public PostModel post { get; set; }
}
然后在控制器中创建PostView
:
public ActionResult Index()
{
//create the PostView model
var pv = new PostView();
pv.ContactManager = contactManager;
pv.post = new PostView()
{
ContactID = contactManager.Contact.Id,
SalutationID = contactManager.SalutationType.Id,
FirstName = contactManager.Contact.FirstName
};
return View(pv);
}
然后视图可能像:
@model ViewModels.PostView
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.post.ContactID)
@Html.DropDownListFor(model => model.post.SalutationID, model.contact.SalutationList)
@Html.EditorFor(model => model.post.FirstName)
<input type="submit" value="Save" />
}
然后控制器中的post动作:
[HttpPost]
public ActionResult Index(PostView pv)
{
//post code
//the posted data will be in pv.post
}
答案 2 :(得分:0)
您是否考虑过使用自定义模型绑定器?自定义模型绑定对于仍然相对简单的模型来说并不复杂,您可以根据需要处理序列化/反序列化。
http://msdn.microsoft.com/en-us/magazine/hh781022.aspx
http://forums.asp.net/t/1944696.aspx?what+is+custom+model+binding+in+mvc
答案 3 :(得分:0)
我不确定这会对你有什么帮助...我有一个类似的问题,但我使用ajax回发...无论如何,我忘了用[Serializable]属性标记我的绑定类。
所以你可以试试
[Serializable]
public class Contract {
...
}
同样,我正在使用Json回发给我的控制器,所以可能没有相关或帮助你。但是,我觉得值得一试。