Asp.net mvc 3 是否仅保留MVC3已过帐表单值?
我在MVC3 web应用程序中使用强类型视图。我注意到,在提交表单时,传递给控制器的ViewModel只具有与表单元素关联的属性值。例如,下面的示例显示了一个简单的确认视图,其中包含一个复选框和一个用户在继续之前必须确认的电话号码。当表单提交给控制器操作时,UserConfirm属性包含一个值,但PhoneNumber属性为null ViewModel是否有保留其所有值的方法,或者我是否必须重新填充没有与之关联的表单元素的ViewModel属性 景色Asp.net mvc 3 是否仅保留MVC3已过帐表单值?,asp.net-mvc-3,Asp.net Mvc 3,我在MVC3 web应用程序中使用强类型视图。我注意到,在提交表单时,传递给控制器的ViewModel只具有与表单元素关联的属性值。例如,下面的示例显示了一个简单的确认视图,其中包含一个复选框和一个用户在继续之前必须确认的电话号码。当表单提交给控制器操作时,UserConfirm属性包含一个值,但PhoneNumber属性为null ViewModel是否有保留其所有值的方法,或者我是否必须重新填充没有与之关联的表单元素的ViewModel属性 景色 @model WebMeterReplace
@model WebMeterReplacement.ViewModels.Appointment.ScheduleConfirmationViewModel
@using (Html.BeginForm()) {
@Html.ValidationSummary(false)
@Html.CheckBoxFor(model => model.UserConfirmed)
<span>Please confirm before proceeding</span>
<div>
Phone Number: @Model.PhoneNumber
</div>
<input type="submit" value="Confirm"/>
那么,表单将只发布您创建的元素。正如你发现的,仅仅把电话号码写在页面上是不够的。模型绑定器只能绑定已发布数据中存在的属性 通常,您在这里有两个选项: 1) 您可以为模型中的所有属性创建输入元素,为要编辑的属性使用可见元素(如文本框)和隐藏元素,这些元素应该发回,但没有UI 2) 发回模型的部分表示(正如您现在所做的),从其数据源读回实体(我假设您使用的是某种数据源,可能是EF),然后使用表单中的属性更改该实体的属性
这两种情况都很常见,但这实际上取决于模型的复杂性。由于您将电话号码作为输出写入页面,因此不会自动发回(您已经找到了该部分)。您可以使用电话号码填充隐藏或只读字段,以便将其发回控制器。第二种选择是对数据源进行新调用,并在将对象保存回数据源之前重新填充对象。我通常在隐藏输入中回发类似的信息。我个人大量使用它来传递所需的数据,以便在按edit之前准确地返回用户所在的位置 对你来说,这很简单
@model WebMeterReplacement.ViewModels.Appointment.ScheduleConfirmationViewModel
@using (Html.BeginForm()) {
@Html.ValidationSummary(false)
@Html.CheckBoxFor(model => model.UserConfirmed)
<span>Please confirm before proceeding</span>
<div>
@Html.HiddenFor(m => m.PhoneNumber)
Phone Number: @Model.PhoneNumber
</div>
<input type="submit" value="Confirm"/>
行动
public HomeController(AViewModel Model)
{
PagingData PagingData = Model.PagingData;
Skip = PagingData.Skip;
}
public HomeController(AViewModel Model)
{
String[] HiddenFields = Model.HiddenFields;
}
如果你通过数组,你可以这样做
看法
行动
public HomeController(AViewModel Model)
{
PagingData PagingData = Model.PagingData;
Skip = PagingData.Skip;
}
public HomeController(AViewModel Model)
{
String[] HiddenFields = Model.HiddenFields;
}
我知道这条线有点旧了,但我想我会把它复活,以得到我解决这个问题的反馈 我所处的情况与此类似,我的对象被传递到一个视图,而该视图可能只显示该对象的一部分进行编辑。显然,当控制器从默认模型绑定器接收到模型时,未回传的值将变为null。。保存这意味着DB值将变为null,因为它没有显示/从视图返回 我不喜欢为每个视图创建模型的想法。我知道这可能是正确的方法。。。但我一直在寻找一种可以很快实现的可重用模式。 请参阅“MergeWith”方法。。。因为这将用于从数据库获取对象的副本,并将其与从视图返回的副本合并(回发) 并在控制器中使用它。。你会有类似于
[HttpPost]
public ActionResult Edit(Agent agent)
{
if (ModelState.IsValid)
{
Agent ag = db.Agents.Where(a => a.id == agent.id).ToList<Agent>().First<Agent>();
ag.MergeWith(agent, Request.Params.AllKeys);
db.Entry(ag).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(agent);
}
[HttpPost]
公共操作结果编辑(代理)
{
if(ModelState.IsValid)
{
Agent ag=db.Agents.Where(a=>a.id==Agent.id).ToList().First();
合并(代理、请求、参数、所有密钥);
db.Entry(ag.State=EntityState.Modified;
db.SaveChanges();
返回操作(“索引”);
}
返回视图(代理);
}
这样,在回发过程中,它从数据库中获取对象,并使用视图中的对象更新它。。。但只更新回发的值。。因此,如果您有“地址”之类的字段或视图中没有显示的内容。。在更新过程中不会触及它
到目前为止,我已经对此进行了测试,我为自己的目的而工作,但我欢迎任何反馈,因为我渴望看到其他人如何克服这种情况。这是第一个版本,我相信它可以通过扩展方法或其他方式更好地实现。。但目前,可以将MergeWith复制/粘贴到每个模型对象。是的,只需在表单中为您不使用且希望返回到服务器控件的值放置隐藏字段即可。 谢谢
namespace SIP.Models
{
[Table("agents")]
public class Agent
{
[Key]
public int id { get; set; }
[Searchable]
[DisplayName("Name")]
[Column("name")]
[Required]
[StringLength(50, MinimumLength = 4)]
public string AgentName { get; set; }
[Searchable]
[DisplayName("Address")]
[Column("address")]
[DataType(DataType.MultilineText)]
public string Address { get; set; }
[DisplayName("Region")]
[Searchable]
[Column("region")]
[StringLength(50, MinimumLength = 3)]
public string Region { get; set; }
[DisplayName("Phone")]
[Column("phone")]
[StringLength(50, MinimumLength = 4)]
public string Phone { get; set; }
[DisplayName("Fax")]
[Column("fax")]
[StringLength(50, MinimumLength = 4)]
public string Fax { get; set; }
[DisplayName("Email")]
[RegularExpression(@"(\S)+", ErrorMessage = "White space is not allowed")]
[Column("email")]
[StringLength(50, MinimumLength = 4)]
public string Email { get; set; }
[DisplayName("Notes")]
[Column("notes")]
[DataType(DataType.MultilineText)]
public string Notes{ get; set; }
[DisplayName("Active")]
[Column("active")]
public bool Active { get; set; }
public override string ToString()
{
return AgentName;
}
public bool MergeWith(Agent a, string[] fields)
{
try
{
foreach (PropertyInfo pi in this.GetType().GetProperties())
{
foreach (string f in fields)
{
if (pi.Name == f && pi.Name.ToLower() != "id")
{
var newVal = a.GetType().GetProperty(f).GetValue(a,null);
pi.SetValue(this, newVal, null);
}
}
}
}
catch (Exception ex)
{
return false;
//todo: Log output to file...
}
return true;
}
}
}
[HttpPost]
public ActionResult Edit(Agent agent)
{
if (ModelState.IsValid)
{
Agent ag = db.Agents.Where(a => a.id == agent.id).ToList<Agent>().First<Agent>();
ag.MergeWith(agent, Request.Params.AllKeys);
db.Entry(ag).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(agent);
}