ASP.NET MVC 4下拉列表错误错误:null值



我是一个初学者程序员,并且在 @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的情况下,CreateEdit操作,当出现错误或ModelState无效时,您会捕获任何异常,并使用构造的Lead视图模型返回默认的View,由模型粘合剂创建和填充。

Edit POST操作中,如果存在错误条件,则将lead对象返回View作为其Model.注意,请注意,UnitedStatesStatesUserProfiles属性不会在POST上重新填充。您可以在GET操作中填充它们,但是您也必须在POST操作中执行此操作。您需要小心,无论您发送到视图的型号都是正确的,并且所有预期的成员都被填充。

还要注意您的视图模型是类型Lead,该模型具有称为lead的属性。那是那里的代码气味;我不会有一个视图模型类,它可以参考其自己类的实例。这已经引起您的困惑。我将LeadLeadViewModel是明确的,并且只要访问和从视图中保留所需的所有属性和值,而没有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属性。据推测,这将照顾视图中的任何零参考例外。

最新更新