Why do I get a null exception on post in my DropDownListFor?

I know this sounds like every other question on the net about this but it's actually not. I have tried finding the right answer high and low so as to not waste anyone's time but to no avail. I should also add that I am pretty new to MVC.NET.

I have an MVC 4 view with a DropDownListFor call that throws a null ref exception on post. I am trying to test a submit with nothing selected scenario ie the default selection is selected. Ideally, it will get picked up and yell at me with a required field message. I see that the Province model property is in fact set to -1 on the post, so that works.

Now this is where my question deviates from most others. I am pretty sure that the model is being passed correctly and that the SelectList is populated. I have set a breakpoint on the line in the view and am seeing it populated on the post just before it blows up. My code seems to look like every other example I have seen.

I very much appreciate any help you can provide.

At the end, I will paste the yellow screen info.

So here are the snippets, I cut out the bulk of it so you're not overwhelmed with non-relevant code:

View:

@using GymManagement.UI.Models
@model UserModel
@Html.DropDownListFor(m => m.Province, Model.ProvinceList, new {@id="ProvincePersonal", @class="inputField", @value="@Model.Province"})

Controller:

public ActionResult CreateMember()
{
    return CreateUser();
}

[HttpPost]
public ActionResult CreateMember(UserModel model)
{
    return CreateUser(model);
}

private ActionResult CreateUser()
{
    var model = new UserModel();

    PrepareModel(model, false);

    return View(model);
}

private ActionResult CreateUser(UserModel model)
{
    if (ModelState.IsValid)
    {
        return DisplayUser(model);
    }

    PrepareModel(model, true);

    return View(model);
}

private void PrepareModel(UserModel model, bool isPostback)
{
    // other items removed for brevity

    if (Session["Provinces"] == null || ((List<Province>)Session["Provinces"]).Count == 0)
    {
        var serviceClient = ServiceProxy.GetLookupService();
        var provinces = serviceClient.GetProvinces(); // Returns List<Province>

        provinces = provinces.OrderBy(p => p.ProvinceName).ToList();
        Session["Provinces"] = provinces;
        model.Provinces = provinces;
    }
    else
    {
        model.Provinces = ((List<Province>)Session["Provinces"]);
    }
}

Model:

// base model
public class BaseModel
{
    public BaseModel()
    {
        Provinces = new List<Province>();
    }
    public List<Province> Provinces { get; set; } 
}

// user model
public int Province { get; set; }

public IEnumerable<SelectListItem> ProvinceList
{
    get
    {
        var list = new SelectList(Provinces, "ProvinceId", "ProvinceName");
        var defaultItem = Enumerable.Repeat(new SelectListItem
        {
            Value = "-1",
            Text = "Select province"
        }, count: 1);

        defaultItem = defaultItem.Concat(list);

        if (Province != 0)
        {
            var selectedItem = Province.ToString();
            var province = defaultItem.First(p => p.Value.Equals(selectedItem));
            province.Selected = true;
        }

        return defaultItem;
    }
}

Object reference not set to an instance of an object.

Stack Trace:

[NullReferenceException: Object reference not set to an instance of an object.] ASP._Page_Views_user_CreateMember_cshtml.Execute() in c:UsersMikedocumentsvisual studio 2012ProjectsGymManagementGymManagement.UIViewsUserCreateMember.cshtml:46 System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +279 System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +124 System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +180 System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +379 System.Web.Mvc.<>c__DisplayClass1a.b__17() +32 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func 1 continuation) +613 System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList 1 filters, ActionResult actionResult) +263 System.Web.Mvc.Async.<>c__DisplayClass25.b__22(IAsyncResult asyncResult) +240 System.Web.Mvc.<>c__DisplayClass1d.b__18(IAsyncResult asyncResult) +28 System.Web.Mvc.Async.<>c__DisplayClass4.b__3(IAsyncResult ar) +15 System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +53 System.Web.Mvc.Async.<>c__DisplayClass4.b__3(IAsyncResult ar) +15 System.Web.Mvc.<>c__DisplayClass8.b__3(IAsyncResult asyncResult) +42 System.Web.Mvc.Async.<>c__DisplayClass4.b__3(IAsyncResult ar) +15 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +606 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +288


Only you can step through an debug your code to determine which object is null and hence throwing the exception. But the real issue is that you have over complicated a simple concept with a lot of pointless code. It can simply be

View model

public Class UserViewModel
{
  ... // other properties of User
  [Display(Name = "Province")]
  [Required(ErrorMessage ="Please select a province")]
  public int ProvinceID { get; set; }
  public SelectList ProvinceList { get; set; }
}

Controller

public ActionResult Create()
{
  UserViewModel model = new UserViewModel();
  ConfigureViewModel(model);
  return View(model);
}

public ActionResult Create(UserViewModel model)
{
  if (!ModelState.IsValid)
  {
    ConfigureViewModel(model);
    return View(model);
  }
  // Save and redirect
}

private void ConfigureViewModel(UserViewModel model)
{
  var provinces = serviceClient.GetProvinces();
  model.ProvinceList = new SelectList(provinces, "ProvinceId", "ProvinceName");
}

View

@model UserViewModel
@using(Html.BeginForm())
{
  ....
  @Html.LabelFor(m => m.ProvinceID)
  @Html.DropDownListFor(m => m.ProvinceID, Model.ProvinceList, "Please select", new { @class="inputField" })
  @Html.ValidationMessageFor(m => m.ProvinceID)
  ....
  <input type="submit" />
}

Check that every "ProvinceId" values are not nulls, because you have

var list = new SelectList(Provinces, "ProvinceId", "ProvinceName");

and then

var province = defaultItem.First(p => p.Value.Equals(selectedItem));

So based on Stephen's example, I stripped my view back and gradually added elements back in. As it turns out, my business address province was conflicting with my personal address province. The issue was tunnel vision combined with a bizarre location for the null reference exception. Thanks everyone for your ideas and help!

链接地址: http://www.djcxy.com/p/72696.html

上一篇: Umbraco当没有当前PublishedContentRequest时,无法呈现宏

下一篇: 为什么在我的DropDownListFor中发布一个空的异常?