简体   繁体   English

ASP.NET MVC DropDownList NullReferenceException

[英]ASP.NET MVC DropDownList NullReferenceException

Im having a problem with my dropDownList giving me a NullReferenceException and I don't know why. 我有一个问题,我的dropDownList给我一个NullReferenceException,我不知道为什么。

I want to post a post where you can choose with the DropDownList which Category it belongs to. 我想发布一个帖子,您可以使用DropDownList选择它所属的类别。

Here is some of my code: 这是我的一些代码:

PostModel 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 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 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 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. 当我尝试发布表单时,我在DropDownList行的视图中得到“对象引用未设置为对象的实例”。 The context.Categories is not empty. context.Categories不为空。 It contains "Web" with id 28 and "Environment" with id 31. 它包含ID为28的“Web”和ID为31的“Environment”。

The only reason I see this to happen is because on POST action you want to use Model.Categories which is not persisted. 我发现这种情况的唯一原因是因为在POST操作中你想使用不持久的Model.Categories You have to call again the GetCatgories() method in action Create . 您必须在操作Create再次调用GetCatgories()方法。

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; 你得到NullReference异常因为post.Categorynull而你无法访问null对象的属性, post.Category.CategoryID = model.SelectedCategoryId; . You have to query the Category from database based on the SelectedCategoryId . 您必须根据SelectedCategoryId从数据库中查询Category

[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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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