Asp.net mvc 4 MVC通过数据预填充将模型传回控制器
我现在已经多次遇到这个问题。我用不同的方法解决了这个问题,但总觉得有更好的方法来处理这个问题。寻找解决方案(最佳实践)产生了nada。希望得到一些明智的建议 场景是这样的:我正在构建一个MVC4 web应用程序。我正在向我的视图传递一个复杂的模型。例如:Asp.net mvc 4 MVC通过数据预填充将模型传回控制器,asp.net-mvc-4,model,controller,sql-update,Asp.net Mvc 4,Model,Controller,Sql Update,我现在已经多次遇到这个问题。我用不同的方法解决了这个问题,但总觉得有更好的方法来处理这个问题。寻找解决方案(最佳实践)产生了nada。希望得到一些明智的建议 场景是这样的:我正在构建一个MVC4 web应用程序。我正在向我的视图传递一个复杂的模型。例如: public class Uat { public int UatId { get; set; } public int ProjectId { get; set; } public virtual Project P
public class Uat
{
public int UatId { get; set; }
public int ProjectId { get; set; }
public virtual Project Project { get; set; }
public virtual ICollection<TestCase> TestCases { get; set; }
public UatStatus Status { get; set; }
public string StartDate { get; set; }
public string StatusChangeDate { get; set; }
public string ProductVersion { get; set; }
public string Introduction { get; set; }
public bool isActive { get; set; }
}
问题是,控制器中我的uat对象只有TestCases数据。其他所有内容均为null或0。Uat中的测试用例只有注释和状态数据,其他所有数据都为null或0。因此,如果我尝试在此模型上运行更新,我会得到错误:ObjectStateManager中已经存在具有相同键的对象。我已经调查过了,这对我来说很有意义。但为了纠正这一点,我在过去做了两件事中的一件:
这两种解决方案对我来说都很难看,而且我肯定我做得不对。虽然这在过去为我解决了这个问题,但它会导致我的视图被隐藏的字段弄得乱七八糟,或者我最终向数据库发出了太多的请求。我的应用程序很小,所以这些变通方法现在没有多大效果,但我真的想养成最佳实践的习惯。任何来自SO社区的帮助都将不胜感激。提前谢谢 这就是为什么需要一个表示实体全部或部分的viewmodel。使用viewmodel的好处之一是可以防止过重或过少过帐。你的情况就是一个很好的例子。您只需要更新实体的几个字段,这在大多数情况下是有意义的,因此不需要将其余字段返回到视图。甚至没有将它们作为隐藏字段,只是为了将值发回并保存在数据库中。如果只需要其中两个字段,则为其创建一个模型,如:
public class TestCaseModel
{
public int TestCaseId { get; set; }
public TestCaseStatus Status { get; set; }
public string Comment { get; set; }
}
var testCaseEntity = retrieve_from_db();
testCaseEntity.UatId = input.UatId;
testCaseEntity.Status = input.Status;
testCaseEntity.Comment = input.Comment;
由于您将选择viewmodel路线,因此您可能需要为您的Uat
实体创建一个viewmodel。或者最好的方法是使用一个扁平的模型,如下所示:
public class TestCase
{
[Key]
public int TestCaseId { get; set; }
public int UatId { get; set; }
public virtual Uat Uat { get; set; }
public virtual ICollection<Step> Steps { get; set; }
public TestCaseStatus Status { get; set; }
public string Title { get; set; }
public string Comment { get; set; }
}
@Model ClientPortal.Models.Uat
@{
ViewBag.Title = "Uat";
}
<h2>Uat</h2>
@using (Html.BeginForm("UatEvalution", "Client"))
{
@Html.ValidationSummary(true)
<div>
@{var iteration = 0;}
@foreach (var testCase in Model.TestCases)
{
<div class="well">
<span class="testCaseTitle"><h4>@testCase.Title</h4></span>
<br />
<br />
<ol style="margin-left:40px">
@foreach (var step in testCase.Steps)
{
<li>@step.Description</li>
}
</ol>
<br />
<input type="checkbox" name="TestCases[@iteration].Status" value="2" />Approve
<input type="checkbox" name="TestCases[@iteration].Status" value="1" />Deny
<br />
<span><textarea name="TestCases[@iteration].Comment"></textarea></span>
@{iteration = iteration + 1;
}
</div>
}
</div>
<input type="submit" />
}
[HttpPost]
public ActionResult UatEvalution(Uat uat)
{
//process data
//Update(uat);
//SaveChanges();
}
public class TestCaseInputModel
{
public int UatId{ get; set; } // for reference
public int TestCaseId { get; set; }
public TestCaseStatus Status { get; set; }
public string Comment { get; set; }
}
然后只需添加必要的字段或您希望“显示”的字段,这意味着您不希望有输入。然后必须将模型的所有“输入”字段映射回实体。比如:
public class TestCaseModel
{
public int TestCaseId { get; set; }
public TestCaseStatus Status { get; set; }
public string Comment { get; set; }
}
var testCaseEntity = retrieve_from_db();
testCaseEntity.UatId = input.UatId;
testCaseEntity.Status = input.Status;
testCaseEntity.Comment = input.Comment;
此外,可以使用自动映射工具将值从模型返回到实体。这是你能做到的最干净的方法,我想。谢谢你的解释。ViewModels在过去帮助过我。有时候,我觉得我必须破解一些东西,而实际上,我想这就是mvc的工作方式。我感谢你的反馈!不客气。我希望您在当前的项目@nycfdtd中也选择viewmodels。