Creating a multi level comments system in asp.net mvc - c#

I'm currently working on a blog written in asp.net mvc. I have a table that stores comments with the following model
public partial class Comment
{
public int CommentId { get; set; }
public string Comment { get; set; }
public System.DateTime CommentDate { get; set; }
public int AuthorId { get; set; }
public int PostId { get; set; }
public int CategoryId { get; set; }
public virtual Category Category { get; set; }
public virtual Post Post { get; set; }
public virtual UserProfile UserProfile { get; set; }
}
Currently the comment is still a one-level comment i.e a user cannot reply to a comment. How can i implement a multilevel comment system in such a way that a comment can have a reply and that reply can have another reply and so on.

Add parentCommentId column which refers to the Comments table.
After that in each reply :
If it is a direct reply to the post, leave parentCommentId column empty
If it is a reply to a previously posted comment, put that comment id in this column. In this case you can leave postid column empty or not. It depends on your favor!

first i need to excuse you for my bad English if you want a tree of comments as i understood like you comment and reply and you need to reply on my reply thats make u should add 1 more field you can call it subcomment id which it will be as an forign key to comment table " self relation " and this subcommenid will hold the parent comment ID

But essentially..
I don't know how your POST Class is defined.. Is it a collection? Or a simple class? If it's not a collection you want to make it as so..
Inside your Comment Class Change..
public virtual Post Post { get; set; }
to:
Public virtual ICollection<Post> Posts { get; set; }
or define it in another class private field..
This will defines the relationship and will be your navigation property as well..
So in your controller you can return both tables like such...
public ActionResult GetComments(int id)
{
db.context.comments.Include("Posts").Where(c => c.CommentID == id).ToList();
}

You need create custom Htmlhelper / TreeView and pass data in to this helper. Data model will be according to Mahmoud Moravej.

Related

Recovery of class containing a list returns a null list

I have a couple of classes:
public class MyGoalsModel
{
[Key]
public string Name { get; set; }
/*Some local bools*/
public List<MyGoalString> myGoals { get; set; }
}
public class MyGoalString
{
public int MyGoalStringID { get; set; }
public string GoalString { get; set; }
public bool Selected { get; set; }
}
I can populate them correctly, and the code (EF?) generates the necessary hidden foreign keys to link them (all ok in SQL) and recover the information for MyGoalsModel, but the List is always null.
I use the following to get the entry I want:
MyGoalsModel goals = db.MyGoals.Find(Name);
but when I investigate the code goals.MyGoals is always null.
Am I missing something, is there a better way to recover the information with the lists present?
Add the keyword virtual so EF can create a proxy for your List and lazy load the data when needed.
Edit: Or as stated in the accepted answer in this question.

Possible redundancy in a table generated by Entity Framework

In my project, users can like a comment or a post, similar to Facebook likes. For this purpose, I created an abstract base class called Like keeping the if of the user who liked the post or the comment, and the datetime of the action. I have CommentLike class inheriting from Like class, which only have Comment property, and similarly, I have PostLike class inheriting from Like class, which only have Post property.
I use Entity Framework, and my database is generated successfully. In the generated database, there are CommentId, PostId, and Discriminator fields in the table. The thing is, if users like only one comment, and like only posts, then the CommentId field in the database will stay as null redundantly. I wonder if this is a problem. What if instead of these three fields, I only have one field, called RelatedItem which can indicate the associated Comment or the Post. In this case I can not define foreignkey I guess. Is this also a problem?
What would be best approach in such a situation?
public abstract class Like
{
public int LikeId { get; set; }
[Required]
public DateTime WhenLiked { get; set; }
[ForeignKey("WhoLiked")]
public string UserId { get; set; }
public Person WhoLiked { get; set; }
}
public class PostLike : Like
{
[Required]
public Post Post { get; set; }
[ForeignKey("Post")]
public int PostId { get; set; }
}
public class CommentLike : Like
{
[ForeignKey("Comment")]
public int CommentId { get; set; }
[Required]
public Comment Comment { get; set; }
}
Here is the database generated:

Setting up routing in order to GET an entity using different "id"s in WebApi

Say for example I have the following model:
public class Comment
{
public long Id { get; set; }
public long UserId { get; set; }
public long AccountId { get; set; }
public long EventId { get; set; }
public string Body { get; set; }
public System.DateTime TimeStamp { get; set; }
}
I already have it set up so that GET /comments/ returns all comments for your account
and GET /comments/123 return the one comment. This is not a problem via default routing.
But I wonder how to be able to have two extra GET endpoints, one being able to return all comments for an EventId and the other, all comments for a UserId.
Any thoughts would be appreciated!
you can alter your routing to look for the method name (the action) :
{controller}/{action}/{id}
then you can have multiple GET methods that will clearly state their intent:
GetCommentsForUser();
GetCommentsForEvent();
GetCommentsForAccount();
and of course the URL will be
/comments/GetCommentsForUser/123

How to auto save complex model with lists of models in it?

I am creating a quiz creator module. There are 5 subjects. Each subject has 2000 questions.
Say, it's called "Create Full model test", and it will contain 100 questions, 20 questions from 5 subjects. So, 20*5=100
In the UI, creator will first select "Create full model test" from the drop down. Suppose if he select the "Full model test". He will have to select one subject among 5 subjects, then he will have to select 20 questions per subject. and then will have to save them into that "Full model test" segment.
If he selects English, he will have to select 20 questions, then he will have to select another subject, for example, physics, and will have to select another 20 questions for physics, then he will have to select maths and then will have to select another 20 questions and so on for maths. Finally 100 questions will be submitted by the form.
Now, my question is, how can I auto save the selected questions into that "Full model test" segment, so that he can continue saving 5 subject's questions before he submit the form.
Here is my Department model:
namespace MvcBCS.Models
{
public class Department
{
[Key]
public int DepartmentId { get; set; }
public string DepartmentName { get; set; }
public string DepartmentCode { get; set; }
public virtual ICollection<Subject> Subject { get; set; }
public virtual ICollection<Section> Section { get; set; }
public virtual ICollection<Subsection> Subsection { get; set; }
}
}
Here is my Subject Model:
namespace MvcBCS.Models
{
public class Subject
{
[Key]
public int SubjectId { get; set; }
public string SubjectName { get; set; }
public string SubjectCode { get; set; }
public int DepartmentId { get; set; }
public virtual Department Department { get; set; }
public virtual ICollection<Section> Section { get; set; }
}
}
Here is the Section Model:
namespace MvcBCS.Models
{
public class Section
{
[ForeignKey("Department")]
public int? DepartmentId { get; set; }
public virtual Department Department { get; set; }
[ForeignKey("Subject")]
public int? SubjectId { get; set; }
public virtual Subject Subject { get; set; }
[Key]
public int SectionId { get; set; }
public string SectionName { get; set; }
}
}
Here is the subjection model:
namespace MvcBCS.Models
{
public class Subsection
{
[ForeignKey("Department")]
public int? DepartmentId { get; set; }
public virtual Department Department { get; set; }
[ForeignKey("Subject")]
public int? SubjectId { get; set; }
public virtual Subject Subject { get; set; }
[ForeignKey("Section")]
public int? SectionId { get; set; }
public virtual Section Section { get; set; }
[Key]
public int SubsectionId { get; set; }
public string SubsectionName { get; set; }
public string SubsectionCode { get; set; }
}
}
All that you need is just to store all temporary data on client side.
And when you get complete pasts or even full set of data - send it to server using POST/JSON/XML/etc.
I think it such case it will be better for you to use some kind of JavaScript frameworks, for example KnockoutJS, which with only few click's and couple lines of code will allows you to store all your data on client side in object-based model.
Anyway if you will use any framework or not, you should use JavaScript to store all of your data, including question, answers and subjects. JavaScript will allows you to store,validate and send all data that you need.
To make your work with JavaScript easier and faster - you can use jQuery library which contains functions for interaction with both DOM structure and server side.
To make learning of KnockoutJS easier just use tutorial: http://learn.knockoutjs.com
This is how I am going to attempt it.
business rules:
- full model test will be completed if all the subjects questions are submitted by certain user.
Assumption: we knew in advance that we have five subjects. Therefore
public enum Subject
{
English,
Physics,
...
}
Test Poco entity structure:
public class Test
{
public int Id{get;set;}
public User CreatedBy{get;set;}
public Subject Subject{get;set;}
public bool IsFullTestCompleted{get;set;}
public string Question1{get;set;}
public string Question2{get;set;}
...
}
Assumptions:
You can use partial views/ajax/Jquery/Angularjs/Knockout whatever suits you best in your problem context to implement it to auto save the changes
You will add necessary view model with appropriate validation annotations/attributes
you will add validation where necessary.
you will add/update the Test entity. like for first subject you will add data into Test entity, and subsequently you will update it.
Hope it will be helpful

ASP.NET Identity - ApplicationUser and my custom models / entities

All,
I have read this article:
How AspNet Identity with my model
where the ApplicationUser has an additing property of
public int AddressId { get; set; }
that is a new property on the ApplicationUser.
But what I am wondering is what if I have a custom entity of my own and I want it to have a property that relates to the Application user:
public class Book
{
public int Id { get; set; }
public string Title { get; set; }
public ApplicationUser CurrentlyBorrowedBy { get; set; }
}
or
public class Book
{
public int Id { get; set; }
public string Title { get; set; }
public Guid CurrentlyBorrowedBy { get; set; }
}
The reason I might want to do this is so I can call a method like GetAllBooksBorrowedForUser(userid) for example.
Do I set the properties type to ApplicationUser as show above
or
use a Guid because the DataType of the Id on ApplicationUser is a Guid
or
is this the completely wrong way to do it?
All suggestions welcome.
Note: this is just psuedo code as I just want an understanding of this before I dive into my project.
thanks
Russ
From what I know, it should be:
public int CurrentlyBorrowedByID { get; set; }
public virtual ApplicationUser CurrentlyBorrowedBy { get; set; }
Where the ApplicationUser instance allows you to easily navigate
All,
Of course after finishing writing my question I found the answer right in front of me.
The sample and blog post written by pranav rastogi here:
http://blogs.msdn.com/b/webdev/archive/2013/10/20/building-a-simple-todo-application-with-asp-net-identity-and-associating-users-with-todoes.aspx
explains how do do what I am talking about.
Still, feel tree to comment as there is more than one way to skin a cat.
thanks
Russ

Categories