简体   繁体   中英

ASP.NET MVC DropDownList NullReferenceException

Im having a problem with my dropDownList giving me a NullReferenceException and I don't know why.

I want to post a post where you can choose with the DropDownList which Category it belongs to.

Here is some of my code:

PostModel

public class Post
    {
        [Key]
        public int PostID { get; set; }

        [Display(Name = "Idea Title")]
        public String Title { get; set; }

        [Display(Name = "Description")]
        public String DescText { get; set; }

        [Display(Name = "Votes")]
        public int Votes { get; set; }

        [Display(Name = "Comments")]
        public int CommentCount { get; set; }

        [Display(Name = "Posted:")]
        [DataType(DataType.DateTime)]
        [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
        public DateTime CreatedDate { get; set; }

        [Display(Name = "Last Edited:")]
        [DataType(DataType.DateTime)]
        [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
        public DateTime? EditedDate { get; set; }

        public String UserName { get; set; }

        public virtual Status Status { get; set; }
        public virtual Category Category { get; set; }
        public virtual Department Department { get; set; }
        public virtual ICollection<Comment> Comments { get; set; }
    }

PostViewModel

public class PostCreateViewModel
    {
        [Required]
        [Display(Name = "Title")]
        [MinLength(10, ErrorMessage = "The title must be at least 10 characters long.")]
        [StringLength(100, ErrorMessage = "The title cannot be longer than 100 characters.")]
        public String Title { get; set; }

        [Required]
        [DataType(DataType.MultilineText)]
        [MinLength(50, ErrorMessage = "The description of your idea should be at least 50 characters long.")]
        public String DescText { get; set; }

        [Required]
        [Display(Name = "Category")]
        public int SelectedCategoryId { get; set; }
        public IEnumerable<SelectListItem> Categories { get; set; }
    }

CategoryModel

    public class Category
    {
        [Key]
        public int CategoryID { get; set; }

        [Display(Name = "Category Name")]
        public String CategoryName { get; set; }
    }

    public class DbCategories
    {
        private IdeaContext context = new IdeaContext();

        public List<Category> GetCategories()
        {
            return context.Categories.ToList();
        }
    }

PostController UPDATED

        private IEnumerable<SelectListItem> GetCategories()
        {
            var dbCategories = new DbCategories();
            var categories = dbCategories
                             .GetCategories()
                             .Select(x =>
                                     new SelectListItem
                                     {
                                         Value = x.CategoryID.ToString(),
                                         Text = x.CategoryName
                                     });
            return new SelectList(categories, "Value", "Text");
        }

        [HttpGet]
        public ActionResult Create()
        {
            var model = new PostCreateViewModel { Categories = GetCategories() };
            return View(model);
        }

        [HttpPost]
        public ActionResult Create(PostCreateViewModel model)
        {
            model.Categories = GetCategories();
            if (ModelState.IsValid)
            {
                var post = new Post();

                // From ViewModel
                post.Title = model.Title;
                post.DescText = model.DescText;

                var dbCategories = new DbCategories();
                var categories = dbCategories.GetCategories();

                post.Category = categories.FirstOrDefault(x => x.CategoryID == model.SelectedCategoryId);

                // Controller created
                post.CreatedDate = DateTime.Now;
                post.Votes = 0;
                post.CommentCount = 0;
                post.Status.StatusName = "Active";
                post.Department = null;
                post.UserName = User.Identity.Name;

                context.Posts.Add(post);
                context.SaveChanges();

                return RedirectToAction("Index");
            }
            else
            {
                return View();
            }
        }

And my View

@model WebApplication3.Models.ViewModels.PostCreateViewModel

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-group top-space-large">
        @Html.LabelFor(model => model.Title, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Title, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Title, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(m => m.SelectedCategoryId, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownListFor(m => m.SelectedCategoryId, Model.Categories, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.SelectedCategoryId, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group top-space-large">
        @Html.LabelFor(model => model.DescText, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.DescText, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.DescText, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group top-space-large">
        <button type="submit" class="btn btn-default">Submit</button>
    </div>
}

Stack Exception

System.NullReferenceException was unhandled by user code
  HResult=-2147467261
  Message=Object reference not set to an instance of an object.
  Source=App_Web_jqgoppva
  StackTrace:
       at ASP._Page_Views_Post_Create_cshtml.Execute() in \\etj\My Documents\Visual Studio 2013\Projects\WebApplication3\WebApplication3\Views\Post\Create.cshtml:line 24
       at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()
       at System.Web.Mvc.WebViewPage.ExecutePageHierarchy()
       at System.Web.WebPages.StartPage.RunPage()
       at System.Web.WebPages.StartPage.ExecutePageHierarchy()
       at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)
       at System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance)
       at System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer)
       at System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context)
       at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
       at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult)
       at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilterRecursive(IList`1 filters, Int32 filterIndex, ResultExecutingContext preContext, ControllerContext controllerContext, ActionResult actionResult)
  InnerException: 

Why is this happening? When I try to post the form I get "Object reference not set to an instance of an object" in the View on the line for the DropDownList. The context.Categories is not empty. It contains "Web" with id 28 and "Environment" with id 31.

The only reason I see this to happen is because on POST action you want to use Model.Categories which is not persisted. You have to call again the GetCatgories() method in action Create .

You get the NullReference exception because post.Category is null and you can't access a property of a null object, post.Category.CategoryID = model.SelectedCategoryId; . You have to query the Category from database based on the SelectedCategoryId .

[HttpPost]
public ActionResult Create(PostCreateViewModel model)
{
    model.Categories = GetCategories(); // call again, Categories don't persist in a POST.
    if (ModelState.IsValid)
    {
        var post = new Post();

        // ...
        post.Category = context.Categories.FirstOrDefault(x => x.CategoryId == model.SelectedCategoryId);
        // ...

        return RedirectToAction("Index");
    }

    return View(model);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM