简体   繁体   中英

2 models in 1 view MVC4

I have two models as shown below:

One:

 [Validator(typeof(BlogPostValidator))]
    public partial class BlogPostModel : BaseNopEntityModel
    {
        public BlogPostModel()
        {
            Tags = new List<string>();
            Comments = new List<BlogCommentModel>();
            AddNewComment = new AddBlogCommentModel();
        }

        public string SeName { get; set; }

        public string Title { get; set; }

        public string Body { get; set; }

        public bool AllowComments { get; set; }

        public int NumberOfComments { get; set; }

        public DateTime CreatedOn { get; set; }

        public IList<string> Tags { get; set; }

        public IList<BlogCommentModel> Comments { get; set; }
        public AddBlogCommentModel AddNewComment { get; set; }

        public BlogCommentModel blogcommentmodel { get; set; }
    }

two:

 public partial class BlogCommentModel : BaseNopEntityModel
    {
        public int CustomerId { get; set; }

        public string CustomerName { get; set; }

        public string CustomerAvatarUrl { get; set; }

        public string CommentText { get; set; }

        public DateTime CreatedOn { get; set; }

        public bool AllowViewingProfiles { get; set; }

        public int CommentParentID { get; set; }

        public IList<BlogComment> ChildCommentList { get; set; }//netra
    }

I want to make use of ChildCommentList from BlogCommentModel to show nested comments.

My View:

@model BlogPostModel
@using Nop.Web.Models.Blogs;
 @if (Model.AllowComments)
        {
            <div class="clear">
            </div>
            <fieldset class="new-comment" id="addcomment">
                <legend class="title">@T("Blog.Comments.LeaveYourComment")</legend>
                @using (Html.BeginForm())
                {
                    <div>
                        <div class="message-error">@Html.ValidationSummary(true)</div>
                        @{
                    string result = TempData["nop.blog.addcomment.result"] as string;
                        }
                        @if (!String.IsNullOrEmpty(result))
                        {
                            <div class="result">@result</div>
                        }
                        <div class="forms-box">
                            <div class="inputs">
                                @Html.LabelFor(model => model.AddNewComment.CommentText)
                                <div class="input-box">
                                    @Html.TextAreaFor(model => model.AddNewComment.CommentText, new { @class = "comment-text" })
                                </div>
                                @Html.ValidationMessageFor(model => model.AddNewComment.CommentText)
                            </div>
                            @if (Model.AddNewComment.DisplayCaptcha)
                            {
                                <div class="captcha-box">
                                    @Html.Raw(Html.GenerateCaptcha())
                                </div>
                                <div class="clear">
                                </div>
                            }
                        </div>
                        <div class="clear">
                        </div>
                        <div class="buttons">
                            <input type="submit" name="add-comment" class="button-1 blog-post-add-comment-button" value="@T("Blog.Comments.SubmitButton")" />
                        </div>
                    </div>
                }
            </fieldset>
                if (Model.Comments.Count > 0)
                {
            <div class="clear">
            </div>
            <div class="comment-list">
                <div class="title">
                    @T("Blog.Comments")
                </div>
                <div class="clear">
                </div>
                @foreach (var comment in Model.Comments)
                {
                    <div class="blog-comment">
                        <div class="comment-info">
                            <div class="user-info">
                                @if (comment.AllowViewingProfiles)
                                {
                                    <a href="@Url.RouteUrl("CustomerProfile", new { id = comment.CustomerId })" class="username">@(comment.CustomerName)</a>
                                }
                                else
                                {
                                    <span class="username">@(comment.CustomerName)</span>
                                }
                                <div class="avatar">
                                    @if (!String.IsNullOrEmpty(comment.CustomerAvatarUrl))
                                    {
                                        <img src="@(comment.CustomerAvatarUrl)" class="avatar-img" title="avatar" alt="avatar" />
                                    }
                                </div>
                            </div>
                        </div>
                        <div class="comment-content">
                            <div class="comment-time">
                                @T("Blog.Comments.CreatedOn"): <span class="stat-value">@comment.CreatedOn.ToString("g")</span>
                            </div>
                            <div class="comment-body">
                                @Html.Raw(Nop.Core.Html.HtmlHelper.FormatText(comment.CommentText, false, true, false, false, false, false))
                            </div>
                        </div>
                        @Html.Widget("blogpost_page_inside_comment")
                    </div>
                    <div class="clear">
                    </div>
                    <div>
                     @foreach(var childcomments in Model.blogcommentmodel.ChildCommentList)
                     {
                      @Html.Raw(Nop.Core.Html.HtmlHelper.FormatText(childcomments.CommentText, false, true, false, false, false, false))
                     }
                    </div>
                }
                <div class="buttons">
                    <input type="submit" id="replyto" name="reply-comment" class="button-1 blog-post-add-comment-button" value="@T("Blog.Comments.ReplyButton")" />
                </div>
            </div>
                }
        }

Error occurred on :

@foreach(var childcomments in Model.blogcommentmodel.ChildCommentList)
                         {
                          @Html.Raw(Nop.Core.Html.HtmlHelper.FormatText(childcomments.CommentText, false, true, false, false, false, false))
                         }
                        </div>
                    }

NullReferenceException was unhandled by usercode -{"Object reference not set to an instance of an object."}

My controller code for ActionResult:

public ActionResult BlogPost(int blogPostId)
        {
            if (!_blogSettings.Enabled)
                return RedirectToRoute("HomePage");

            var blogPost = _blogService.GetBlogPostById(blogPostId);
            if (blogPost == null ||
                (blogPost.StartDateUtc.HasValue && blogPost.StartDateUtc.Value >= DateTime.UtcNow) ||
                (blogPost.EndDateUtc.HasValue && blogPost.EndDateUtc.Value <= DateTime.UtcNow))
                return RedirectToRoute("HomePage");

            var model = new BlogPostModel();
            **PrepareBlogPostModel(model, blogPost, true);**

            return View(model);
        }

Below method called in above ActionResult:

 [NonAction]
        protected void PrepareBlogPostModel(BlogPostModel model, BlogPost blogPost, bool prepareComments)
        {
            if (blogPost == null)
                throw new ArgumentNullException("blogPost");

            if (model == null)
                throw new ArgumentNullException("model");

            model.Id = blogPost.Id;
            model.SeName = blogPost.GetSeName();
            model.Title = blogPost.Title;
            model.Body = blogPost.Body;
            model.AllowComments = blogPost.AllowComments;
            model.CreatedOn = _dateTimeHelper.ConvertToUserTime(blogPost.CreatedOnUtc, DateTimeKind.Utc);
            model.Tags = blogPost.ParseTags().ToList();
            model.NumberOfComments = blogPost.ApprovedCommentCount;
            model.AddNewComment.DisplayCaptcha = _captchaSettings.Enabled && _captchaSettings.ShowOnBlogCommentPage;
            if (prepareComments)
            {
               // var blogchildcomment = _blogService.GetAllChildComments();
                var blogComments = blogPost.BlogComments.Where(pr => pr.IsApproved).OrderBy(pr => pr.CreatedOnUtc);
                foreach (var bc in blogComments)
                {
                    var commentModel = new BlogCommentModel()
                    {
                        Id = bc.Id,
                        CustomerId = bc.CustomerId,
                        CustomerName = bc.Customer.FormatUserName(),
                        CommentText = bc.CommentText,
                        CreatedOn = _dateTimeHelper.ConvertToUserTime(bc.CreatedOnUtc, DateTimeKind.Utc),
                        AllowViewingProfiles = _customerSettings.AllowViewingProfiles && bc.Customer != null && !bc.Customer.IsGuest(),
                        CommentParentID = bc.CommentParentID,//Netra
                    };
                    //Netra
                    var comments = _blogService.GetBlogComments(bc.CommentParentID);
                    if (comments != null)
                    {
                        commentModel.ChildCommentList = new List<BlogComment>(); 
                        foreach (var cmnt in comments)
                        {
                            commentModel.ChildCommentList.Add(cmnt);
                        }
                    }

                    if (_customerSettings.AllowCustomersToUploadAvatars)
                    {
                        var customer = bc.Customer;
                        string avatarUrl = _pictureService.GetPictureUrl(customer.GetAttribute<int>(SystemCustomerAttributeNames.AvatarPictureId), _mediaSettings.AvatarPictureSize, false);
                        if (String.IsNullOrEmpty(avatarUrl) && _customerSettings.DefaultAvatarEnabled)
                            avatarUrl = _pictureService.GetDefaultPictureUrl(_mediaSettings.AvatarPictureSize, PictureType.Avatar);
                        commentModel.CustomerAvatarUrl = avatarUrl;
                    }
                    model.Comments.Add(commentModel);
                }
            }
        } 

BlogComment is class which describes the properties.

 public partial class BlogComment : CustomerContent
    {
        /// <summary>
        /// Gets or sets the comment text
        /// </summary>
        public virtual string CommentText { get; set; }

        /// <summary>
        /// Gets or sets the blog post identifier
        /// </summary>
        public virtual int BlogPostId { get; set; }

        /// <summary>
        /// Gets or sets the blog post
        /// </summary>
        public virtual BlogPost BlogPost { get; set; }

        public virtual int CommentParentID { get; set; } //netra
    }

So you have a null somewhere - you need to find out what's null and make it so it's not null; or change the Razor code to something like:

@if(Model.blogcommentmodel != null && Model.blogcommentmodel.ChildCommentList != null)
{
  @* original @foreach statement here *@
}

My first guess would be that you need to create a default constructor for your model. In the constructor, set ChildCommentList = new List<BlogComment>(); .

It looks like you didn't set that in your Controller, which the way that you have your Model set up, would cause ChildCommentList to still be null. With that default constructor, you won't have to worry about your code breaking like this if you miss setting it somewhere.

To answer wnetra's comment, the constructor is on the BlogcommentModel class. So you'll need something like this:

public class BlogcommentModel {
    /* All of the property declarations */
    public IList<BlogComment> ChildCommentList { get; set; }

    /* Constructor for the BlogcommentModel class */
    public BlogcommentModel() {
        ChildcommentList = new List<BlogComment>();
    }
}

Any reference objects should always be instantiated inside a default constructor to ensure they won't be null when trying to reference them in code.

Also see Andras' answer with regard to always doing != null when trying to reference reference objects in your code.

I have removed following code from BlogCommenmodel :

//public int CommentParentID { get; set; }

    //public IList<BlogComment> ChildCommentList { get; set; }//netra

    //public BlogCommentModel()
    //{
    //    ChildCommentList = new List<BlogComment>();
    //}

and introduced in BlogPostModel

 [Validator(typeof(BlogPostValidator))]
public partial class BlogPostModel : BaseNopEntityModel
{
    public BlogPostModel()
    {
        Tags = new List<string>();
        Comments = new List<BlogCommentModel>();
        AddNewComment = new AddBlogCommentModel();
        ChildCommentList = new List<BlogComment>();
    }

    public string SeName { get; set; }

    public string Title { get; set; }

    public string Body { get; set; }

    public bool AllowComments { get; set; }

    public int NumberOfComments { get; set; }

    public DateTime CreatedOn { get; set; }

    public IList<string> Tags { get; set; }

    public IList<BlogCommentModel> Comments { get; set; }
    public AddBlogCommentModel AddNewComment { get; set; }


    //Netra
    public int CommentParentID { get; set; }

    public IList<BlogComment> ChildCommentList { get; set; }//netra

   // public BlogCommentModel blogcommentmodel { get; set; }
}

IN View:

<div>
                            @if (Model.ChildCommentList != null)
                            {
                                foreach (var childcomments in Model.ChildCommentList)
                                {
                                    @Html.Raw(Nop.Core.Html.HtmlHelper.FormatText(childcomments.CommentText, false, true, false, false, false, false))
                                }
                            }
                        </div>

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