MVC 4 - 使用 Entity Framework 更新模型 - 传递 httpPost 参数的空异常
MVC4 - Updating Model using Entity Framework - Null Exception passing httpPost paramater
我正在学习 MVC 并尝试创建一个简单的表单,允许用户更新模型的描述。
问题是我得到一个空异常
The parameters dictionary contains a null entry for parameter
'ThreatID' of non-nullable type 'System.Int32' for method
'System.Web.Mvc.ActionResult GetThreat(Int32)' in
'RiskAssesmentApplication.Controllers.ThreatsController'. An optional
parameter must be a reference type, a nullable type, or be declared as
an optional parameter. Parameter name: parameters
表单的 Get 方法似乎按预期工作,但 id 没有传回 HttpPost 方法参数,我不知道如何传递它。我 运行搜索并看到了一些关于使用 @hiddenfor
助手的信息,但它对我不起作用。
这是我的方法
public ActionResult GetThreat(int ThreatID)
{
// ViewModel.Threat = repository.GetThreat(ThreatID);
RiskAssessmentApplicationEntities _DBContext = new RiskAssessmentApplicationEntities();
ThreatWithSecurityEventAndISOControlViewModel ViewModel = new ThreatWithSecurityEventAndISOControlViewModel();
ViewModel.Threat = _DBContext.Threats.Single(x => x.ID == ThreatID);
ViewModel.SecurityEvents = _DBContext
.ThreatHasSecurityEvents
.Include("ThreatHasSecurityEvent.SecurityEvent")
.Where(x => x.ThreatID == ThreatID)
.Select(x => x.SecurityEvent);
return View(ViewModel);
}
[HttpGet]
public ViewResult EditThreat(int ThreatID)
{
Threat Threat = repository.Threats.FirstOrDefault(x => x.ID == ThreatID);
return View(Threat);
}
[HttpPost]
public ActionResult EditThreat(Threat Threat)
{
if (ModelState.IsValid)
{
repository.SaveThreat(Threat);
TempData["message"] = string.Format("{0} new description has been saved", Threat.Description);
return RedirectToAction("GetThreat");
}
else
{
// something is incorrect!
return View(Threat);
}
}
这是我的看法
@model RiskAssesmentApplication.Threat
@using RiskAssesmentApplication;
@{
ViewBag.Title = "EditThreat";
}
<div style="font-family: Calibri">
<fieldset>
<legend>Edit Threat Description</legend>
@using (Html.BeginForm())
{
@Html.HiddenFor(model => model.ID);
<div class="editor-label">
@Html.LabelFor(model => @Model.Description, "Threat Description")
</div>
<div class="editor-field">
@Html.EditorFor(model => @Model.Description)
@Html.ValidationMessageFor(model => @Model.Description )
</div>
<p>
<input type="submit" value="Save Changes" />
</p>
}
</fieldset>
</div>
这是我的模特
public class ThreatWithSecurityEventAndISOControlViewModel
{
public Threat Threat { get; set; }
public SecurityEvent SecurityEvent { get; set; }
public IEnumerable<ISOControl> ISOControls { get; set; }
public IEnumerable<SecurityEvent> SecurityEvents { get; set; }
我真的很难过所以任何帮助将不胜感激
如果没有看到您的其余代码,很难确定,但听起来您正在使用一个断开连接的实体。仅仅因为您使用的实体模型具有数据库中行的 ID,并不意味着它已连接到您的数据上下文。使用 post 中传回的模型来查找连接的版本。示例:
[HttpPost]
public void Whatever(Threat model)
{
var connectedModel = context.Threats.FirstOrDefault(x => x.ID == model.ID);
connectedModel.SomeProperty = model.SomeProperty; //or use AutoMapper
context.SaveChanges();
}
将您的 RedirectToAction
替换为:
return RedirectToAction("EditThreat", new { ThreatID = 99 });
您的 GetThreat()
方法需要参数 int ThreatID
(不可为空),但在您的 EditThreat()
方法中,您在重定向时不传递值。变化
return RedirectToAction("GetThreat");
至
return RedirectToAction("GetThreat", new { ThreatID = Threat.ID });
我正在学习 MVC 并尝试创建一个简单的表单,允许用户更新模型的描述。
问题是我得到一个空异常
The parameters dictionary contains a null entry for parameter 'ThreatID' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult GetThreat(Int32)' in 'RiskAssesmentApplication.Controllers.ThreatsController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter. Parameter name: parameters
表单的 Get 方法似乎按预期工作,但 id 没有传回 HttpPost 方法参数,我不知道如何传递它。我 运行搜索并看到了一些关于使用 @hiddenfor
助手的信息,但它对我不起作用。
这是我的方法
public ActionResult GetThreat(int ThreatID)
{
// ViewModel.Threat = repository.GetThreat(ThreatID);
RiskAssessmentApplicationEntities _DBContext = new RiskAssessmentApplicationEntities();
ThreatWithSecurityEventAndISOControlViewModel ViewModel = new ThreatWithSecurityEventAndISOControlViewModel();
ViewModel.Threat = _DBContext.Threats.Single(x => x.ID == ThreatID);
ViewModel.SecurityEvents = _DBContext
.ThreatHasSecurityEvents
.Include("ThreatHasSecurityEvent.SecurityEvent")
.Where(x => x.ThreatID == ThreatID)
.Select(x => x.SecurityEvent);
return View(ViewModel);
}
[HttpGet]
public ViewResult EditThreat(int ThreatID)
{
Threat Threat = repository.Threats.FirstOrDefault(x => x.ID == ThreatID);
return View(Threat);
}
[HttpPost]
public ActionResult EditThreat(Threat Threat)
{
if (ModelState.IsValid)
{
repository.SaveThreat(Threat);
TempData["message"] = string.Format("{0} new description has been saved", Threat.Description);
return RedirectToAction("GetThreat");
}
else
{
// something is incorrect!
return View(Threat);
}
}
这是我的看法
@model RiskAssesmentApplication.Threat
@using RiskAssesmentApplication;
@{
ViewBag.Title = "EditThreat";
}
<div style="font-family: Calibri">
<fieldset>
<legend>Edit Threat Description</legend>
@using (Html.BeginForm())
{
@Html.HiddenFor(model => model.ID);
<div class="editor-label">
@Html.LabelFor(model => @Model.Description, "Threat Description")
</div>
<div class="editor-field">
@Html.EditorFor(model => @Model.Description)
@Html.ValidationMessageFor(model => @Model.Description )
</div>
<p>
<input type="submit" value="Save Changes" />
</p>
}
</fieldset>
</div>
这是我的模特
public class ThreatWithSecurityEventAndISOControlViewModel
{
public Threat Threat { get; set; }
public SecurityEvent SecurityEvent { get; set; }
public IEnumerable<ISOControl> ISOControls { get; set; }
public IEnumerable<SecurityEvent> SecurityEvents { get; set; }
我真的很难过所以任何帮助将不胜感激
如果没有看到您的其余代码,很难确定,但听起来您正在使用一个断开连接的实体。仅仅因为您使用的实体模型具有数据库中行的 ID,并不意味着它已连接到您的数据上下文。使用 post 中传回的模型来查找连接的版本。示例:
[HttpPost]
public void Whatever(Threat model)
{
var connectedModel = context.Threats.FirstOrDefault(x => x.ID == model.ID);
connectedModel.SomeProperty = model.SomeProperty; //or use AutoMapper
context.SaveChanges();
}
将您的 RedirectToAction
替换为:
return RedirectToAction("EditThreat", new { ThreatID = 99 });
您的 GetThreat()
方法需要参数 int ThreatID
(不可为空),但在您的 EditThreat()
方法中,您在重定向时不传递值。变化
return RedirectToAction("GetThreat");
至
return RedirectToAction("GetThreat", new { ThreatID = Threat.ID });