Next, a new dialog will pop up for selecting the template. We are going to choose MVC template and click OK.
Once our project is created, we will add ADO.NET Entity Data Model.
Adding ADO.NET Entity Data Model
Right-click on the project name, click Add >> Add New Item.
A dialog box will pop up. Inside Visual C#, select Data >> ADO.NET Entity Data Model, and enter the name for your DbContext model as SysComments, then click Add.
As you can see, we have 4 model contents. We are selecting the first approach (EF Designer from database).
As you can see below, we need to select server name, then via drop-down list connected to a database section, you must choose your database name and finally click OK.
For the next step, the dialog Entity Data Model Wizard will pop up for choosing objects which will be used in our application. We are selecting all the tables except sysdiagrams and click Finish.
Finally, we can see that EDMX model generates all objects, as shown below.
Create a Controller
Now, we are going to create a Controller. Right-click on the Controllers folder> > Add >> Controller>> selecting MVC 5 Controller - Empty>> click Add. In the next dialog, name the controller CommentsController and then click Add.
CommentsController.cs
Here, we have used Get Users action in order to authenticate user by providing her/his username. If the user exists in users table, we will redirect him to Get Posts action, otherwise the following message ‘username does not exist’ will be displayed.
- [HttpGet]
- public ActionResult GetUsers()
- {
- return View();
- }
-
- [HttpPost]
- public ActionResult GetUsers(string username)
- {
- User user = dbContext.Users.Where(u => u.Username.ToLower() == username.ToLower())
- .FirstOrDefault();
-
- if(user != null)
- {
- Session["UserID"] = user.UserID;
- return RedirectToAction("GetPosts");
- }
-
- ViewBag.Msg = "Username does not exist !";
- return View();
- }
GetUsers.cshtml
- @{
- ViewBag.Title = "GetUsers";
- }
-
-
- @using (Html.BeginForm("GetUsers", "Comments", FormMethod.Post))
- {
- <div class="blockUser" style="width: 44%; margin: 16% 26%;">
-
- <div style="margin-left: 23%;">
- <input type="text" class="form-control input-lg" name="username" placeholder="Username" /><br />
- <input type="submit" class="btn btn-success btn-lg" value="Let's GO ^_^" style="width: 75%;" />
- </div>
-
- </div>
-
- }
-
- @if (ViewBag.Msg != null)
- {
- <div class="alert alert-danger" role="alert">Oups! @ViewBag.Msg</div>
- }
In order to display all posts, we have created Get Posts action which selects all posts from posts table, then displayed them within GetPosts.cshtml by using foreach loop.
- [HttpGet]
- public ActionResult GetPosts()
- {
- IQueryable<PostsVM> Posts = dbContext.Posts
- .Select(p => new PostsVM
- {
- PostID = p.PostID,
- Message = p.Message,
- PostedDate = p.PostedDate.Value
- }).AsQueryable();
-
- return View(Posts);
- }
GetPosts.cshtml
- @model IQueryable<CommentsSystemMVC5.ViewModels.PostsVM>
-
- @{
- ViewBag.Title = "GetPosts";
- }
-
- @if (Model != null)
- {
- foreach (var post in Model)
- {
- <div class="panel panel-default" style="width: 80%;">
- <div class="panel-body">
- <div class="avatar">
- <img src="~/Images/avatar.png" class="img-circle" style="width: 60px;"/>
- <span> <a href="" style="font-weight:bold">Leo Messi</a> </span><br />
- <p style="margin-left: 60px; margin-top: -19px;">
- <span class="glyphicon glyphicon-time" aria-hidden="true"></span>
- <time class="timeago" datetime="@post.PostedDate">@post.PostedDate</time>
- </p>
-
- </div>
-
- <div class="postMessage" style="margin-top: 11px; margin-left: 9px;">
- <span class="label label-warning"> @string.Format("Post #{0}", post.PostID) </span><br />
- <p class="message">
- @post.Message
- </p>
- </div>
-
- </div>
- <div class="panel-footer">
- <button type="button" class="btn btn-default Comment" data-id="@post.PostID" value="Comment">
- <span class="glyphicon glyphicon-comment" aria-hidden="true"></span> Comment
- </button>
-
- </div>
- <div id="@string.Format("{0}_{1}","commentsBlock", post.PostID)" style="border: 1px solid #f1eaea; background-color: #eaf2ff;">
-
- <div class="AddComment" style="margin-left: 30%; margin-bottom: 5px; margin-top: 8px;">
- <input type="text" id="@string.Format("{0}_{1}", "comment", post.PostID)" class="form-control" placeholder="Add a Comment ..." style="display: inline;" />
- <button type="button" class="btn btn-default addComment" data-id="@post.PostID"><span class="glyphicon glyphicon-comment" aria-hidden="true"></span></button>
- </div>
-
- </div>
-
-
-
- </div>
- }
- }
-
- @section Scripts
- {
-
- <script type="text/javascript">
-
- $(document).ready(function () {
-
-
-
- $('.Comment').on('click', function () {
-
- var id = $(this).attr("data-id");
- var allCommentsArea = $('<div>').addClass('allComments_' + id);
-
-
- $.ajax({
-
- type: 'GET',
- url: '@Url.Action("GetComments", "Comments")',
- data: { postId: id },
- success: function (response) {
-
- if ($('div').hasClass('allComments_' + id + ''))
- {
- $('div[class=allComments_' + id + ']').remove();
- }
-
-
-
- allCommentsArea.html(response);
- allCommentsArea.prependTo('#commentsBlock_' + id);
-
-
- },
- error: function (response) {
- alert('Sorry: Comments cannot be loaded !');
- }
-
-
- })
-
- });
-
-
- $('.addComment').on('click', function () {
-
- var postId = $(this).attr('data-id');
- var commentMsg = $('#comment_' + postId).val();
- var dateTimeNow = new Date();
-
-
- var comment = {
- CommentMsg: commentMsg,
- CommentedDate: dateTimeNow.toLocaleString()
- };
-
- $.ajax({
-
- type: 'POST',
- url: '@Url.Action("AddComment", "Comments")',
- data: { comment, postId },
- success: function (response) {
-
- $('div[class=allComments_' + postId + ']').remove();
-
- var allCommentsArea = $('<div>').addClass('allComments_' + postId);
- allCommentsArea.html(response);
-
- allCommentsArea.prependTo('#commentsBlock_' + postId);
-
- },
- error: function (response) {
- alert('Sorry: Something Wrong');
- }
-
- });
-
- });
-
- jQuery("time.timeago").timeago();
-
- });
-
- </script>
-
-
- }
As you can see, Get Comments action is responsible to get all comments related to the given post id, then we will display them within _MyComments partial view.
- public PartialViewResult GetComments(int postId)
- {
- IQueryable<CommentsVM> comments = dbContext.Comments.Where(c => c.Post.PostID == postId)
- .Select(c => new CommentsVM
- {
- ComID = c.ComID,
- CommentedDate = c.CommentedDate.Value,
- CommentMsg = c.CommentMsg,
- Users = new UserVM
- {
- UserID = c.User.UserID,
- Username = c.User.Username,
- imageProfile = c.User.imageProfile
- }
- }).AsQueryable();
-
- return PartialView("~/Views/Shared/_MyComments.cshtml", comments);
- }
Shared/_MyComments.cshtml
To add partial view, from the Solution Explorer, expand Views folder, right click on Shared folder >> Add >> View. Don’t forget to check "Create as a partial view" option.
- @model IQueryable<CommentsSystemMVC5.ViewModels.CommentsVM>
- @using CommentsSystemMVC5.ViewModels;
-
-
- @if (Model != null)
- {
-
- foreach (CommentsVM comment in Model)
- {
- <div class="row" style="width: 100.3%; border-bottom: 1px solid #d2cece; margin-right: -14px; margin-left: -1px;">
-
- <div class="col-md-4" style="width: 21%;">
- <div class="userProfil" style="margin-left: 9px; margin-top: 12px;">
- <img src="~/Images/@comment.Users.imageProfile" class="img-circle" style="width: 46px; height: 53px; border: 1px solid #bcb8b8;" />
- <a href="#" style="margin-left: 5px; font-weight: bold; font-size: 13px;"> @comment.Users.Username </a>
- </div>
- </div>
-
- <div class="col-md-7" style="width: 60%;">
- <div class="commentDetails">
- <p style="margin-top: 27px; font-size: 13px; color: #9c9898;"> @comment.CommentMsg </p>
- <a href="#" class="Reply" data-id="@comment.ComID">Reply</a>
- <div class="@string.Format("{0}_{1}", "ReplayComments", comment.ComID)" style="display:none;">
-
-
- <div class="ReplayCommentInput" style="margin-left: 3%; margin-bottom: 5px; margin-top: 8px;">
- <input type="text" id="@string.Format("{0}_{1}", "inputReplay", comment.ComID)" class="form-control" placeholder="Add a Comment ..." style="display: inline;" />
- <button type="button" class="btn btn-default ReplyAddComment" data-id="@comment.ComID"><span class="glyphicon glyphicon-comment" aria-hidden="true"></span></button>
- </div>
-
- </div>
-
- </div>
- </div>
-
- <div class="col-md-1" style="width: 19%;">
- <div class="commentDate">
- <span class="glyphicon glyphicon-time" aria-hidden="true"></span>
- <time class="timeago" style="margin-top: 27px; font-size: 13px; color: #9c9898; margin-left: 4px;" datetime="@comment.CommentedDate">@comment.CommentedDate</time>
-
- </div>
- </div>
- </div>
-
- }
-
-
- }
-
-
- <script type="text/javascript">
-
- $(document).ready(function () {
-
-
- $('.Reply').on('click', function () {
-
- var ComID = $(this).attr('data-id');
-
- $.ajax({
-
- type: 'GET',
- url: '@Url.Action("GetSubComments", "Comments")',
- data: { ComID },
- success: function (response) {
-
- if ($('div').hasClass('zoneReply_' + ComID + ''))
- {
- $('div [class=zoneReply_' + ComID + ']').remove();
- }
-
- var selReply = $("<div>").addClass('zoneReply_' + ComID);
-
- selReply.append(response);
- selReply.prependTo($('.ReplayComments_' + ComID));
-
- $('.ReplayComments_' + ComID).show();
-
- },
- error: function (response) {
- alert('something Wrong');
- }
- });
-
- });
-
-
- $('.ReplyAddComment').on('click', function () {
-
- var ComID = $(this).attr('data-id');
- var CommentMsg = $('#inputReplay_' + ComID).val();
- var dateTimeNow = new Date();
-
- var subComment = {
- CommentMsg: CommentMsg,
- CommentedDate: dateTimeNow.toLocaleString()
- };
-
-
- $.ajax({
-
- type: 'POST',
- url: '@Url.Action("AddSubComment", "Comments")',
- data: { subComment, ComID },
- success: function (response) {
-
- if ($('div').hasClass('zoneReply_' + ComID + '')) {
- $('div [class=zoneReply_' + ComID + ']').remove();
- }
-
- var selReply = $("<div>").addClass('zoneReply_' + ComID);
-
- selReply.append(response);
- selReply.prependTo($('.ReplayComments_' + ComID));
-
- $('.ReplayComments_' + ComID).show();
-
- },
- error: function (response) {
- alert('something Wrong');
- }
- });
-
- });
-
- jQuery("time.timeago").timeago();
-
-
- })
- </script>
Adding a comment is very simple. We have created Add Comment action which accepts the comment and posts id parameters then persisting comment object into comments table by using add extension method.
- [HttpPost]
- public ActionResult AddComment(CommentsVM comment, int postId)
- {
-
- Comment commentEntity = null;
- int userId = (int)Session["UserID"];
-
- var user = dbContext.Users.FirstOrDefault(u => u.UserID == userId);
- var post = dbContext.Posts.FirstOrDefault(p => p.PostID == postId);
-
- if (comment != null)
- {
-
- commentEntity = new EDMX.Comment
- {
- CommentMsg = comment.CommentMsg,
- CommentedDate = comment.CommentedDate,
- };
-
-
- if (user != null && post != null)
- {
- post.Comments.Add(commentEntity);
- user.Comments.Add(commentEntity);
-
- dbContext.SaveChanges();
-
- }
- }
-
- return RedirectToAction("GetComments", "Comments", new { postId = postId });
- }
Here, Get subComments is used to select all sub comments related to the given comID (comment id). Then, we will display them within _MySubComments partial view.
- [HttpGet]
- public PartialViewResult GetSubComments(int ComID)
- {
- IQueryable<SubCommentsVM> subComments = dbContext.SubComments.Where(sc => sc.Comment.ComID == ComID)
- .Select(sc => new SubCommentsVM
- {
- SubComID = sc.SubComID,
- CommentMsg = sc.CommentMsg,
- CommentedDate = sc.CommentedDate.Value,
- User = new UserVM
- {
- UserID = sc.User.UserID,
- Username = sc.User.Username,
- imageProfile = sc.User.imageProfile
- }
- }).AsQueryable();
-
- return PartialView("~/Views/Shared/_MySubComments.cshtml", subComments);
- }