我是一个初学者程序员,并且在 @html.dropdownlistfor助手...
上遇到麻烦我正在使用基于教程的一般存储库和工作模式单位:http://www.asp.net/mvc/tutorials/getting-with-with-with-ef-usish-mvc/implementing-the-the-repository-and-unit-unit-ounit-ert-work-work-work-work-patterns-in-An-asp-net-MVC-Application
这是我的存储库的代码:
public class GenericRepository<TEntity> where TEntity : class
{
internal UsersContext context;
internal DbSet<TEntity> dbSet;
public GenericRepository(UsersContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
public virtual TEntity GetByID(object id)
{
return dbSet.Find(id);
}
public virtual void Insert(TEntity entity)
{
dbSet.Add(entity);
}
// Delete methods not shown
public virtual void Update(TEntity entityToUpdate)
{
dbSet.Attach(entityToUpdate);
context.Entry(entityToUpdate).State = EntityState.Modified;
}
}
这是我的unitofwork类的代码:
public class UnitOfWork : IDisposable
{
private UsersContext context = new UsersContext();
private GenericRepository<UserProfile> userProfileRepository;
private GenericRepository<Lead> leadRepository;
private GenericRepository<UnitedStatesState> unitedStatesStateRepository;
public GenericRepository<UserProfile> UserProfileRepository
{
get
{
if (this.userProfileRepository == null)
{
this.userProfileRepository = new GenericRepository<UserProfile(context);
}
return userProfileRepository;
}
}
public GenericRepository<Lead> LeadRepository
{
get
{
if (this.leadRepository == null)
{
this.leadRepository = new GenericRepository<Lead>(context);
}
return leadRepository;
}
}
public GenericRepository<UnitedStatesState> UnitedStatesStateRepository
{
get
{
if (this.unitedStatesStateRepository == null)
{
this.unitedStatesStateRepository = new GenericRepository<UnitedStatesState>(context);
}
return unitedStatesStateRepository;
}
}
我正在尝试使用强烈键入的视图和模型,以便在不使用viewData/viewbag的情况下将选择列表数据传递到视图。据我了解,最好的做法是做与我在这里看到的类似的事情:验证在ASP.NET MVC
中验证一个下拉列表我尽可能地尝试了它,这就是我想出的
我的视图模型看起来像这样:
public class Lead
{
public int LeadID { get; set; }
public int CompanyID { get; set; }
[Required(ErrorMessage = "Please enter state")]
[Display(Name = "State")]
[MaxLength(2)]
public string State { get; set; }
[Display(Name = "Assigned To")]
public string AssignedTo { get; set; }
[Timestamp]
public Byte[] Timestamp { get; set; }
public virtual Company Company { get; set; }
// IEnumerables for Dropdown Lists passed to views
public IEnumerable<UnitedStatesState> UnitedStatesStates { get; set; }
public IEnumerable<UserProfile> UserProfiles { get; set; }
// Objects passed to views
public Lead lead { get; set; }
}
这些下拉列表的这些iEnumerables然后通过我的存储库从数据库中填充了我的控制器。奇怪的部分是我在两个不同的视图中使用这些下拉列表,即创建和编辑。当我在"创建视图"中使用下拉列表时,它们在get和post action results上都可以很好地工作。当我尝试对我的编辑视图使用相同的下拉列表时,它们适用于GET ActionResult(视图加载和下拉列表工作),但是当我尝试将它们发布到我的Edit ActionResult中时,我会收到以下错误:
{"值不能为null。 r n参数名称:项目"}//这是Visual Studio 2012
中所示的错误system.argumentNullexception:值不能为null。参数名称:项目//这是Google Chrome中显示的错误
以下是我的铅控制器,并具有编辑和创建ActionResults:
public class LeadController : Controller
{
// create instance of Repository Unit of Work
private UnitOfWork unitOfWork = new UnitOfWork();
public ActionResult Create()
{
// Get the current users profile
UserProfile userProfile = UserProfile.GetCurrentUserProfile();
// Creates Dropdown Lists to pass to view
var model = new Lead
{
UnitedStatesStates = unitOfWork.UnitedStatesStateRepository.Get(u => u.StateAbbreviation != null),
UserProfiles = unitOfWork.UserProfileRepository.Get(u => u.CompanyID == userProfile.CompanyID)
};
// Return View
return View(model);
}
[HttpPost]
public ActionResult Create(Lead model)
{
try
{
if (ModelState.IsValid)
{
// Call the current users profile
UserProfile userProfile = UserProfile.GetCurrentUserProfile();
// Create a new lead and apply all attirbutes that were entered
Lead lead = new Lead();
lead.CompanyID = userProfile.CompanyID;
lead.State = model.State;
lead.AssignedTo = model.AssignedTo;
// Add the lead and save the changes. Redirect to Lead Index.
unitOfWork.LeadRepository.Insert(lead);
unitOfWork.Save();
return RedirectToAction("Index");
}
}
catch (DataException)
{
ModelState.AddModelError("", "Unable to save changes. Try again and if the problem persists, see your system administrator.");
}
// Return view if ModelState is not valid
return View();
}
public ActionResult Edit(int id = 0)
{
// Get Users Profile
UserProfile userProfile = UserProfile.GetCurrentUserProfile();
// Check to see if Lead Exists
if (unitOfWork.LeadRepository.GetByID(id) == null)
{
return HttpNotFound();
}
// Creates Dropdown Lists and Gets current lead values to pass to view
var model = new Lead
{
lead = unitOfWork.LeadRepository.GetByID(id),
UnitedStatesStates = unitOfWork.UnitedStatesStateRepository.Get(u => u.StateAbbreviation != null),
UserProfiles = unitOfWork.UserProfileRepository.Get(u => u.CompanyID == userProfile.CompanyID)
};
return View(model);
}
[HttpPost]
public ActionResult Edit(Lead lead)
{
try
{
// Update lead if model state is valid
if (ModelState.IsValid)
{
unitOfWork.LeadRepository.Update(lead);
unitOfWork.Save();
return RedirectToAction("Index");
}
}
// Catch any concurrency exceptions
catch (DbUpdateConcurrencyException ex)
{
var entry = ex.Entries.Single();
var databaseValues = (Lead)entry.GetDatabaseValues().ToObject();
var clientValues = (Lead)entry.Entity;
if (databaseValues.State != clientValues.State)
ModelState.AddModelError("State", "Current value: "
+ databaseValues.State);
if (databaseValues.AssignedTo != clientValues.AssignedTo )
ModelState.AddModelError("Assigned To ", "Current value: "
+ databaseValues.AssignedTo );
ModelState.AddModelError(string.Empty, "The record you attempted to edit "
+ "was modified by another user after you got the original value. The "
+ "edit operation was canceled and the current values in the database "
+ "have been displayed. If you still want to edit this record, click "
+ "the Save button again. Otherwise click the Back to List hyperlink.");
lead.Timestamp = databaseValues.Timestamp;
}
catch (DataException)
{
//Log the error (add a variable name after Exception)
ModelState.AddModelError(string.Empty, "Unable to save changes. Try again, and if the problem persists contact your system administrator.");
}
// Return View if Model State is not valid
return View(lead);
}
帖子编辑ActionResult包括捕获我在此处显示的教程中创建的同意的代码:http://www.asp.net/mvc/tutorials/getting-with-with-ef-using-mvc/handling-concurrency-with-with-the-the-the-the-pramework-framework-in-an-as-asp-net-mvc-mvc-plication
以下是我的创建视图(这很好地起作用):
@model SolarToolbase.Models.Lead
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<div>
<div>
@Html.LabelFor(model => model.State)
@Html.DropDownListFor(model => model.State, new SelectList(Model.UnitedStatesStates, "StateAbbreviation", "UnitedStatesStateName"),"Choose State")<br />
@Html.ValidationMessageFor(model => model.State)
</div>
<div>
@Html.LabelFor(model => model.AssignedTo)
@Html.DropDownListFor(model => model.AssignedTo, new SelectList(Model.UserProfiles, "FullName", "FullName"),"Choose User")<br />
@Html.ValidationMessageFor(model => model.AssignedTo)
</div>
<p>
<input type="submit" value="Create" />
</p>
</div>
}
下面是我的编辑视图(当我点击提交按钮时,这会引发上述错误。我在下面插入了评论,以显示该错误是从中丢弃的):
@model SolarToolbase.Models.Lead
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.lead.LeadID)
@Html.HiddenFor(model => model.lead.Timestamp)
<div>
<div>
@Html.LabelFor(model => model.lead.State)
@Html.DropDownListFor(model => model.lead.State, new SelectList(Model.UnitedStatesStates, "StateAbbreviation", "UnitedStatesStateName"))<br /> // Error thrown from this line
@Html.ValidationMessageFor(model => model.lead.State)
</div>
<div>
@Html.LabelFor(model => model.lead.AssignedTo)
@Html.DropDownListFor(model => model.lead.AssignedTo, new SelectList(Model.UserProfiles, "FullName", "FullName"))<br />
@Html.ValidationMessageFor(model => model.lead.AssignedTo)
</div>
<p>
<input type="submit" value="Save" />
</p>
</div>
}
我提前向发布了如此多的代码表示歉意,老实说,我不知道这个错误来自哪里,我在墙上击败了墙,试图弄清楚它大约4个小时。免费的虚拟五击和为任何可以提供帮助的人的好业力。
谢谢!
在POST
的情况下,Create
和Edit
操作,当出现错误或ModelState
无效时,您会捕获任何异常,并使用构造的Lead
视图模型返回默认的View
,由模型粘合剂创建和填充。
在Edit
POST
操作中,如果存在错误条件,则将lead
对象返回View
作为其Model.
注意,请注意,UnitedStatesStates
和UserProfiles
属性不会在POST
上重新填充。您可以在GET
操作中填充它们,但是您也必须在POST
操作中执行此操作。您需要小心,无论您发送到视图的型号都是正确的,并且所有预期的成员都被填充。
还要注意您的视图模型是类型Lead
,该模型具有称为lead
的属性。那是那里的代码气味;我不会有一个视图模型类,它可以参考其自己类的实例。这已经引起您的困惑。我将Lead
是LeadViewModel
是明确的,并且只要访问和从视图中保留所需的所有属性和值,而没有lead
属性。
在您的Edit
视图中,您将模型的属性称为model.lead.State
,但是在Create
视图中,您引用了父级属性,如model.State
所示。但是在Edit
视图中,当涉及到SelectListItems
时,您正在使用Model.UnitedStatesStates
而不是Model.lead.UnitedStatesStates.
,就像我说的那样,我会消除这种模式,并执行Create
视图现在所做的事情,根本没有lead
属性。例如,对于所有属性和两个视图中的model.State
。
因此,每当您将模型传递到视图时,请确保您的收集属性被填充,如
[HttpPost]
public ActionResult Edit(Lead lead)
{
try
{
// Update lead if model state is valid
if (ModelState.IsValid)
{
unitOfWork.LeadRepository.Update(lead);
unitOfWork.Save();
return RedirectToAction("Index");
}
}
// Catch any concurrency exceptions
catch (DbUpdateConcurrencyException ex)
{
var entry = ex.Entries.Single();
var databaseValues = (Lead)entry.GetDatabaseValues().ToObject();
var clientValues = (Lead)entry.Entity;
if (databaseValues.State != clientValues.State)
ModelState.AddModelError("State", "Current value: "
+ databaseValues.State);
if (databaseValues.AssignedTo != clientValues.AssignedTo )
ModelState.AddModelError("Assigned To ", "Current value: "
+ databaseValues.AssignedTo );
ModelState.AddModelError(string.Empty, "The record you attempted to edit "
+ "was modified by another user after you got the original value. The "
+ "edit operation was canceled and the current values in the database "
+ "have been displayed. If you still want to edit this record, click "
+ "the Save button again. Otherwise click the Back to List hyperlink.");
lead.Timestamp = databaseValues.Timestamp;
}
catch (DataException)
{
//Log the error (add a variable name after Exception)
ModelState.AddModelError(string.Empty, "Unable to save changes. Try again, and if the problem persists contact your system administrator.");
}
// Return View if Model State is not valid
/////////// CHANGES HERE
lead.UnitedStatesStates = unitOfWork.UnitedStatesStateRepository.Get(u => u.StateAbbreviation != null),
lead.UserProfiles = unitOfWork.UserProfileRepository.Get(u => u.CompanyID == userProfile.CompanyID)
return View(lead); // pass the model to the view for Create and Edit POST actions when there's an error
}
在两个POST
操作中都这样做。如果有错误,则使用填充模型的操作将实例化视图。还将Edit
视图更改为像Create
视图一样工作,并且不使用Lead
视图模型的lead
属性。据推测,这将照顾视图中的任何零参考例外。