Forums Application Using MVC4 and Entity Framework

Hi all in this article I would like to show you how to create a forums application using MVC4 and Entity Framework.

This application mainly covers the following:

  1. Registering a User.
  2. Login.
  3. Create questions on the technology available.
  4. Add reply's to the posted questions.
There were also several things included like getting the last reply posted for the question and also not allowing the user to post questions or replies without logging in.

The database for the current application has the necessary tables and Stored Procedures as follows:
  1. USE [newForumDB]  
  2. GO  
  3.    
  4. /****** Object:  Table [dbo].[tblUser]    Script Date: 02/14/2013 14:21:09 ******/  
  5. SET ANSI_NULLS ON  
  6. GO  
  7.    
  8. SET QUOTED_IDENTIFIER ON  
  9. GO  
  10.    
  11. SET ANSI_PADDING ON  
  12. GO  
  13.    
  14. CREATE TABLE [dbo].[tblUser](  
  15. [UserName] [varchar](50) NOT NULL,  
  16. [EmailID] [varchar](50) NOT NULL,  
  17. [DisplayName] [varchar](50) NOT NULL,  
  18. [DateJoined] [datetime] NOT NULL,  
  19. [Password] [varchar](50) NOT NULL,  
  20. [Photo] [image] NULL,  
  21.  CONSTRAINT [PK_tblUser] PRIMARY KEY CLUSTERED   
  22. (  
  23. [UserName] ASC  
  24. )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ONON [PRIMARY]  
  25. ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]  
  26.    
  27. GO  
  28.    
  29. SET ANSI_PADDING OFF  
  30. GO  
  31.    
  32. USE [newForumDB]  
  33. GO  
  34.    
  35. /****** Object:  Table [dbo].[tblTechnology]    Script Date: 02/14/2013 14:21:54 ******/  
  36. SET ANSI_NULLS ON  
  37. GO  
  38.    
  39. SET QUOTED_IDENTIFIER ON  
  40. GO  
  41.    
  42. SET ANSI_PADDING ON  
  43. GO  
  44.    
  45. CREATE TABLE [dbo].[tblTechnology](  
  46. [TechID] [int] IDENTITY(1,1) NOT NULL,  
  47. [TechName] [varchar](maxNOT NULL,  
  48. [TechDesc] [varchar](100) NULL,  
  49. PRIMARY KEY CLUSTERED   
  50. (  
  51. [TechID] ASC  
  52. )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ONON [PRIMARY]  
  53. ON [PRIMARY]  
  54.    
  55. GO  
  56.    
  57. SET ANSI_PADDING OFF  
  58. GO  
  59.    
  60. USE [newForumDB]  
  61. GO  
  62.    
  63. /****** Object:  Table [dbo].[tblQuestions]    Script Date: 02/14/2013 14:22:06 ******/  
  64. SET ANSI_NULLS ON  
  65. GO  
  66.    
  67. SET QUOTED_IDENTIFIER ON  
  68. GO  
  69.    
  70. SET ANSI_PADDING ON  
  71. GO  
  72.    
  73. CREATE TABLE [dbo].[tblQuestions](  
  74. [QuestionID] [int] IDENTITY(1,1) NOT NULL,  
  75. [QuestionTitle] [varchar](maxNOT NULL,  
  76. [QuestionDesc] [varchar](maxNOT NULL,  
  77. [DatePosted] [datetime] NOT NULL,  
  78. [UserName] [varchar](50) NOT NULL,  
  79. [TechID] [intNOT NULL,  
  80. [viewCount] [intNOT NULL,  
  81. [ReplyCount] [intNOT NULL,  
  82. PRIMARY KEY CLUSTERED   
  83. (  
  84. [QuestionID] ASC  
  85. )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ONON [PRIMARY]  
  86. ON [PRIMARY]  
  87.    
  88. GO  
  89.    
  90. SET ANSI_PADDING OFF  
  91. GO  
  92.    
  93. SELECT [ReplyID]  
  94.       ,[QuestionID]  
  95.       ,[date]  
  96.       ,[TechID]  
  97.       ,[UserName]  
  98.       ,[ReplyMsg]  
  99.   FROM [newForumDB].[dbo].[tblReplies]  
  100. GO
Stored Procedures
  1. USE [newForumDB]  
  2. GO  
  3.    
  4. /****** Object:  StoredProcedure [dbo].[displayallQuesTechID1]    Script Date: 02/14/2013 14:23:05 ******/  
  5. SET ANSI_NULLS ON  
  6. GO  
  7.    
  8. SET QUOTED_IDENTIFIER ON  
  9. GO  
  10.    
  11. CREATE procedure [dbo].[displayallQuesTechID1](@TechID int  
  12. )as  
  13. begin  
  14. select FI.QuestionID,FI.QuestionTitle,FI.UserName,FI.DatePosted,FI.[date],FI.RepliedName,FI.viewCount,FI.ReplyCount  
  15. ,FI.ReplyMsg,TT.TechID,TT.TechName from tblTechnology TT,  
  16. (select distinct TQ.TechID,TQ.QuestionID,TQ.QuestionTitle,TQ.UserName,TQ.DatePosted,TR.[date],TR.UserName as RepliedName,TQ.viewCount,TQ.ReplyCount  
  17. ,TR.ReplyMsg from  tblQuestions TQ LEFT OUTER JOIN tblReplies TR ON TR.TechID=TQ.TechID and TR.QuestionID = TQ.QUESTIONID   
  18. and TR.[date]in (select MAX(TR.[date]) from tblReplies TR group by TR.QuestionID)) FI where FI.TechID=TT.TechID and TT.TechID=@TechID  
  19. end  
  20.    
  21. GO  
  22.    
  23. USE [newForumDB]  
  24. GO  
  25.    
  26. /****** Object:  StoredProcedure [dbo].[displayResults]    Script Date: 02/14/2013 14:23:38 ******/  
  27. SET ANSI_NULLS ON  
  28. GO  
  29.    
  30. SET QUOTED_IDENTIFIER ON  
  31. GO  
  32.    
  33. CREATE procedure [dbo].[displayResults](@QuestionID int  
  34. )as  
  35. begin  
  36. select tbl.QuestionID,tbl.QuestionDesc,tbl.TechID,tbl.quesaskedby,tbl.QuestionTitle,tbl.DatePosted,tbl.ReplyID,  
  37. tbl.date,tbl.ReplyMsg,tbl.ReplyUser from   
  38. (select distinct q.QuestionID,q.QuestionDesc,q.TechID, q.UserName as quesaskedby,q.QuestionTitle,q.DatePosted,  
  39. r.date,r.ReplyID,r.ReplyMsg,r.UserName as ReplyUser  
  40.  from tblQuestions q left outer join tblReplies r on r.QuestionID=q.QuestionID) tbl  
  41.  where tbl.QuestionID=@QuestionID  
  42. end  
  43.    
  44. GO  
  45.    
  46. USE [newForumDB]  
  47. GO  
  48.    
  49. /****** Object:  StoredProcedure [dbo].[selectTechQuestions1]    Script Date: 02/14/2013 14:23:47 ******/  
  50. SET ANSI_NULLS ON  
  51. GO  
  52.    
  53. SET QUOTED_IDENTIFIER ON  
  54. GO  
  55.   
  56. CREATE PROCEDURE [dbo].[selectTechQuestions1]  
  57.  As    
  58. Begin  
  59.     WITH A AS (  
  60. SELECT top(1) WITH ties Q.TechID  
  61. ,QuestionID  
  62. ,QuestionTitle  
  63. ,DatePosted  
  64. ,Username,TechName,TechDesc,T.TechID as TechnID  
  65. FROM tblTechnology T LEFT OUTER JOIN tblQuestions Q ON Q.TechID = T.TechID  
  66. ORDER BY row_number() over(partition BY Q.TechID ORDER BY Dateposted DESC)  
  67. )  
  68. SELECT * FROM A  
  69. OUTER apply (SELECT count(QuestionDesc) Totalposts, sum(ReplyCount) ReplyCount  
  70. FROM tblQuestions WHERE A.TechID=tblQuestions.TechID) D  
  71. End  
  72.   
  73. GO  

Ok now let's create an MVC application.

one.jpg
 
two.jpg
 
Open your "_ViewStart.cshtml" that is present in the "VIEWS->Shared" folder and replace the contents with the following:
 
 
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.     <meta charset="utf-8" />  
  5.     <meta name="viewport" content="width=device-width" />  
  6.     <title>@ViewBag.Title</title>  
  7.     @Styles.Render("~/Content/css")  
  8.     @Scripts.Render("~/bundles/modernizr")  
  9.     <script src="@Url.Content("~/Scripts/tinymce/jquery.tinymce.js")" type="text/javascript"></script>  
  10. </head>  
  11. <body>  
  12.     <div id="branding">  
  13.     </div>  
  14.     <div>  
  15.         @if (Session["UserName"] != null)  
  16.         {  
  17.             <div class="logged_in" id="user_navigation" runat="server">  
  18.                 <a title="Your Profile" href="">@*<img height="50" width="50" class="photo" src='<%= Url.Action( "GetPhoto", "image", new { photoId = Session["UserName"] } ) %>' />*@  
  19.                     <img alt="" src="@Url.Action("GetPhoto", "User")" height="50" width="50" class="photo" />  
  20.                 </a>  
  21.                 <div id="user_info">  
  22.                     <p>  
  23.                         <span class="hide">Signed in as </span><a href="" title="Your Profile" class="ipbmenu">  
  24.                             <span class="ipbmenu">@Html.Label("Name", Session["UserName"].ToString()) </span>  
  25.                         </a>  
  26.                         <img alt=">" src="http://www.gimptalk.com/public/style_images/master/opts_arrow.png" />  
  27.                     </p>  
  28.                     <ul class="boxShadow" id="user_link_menucontent" style="display: none; position: absolute;  
  29.                         z-index: 9999;">  
  30.                     </ul>  
  31.                     <ul id="user_other">  
  32.                         <li><a href="../User/Logout">Logout</a> </li>  
  33.                     </ul>  
  34.                 </div>  
  35.                 <br />  
  36.             </div>  
  37. @*<strong>@Html.Encode(User.Identity.Name)</strong>  
  38.             @Html.ActionLink("Log Out""Logout""User");*@  
  39.         }  
  40.         else  
  41.         {  
  42.             <div class="not_logged_in" id="user_navigation" runat="server">  
  43.                 <a class="rounded" id="A1" title="Sign In Â»" href="../User/Login"><span class="left">  
  44.                     Sign In Â»</span> <span class="services right"></span>  
  45.                     <br />  
  46.                 </a>  
  47.                 <br />  
  48.                 <span class="links">New user? <a id="register_link" title="Register Now!" href="../User/Register">  
  49.                     Register Now!</a>  </span>  
  50.             </div>  
  51.         }  
  52.     </div>  
  53.     <div id="primary_nav">  
  54.         <ul>  
  55.             <li class="left active" id="nav_discussion" runat="server"><a title="Go to Forums"  
  56.                 href="@Url.Action("Main", "Home")">Forums</a></li><li class="left" id="nav_members"  
  57.                     runat="server"><a  
  58.                     title="Go to Member List" href="@Url.Action("Members", "Home")">Members</a></li>  
  59.         </ul>  
  60.     </div>  
  61.     @RenderBody()  
  62.     @Scripts.Render("~/bundles/jquery")  
  63.     @RenderSection("scripts", required: false)  
  64. </body>  
  65. </html>
If you would like to include your own scripts and CSS then open the "BundleConfig.cs" that is present in the "App_Start" folder and you will see CSS or scripts included that you need to add the following to:
  1. bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/css/ipb_common.css",  
  2.                "~/Content/css/ipb_editor.css",  
  3.                 "~/Content/css/ipb_help.css",  
  4.                 "~/Content/css/ipb_login_register.css",  
  5.                 "~/Content/css/ipb_print.css",  
  6.                 "~/Content/css/ipb_styles.css""~/Content/css/ipb_ucp.css"));
Now let us create a Model with two classes, namely "userModel" and "Register".
 
three.jpg
 
four.jpg
 
Copy and paste the following code in your class and build the application.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.ComponentModel.DataAnnotations;  
  6. using System.ComponentModel.DataAnnotations.Schema;  
  7. using System.Web.Mvc;  
  8.   
  9. namespace mvcForumapp.Models  
  10. {  
  11.     public class userModel  
  12.     {  
  13.         [Required]  
  14.         [DataType(DataType.EmailAddress)]  
  15.         [Display(Name = "Email address")]  
  16.         [MaxLength(50)]  
  17.         [RegularExpression(@"[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}", ErrorMessage = "Please enter correct email")]  
  18.         public string Email { getset; }  
  19.    
  20.         [Required]  
  21.         [DataType(DataType.Password)]  
  22.         [Display(Name = "Password")]  
  23.         public string password { getset; }  
  24.     }  
  25.   
  26.     public class Register  
  27.     {  
  28.          
  29. [Required(ErrorMessage = "username required")]  
  30.         [Display(Name = "Choose username")]  
  31.         [StringLength(20, MinimumLength = 4)]  
  32.         [Remote("IsUserNameAvailable""Register""Username is already taken")]  
  33.         public string Username { getset; }  
  34.   
  35.         [Required(ErrorMessage = "display required")]  
  36.         [StringLength(20, MinimumLength = 4)]  
  37.         [Remote("IsDisplayAvailable""Register""displayname already taken")]  
  38.         public string Displayname { getset; }  
  39.   
  40.         [Required(ErrorMessage = "EmailAddress required")]  
  41.         [DataType(DataType.EmailAddress)]  
  42.         [Display(Name = "Email address")]  
  43.         [MaxLength(50)]  
  44.         [RegularExpression(@"[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}", ErrorMessage = "Please enter correct email")]  
  45.         [Remote("IsEmailAvailable""Register""EmailAddress is already taken")]  
  46.         public string Email { getset; }  
  47.   
  48.         [Required(ErrorMessage = "password required")]  
  49.         [DataType(DataType.Password)]  
  50.         [StringLength(20, MinimumLength = 8)]  
  51.         [Display(Name = "Password")]  
  52.         public string password { getset; }  
  53.   
  54.         [Required(ErrorMessage = "password required")]  
  55.         [DataType(DataType.Password)]  
  56.         [Compare("password", ErrorMessage = "password didn't match")]  
  57.         [StringLength(20, MinimumLength = 8)]  
  58.         public string PasswordConfirm { getset; }  
  59.     }  
  60. }   
Now let us create a controller and provide the name you need, or since we are initially trying to create and register a user, the name "UserController" is a better naming convention that will make your work easy in MVC otherwise we will encounter problems when we implement or work on large applications.
 
five.jpg
Name it "Register".
 
six.jpg
 
First let us work on user registeration. As I said, we are using Entity Framework to add an entity model to our project, from the tables and Stored Procedures that I provided, you can easily add an Entity Model to the application, Entity Framework beginners can check my previous articles explaining how to add a model to the project from here:
 
Now replace your controller code with the following
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.Mvc;  
  6. using System.Web.UI;  
  7. namespace mvcForumapp.Controllers  
  8. {  
  9.     public class UserController : Controller  
  10.     {  
  11.         //  
  12.         // GET: /User/  
  13.         newForumDBEntities db = new newForumDBEntities();  
  14.         public ActionResult Index()  
  15.         {  
  16.             return View();  
  17.         }  
  18.         [HttpGet]  
  19.         public ActionResult Register()  
  20.         {  
  21.             return View();  
  22.         }  
  23.         public ActionResult IsUserNameAvailable(string UserName)  
  24.         {  
  25.             var usrAvailable = db.tblUsers.Where(p => p.UserName == UserName).Select(img => img.UserName).FirstOrDefault();  
  26.             if (usrAvailable == null)  
  27.             {  
  28.                 return Json(true, JsonRequestBehavior.AllowGet);  
  29.             }  
  30.             //string html = "<span style='color:Red;'> Username in use</span>";  
  31.             return Json("<span style='color:Red;'> Username in already in use</span>", JsonRequestBehavior.AllowGet);  
  32.         }  
  33.         [OutputCache(Location = OutputCacheLocation.None, NoStore = true)]  
  34.         public JsonResult IsDisplayAvailable(string Displayname)  
  35.         {  
  36.             var usrAvailable = db.tblUsers.Where(p => p.DisplayName == Displayname).Select(img => img.DisplayName).FirstOrDefault();  
  37.             if (usrAvailable == null)  
  38.             {  
  39.                 return Json(true, JsonRequestBehavior.AllowGet);  
  40.             }  
  41.             //string html = "<span style='color:Red;'> Username in use</span>";  
  42.             return Json("<span style='color:Red;'> Display name in already use</span>", JsonRequestBehavior.AllowGet);  
  43.         }  
  44.         [OutputCache(Location = OutputCacheLocation.None, NoStore = true)]  
  45.         public JsonResult IsEmailAvailable(string Email)  
  46.         {  
  47.             var usrAvailable = db.tblUsers.Where(p => p.EmailID == Email).Select(img => img.EmailID).FirstOrDefault();  
  48.             if (usrAvailable == null)  
  49.             {  
  50.                 return Json(true, JsonRequestBehavior.AllowGet);  
  51.             }  
  52.             //string html = "<span style='color:Red;'> Username in use</span>";  
  53.             return Json("<span style='color:Red;'> Emai in already in use</span>", JsonRequestBehavior.AllowGet);  
  54.         }  
  55.         [HttpPost]  
  56.         public ActionResult Register(mvcForumapp.Models.Register user, HttpPostedFileBase file)  
  57.         {  
  58.             if (ModelState.IsValid)  
  59.             {  
  60.                 if (file == null)  
  61.                 {  
  62.                     ModelState.AddModelError("File""Please Upload Your file");  
  63.                 }  
  64.                 else if (file.ContentLength > 0)  
  65.                 {  
  66.                     int MaxContentLength = 1024 * 1024 * 3; //3 MB  
  67.                     string[] AllowedFileExtensions = new string[] { ".jpg"".gif"".png"".pdf" };  
  68.                     if (!AllowedFileExtensions.Contains(file.FileName.Substring(file.FileName.LastIndexOf('.'))))  
  69.                     {  
  70.                         ModelState.AddModelError("File""Please file of type: " + string.Join(", ", AllowedFileExtensions));  
  71.                     }  
  72.                     else if (file.ContentLength > MaxContentLength)  
  73.                     {  
  74.                         ModelState.AddModelError("File""Your file is too large, maximum allowed size is: " + MaxContentLength + " MB");  
  75.                     }  
  76.                     else  
  77.                     {  
  78.                         using (var db = new newForumDBEntities())  
  79.                         {  
  80.                             Byte[] imgByte = null;  
  81.                             HttpPostedFileBase File = file;  
  82.                             //Create byte Array with file len  
  83.                             imgByte = new Byte[File.ContentLength];  
  84.                             //force the control to load data in array  
  85.                             File.InputStream.Read(imgByte, 0, File.ContentLength);  
  86.                             var userdets = db.tblUsers.CreateObject();  
  87.                             userdets.UserName = user.Username;  
  88.                             userdets.DateJoined = DateTime.Now;  
  89.                             userdets.DisplayName = user.Displayname;  
  90.                             userdets.EmailID = user.Email;  
  91.                             userdets.Password = user.password;  
  92.                             userdets.Photo = imgByte;  
  93.                             //var encrppass = Encrypt(user.password, true);  
  94.                             //var userdets = db.tblUsers.CreateObject();  
  95.                             //userdets.EmailID = user.Email;  
  96.                             //userdets.password = encrppass;  
  97.                             db.tblUsers.AddObject(userdets);  
  98.                             db.SaveChanges();  
  99.                             return RedirectToAction("Main""Home");  
  100.                         }  
  101.                     }  
  102.                 }  
  103.             }  
  104.             return View(user);  
  105.         }  
  106.     }  
  107. }
Now let us create a View for registering inside the controller. There are two action results with the same name "Register" but the functionality is different, one is for HttpGet that just returns a view with controls and the other is for HttpPost to post the data to the database.
 
seven.jpg
 
 
eight.jpg
 
 
You can also create a strongly-type view by selecting the desired class from the drop-down and select create in the Scaffold template if you would like to have your own design just create an empty view.
 
Your view initially, if you didn't select a strongly-typed view, will be as follows:
  1. @{  
  2.     ViewBag.Title = "Register";  
  3.     Layout = "~/Views/Shared/_Layout.cshtml";  
  4. }    
Copy and paste the following:
  1.  @model mvcForumapp.Models.Register  
  2. @{  
  3.     ViewBag.Title = "Register";  
  4.     Layout = "~/Views/Shared/_Layout.cshtml";  
  5. }  
  6. <script src="../../Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>  
  7. <script src="../../Scripts/jquery.validate.min.js" type="text/javascript"></script>  
  8. <script src="../../Scripts/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>  
  9. <script type="text/jscript">  
  10.     //get file size  
  11.     function GetFileSize(fileid) {  
  12.         try {  
  13.             var fileSize = 0;  
  14.             //for IE  
  15.             if ($.browser.msie) {  
  16.                 //before making an object of ActiveXObject,   
  17.                 //please make sure ActiveX is enabled in your IE browser  
  18.                 var objFSO = new ActiveXObject("Scripting.FileSystemObject"); var filePath = $("#" + fileid)[0].value;  
  19.                 var objFile = objFSO.getFile(filePath);  
  20.                 var fileSize = objFile.size; //size in kb  
  21.                 fileSize = fileSize / 1048576; //size in mb   
  22.             }  
  23.             //for FF, Safari, Opeara and Others  
  24.             else {  
  25.                 fileSize = $("#" + fileid)[0].files[0].size //size in kb  
  26.                 fileSize = fileSize / 1048576; //size in mb   
  27.             }  
  28.   
  29.             // alert("Uploaded File Size is" + fileSize + "MB");  
  30.             return fileSize;  
  31.         }  
  32.         catch (e) {  
  33.             alert("Error is :" + e);  
  34.         }  
  35.     }  
  36.   
  37.     //get file path from client system  
  38.     function getNameFromPath(strFilepath) {  
  39.   
  40.         var objRE = new RegExp(/([^\/\\]+)$/);  
  41.         var strName = objRE.exec(strFilepath);  
  42.   
  43.         if (strName == null) {  
  44.             return null;  
  45.         }  
  46.         else {  
  47.             return strName[0];  
  48.         }  
  49.   
  50.     }  
  51.   
  52.     $("#btnSubmit").live("click"function () {  
  53.   
  54.         if ($('#fileToUpload').val() == "") {  
  55.             $("#spanfile").html("Please upload file");  
  56.             return false;  
  57.         }  
  58.         else {  
  59.             return checkfile();  
  60.         }  
  61.     });  
  62.   
  63.     function checkfile() {  
  64.         var file = getNameFromPath($("#fileToUpload").val());  
  65.         if (file != null) {  
  66.             var extension = file.substr((file.lastIndexOf('.') + 1));  
  67.             //  alert(extension);  
  68.             switch (extension) {  
  69.                 case 'jpg':  
  70.                 case 'JPG':  
  71.                 case 'png':  
  72.                 case 'PNG':  
  73.                 case 'gif':  
  74.                 case 'GIF':  
  75.                     flag = true;  
  76.                     break;  
  77.                 default:  
  78.                     flag = false;  
  79.             }  
  80.         }  
  81.         if (flag == false) {  
  82.             $("#spanfile").text("You can upload only jpg,png,gif,pdf extension file");  
  83.             return false;  
  84.   
  85.         }  
  86.         else {  
  87.             var size = GetFileSize('fileToUpload');  
  88.             if (size > 3) {  
  89.                 $("#spanfile").text("You can upload file up to 3 MB");  
  90.                 return false;  
  91.             }  
  92.             else {  
  93.                 $("#spanfile").text("");  
  94.             }  
  95.         }  
  96.     }  
  97.     $(function () {  
  98.         $("#fileToUpload").change(function () {  
  99.             checkfile();  
  100.         });  
  101.   
  102.     });  
  103.   
  104. </script>  
  105. @using (Html.BeginForm("Register""User", FormMethod.Post, new { enctype = "multipart/form-data" }))  
  106. {                                           
  107.     <br />  
  108.     <br />  
  109.     <div class="block_wrap left" id="register_form">  
  110.         <h2>  
  111.                Ready to register?</h2>  
  112.         <p class="extra">  
  113.                 It's free and simple to register for our board! We just need  
  114.             a few pieces of information from you, and you'll be ready     to  
  115.             make your first post in no time!  
  116.             <br />  
  117.                 If you already have an account, you can go directly to the <a  
  118.                 title="Go to sign in" href="../User/Login">sign in page</a>  
  119.             <br />  
  120.         </p>  
  121.         <div class="generic_bar">  
  122.         </div>  
  123.         <h3 style="text-align: center;" class="bar">  
  124.                 Account Information</h3>  
  125.         <ul>  
  126.             <li class="field required ">  
  127.                 @Html.LabelFor(m => m.Username)  
  128.                 @Html.TextBoxFor(m => m.Username, new { maxlength = 50 })  
  129.                   <span class="input_error">@Html.ValidationMessageFor(m => m.Username)</span>  
  130.             </li>  
  131.             <li class="field required ">  
  132.                 @Html.LabelFor(m => m.Displayname)  
  133.                 @Html.TextBoxFor(m => m.Displayname, new { maxlength = 50 })  
  134.                   <span class="input_error">@Html.ValidationMessageFor(m => m.Displayname)</span>  
  135.             </li>  
  136.             <li class="field required ">  
  137.                 @Html.LabelFor(m => m.Email)  
  138.                 @Html.TextBoxFor(m => m.Email, new { maxlength = 50 })  
  139.                   <span class="input_error">@Html.ValidationMessageFor(m => m.Email)</span>  
  140.             </li>  
  141.             <li class="field required ">  
  142.                 @Html.LabelFor(m => m.password)  
  143.                 @Html.PasswordFor(m => m.password, new { maxlength = 50 })  
  144.                   <span class="input_error">@Html.ValidationMessageFor(m => m.password)</span>  
  145.             </li>  
  146.             <li class="field required ">  
  147.                 @Html.LabelFor(m => m.PasswordConfirm)  
  148.                 @Html.PasswordFor(m => m.PasswordConfirm, new { maxlength = 50 })  
  149.                   <span class="input_error">@Html.ValidationMessageFor(m => m.PasswordConfirm)</span>  
  150.             </li>  
  151.             <li class="field required ">  
  152.                 <label>  
  153.                     Select Image</label>  
  154.                 <input type="file" id="fileToUpload" name="file" />  
  155.                 <span class="input_error" id="spanfile"></span></li>  
  156.         </ul>  
  157.         <br />  
  158.         <hr />  
  159.         <div style="float: left; margin-left: 250px;">  
  160.             <table>  
  161.                 <tr>  
  162.                     <td>  
  163.                         <input type="submit" class="input_submit" id="btnSubmit" value="Create User" />  
  164.                     </td>  
  165.                     <td>  
  166.                         @Html.ActionLink("Cancel""Main"new { Controller = "Home" }, new { @class = "input_submit" })  
  167.                     </td>  
  168.                 </tr>  
  169.             </table>  
  170.             @*<input type="submit" value=" Cancel" class="input_submit" />*@  
  171.         </div>  
  172.     </div>  
  173.     <br />  
  174.     <div style="float: right; margin-right: 350px;">  
  175.     </div>  
  176. }
Changes in "RouteConfig.cs" that is in the "App_Start" folder:
  1. public static void RegisterRoutes(RouteCollection routes)  
  2. {  
  3.     routes.IgnoreRoute("{resource}.axd/{*pathInfo}");  
  4.   
  5.     routes.MapRoute(  
  6.         name: "Default",  
  7.         url: "{controller}/{action}/{id}",  
  8.         defaults: new { controller = "User", action = "Index", id = UrlParameter.Optional }  
  9.     );  
  10. }
Now run the application and you will be shown the following:
 
main.jpg
 

 
Clicking on "Register" will route to the Register view and "Login" will route to the Login view.

 
This is how the register view looks:

 
register.jpg
 
validations.jpg
 
Remote validation:
 
Check here for the implementation of remote validation http://msdn.microsoft.com/en-us/library/gg508808(v=vs.98).aspx
 
Here I checked whether Username, displayname and email exist, if the do not exist then remote validation fires if not then it will not show an error.
 
remote.jpg
 
If everything is fine then you are ready to register.
 
mvcuse.jpg
 
 
After you are registered, it will route back to the default page.
 
Now let us work on Login as you already create a Model let us work on creating a controller for Login and required Views.
 
Follow as we do for Register starting from the controller, first add a controller named "logincontroller" in the "Controller" folder then replace it with the following code:
  1.  using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.Mvc;  
  6. namespace mvcForumapp.Controllers  
  7. {  
  8.     public class LoginController : Controller  
  9.     {  
  10.         newForumDBEntities db = new newForumDBEntities();  
  11.         [HttpGet]  
  12.         public ActionResult Login()  
  13.         {  
  14.             return View();  
  15.         }  
  16.         [HttpPost]  
  17.         public ActionResult Login(mvcForumapp.Models.userModel user)  
  18.         {  
  19.             if (ModelState.IsValid)  
  20.             {  
  21.                 if (isValid(user.Email, user.password))  
  22.                 {  
  23.                     var user1 = db.tblUsers.FirstOrDefault(u => u.EmailID == user.Email).UserName;  
  24.                     Session["UserName"] = user1;  
  25.                     //FormsAuthentication.SetAuthCookie(user.Email, false);  
  26.                     return RedirectToAction("Index""Register");  
  27.                 }  
  28.                 else  
  29.                 {  
  30.                     ModelState.AddModelError("""Login Data is Incorrect");  
  31.                 }  
  32.             }  
  33.             return View(user);  
  34.         }  
  35.         private bool isValid(string Email, string password)  
  36.         {  
  37.             //string crypto = Encrypt(password, true);  
  38.             bool isvalid = false;  
  39.             using (var db = new newForumDBEntities())  
  40.             {  
  41.                 var user = db.tblUsers.FirstOrDefault(u => u.EmailID == Email);  
  42.                 if (user != null)  
  43.                 {  
  44.                     if (user.Password == password)  
  45.                     {  
  46.                         isvalid = true;  
  47.                     }  
  48.                 }  
  49.             }  
  50.             return isvalid;  
  51.         }  
  52.     }  
  53. }
Add Views correspondingly as we did for "Register", after adding the view your login view your run will look as follows:
 
login.jpg
 
After successful login you will be shown your user name along with your image as follows, before that ensure you implement code for showing the image of the user logging in; we will implement that as follows.
 
You will see your "_Layout.cshtml" as follows:
  1. <img alt="" src="@Url.Action("GetPhoto", "User")" height="50" width="50" class="photo" />
This means we are trying to load the image from the "controller(User)" with the method or function name "GetPhoto"; change it as per your controller and method here. For a better understanding I will create a new controller and name it "displayImage" with the function "ShowImage" so my image source will be as follows:
now <img alt="" src="@Url.Action("ShowImage", "displayImage")" height="50" width="50" class="photo" />
 
Your controller code to display the login user image is as follows:
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.Mvc;  
  6. namespace mvcForumapp.Controllers  
  7. {  
  8.     public class displayImageController : Controller  
  9.     {  
  10.         //  
  11.         // GET: /displayImage/  
  12.         newForumDBEntities db = new newForumDBEntities();  
  13.         public ActionResult Index()  
  14.         {  
  15.             return View();  
  16.         }  
  17.         [HttpGet]  
  18.         public ActionResult ShowImage()  
  19.         {  
  20.             string user = Session["UserName"as string;  
  21.             byte[] photo = null;  
  22.             var v = db.tblUsers.Where(p => p.UserName == user).Select(img => img.Photo).FirstOrDefault();  
  23.             photo = v;  
  24.             return File(photo, "image/jpeg");  
  25.         }  
  26.     }  
Here is what you will see after a successful login:
 
disp.jpg
Now let us create a controller and a view for logout. Create a controller and name it "Logout" and then replace your controller with the following:
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.Mvc;  
  6. namespace mvcForumapp.Controllers  
  7. {  
  8.     public class LogoutController : Controller  
  9.     {  
  10.         //  
  11.         // GET: /Logout/  
  12.         public ActionResult Logout()  
  13.         {  
  14.             Session.Abandon();  
  15.             return RedirectToAction("Index""Register");  
  16.         }  
  17.     }  
  18. }
Now add a view by right-clicking on the "Logout" action result and select the master page. Your view should be as follows:
  1. @{  
  2.     ViewBag.Title = "Logout";  
  3.     Layout = "~/Views/Shared/_Layout.cshtml";  
  4. }  
  5.   
  6. <h2>Logout</h2>
After successful log-out you will be routed to the main view again.
 
So far so good. Now let us create Controllers and Views for the rest, i.e posting questions, replies and all. First let us bring all the Questions from the database from each technology.    

As we are using Entity Framework each and every Stored Procedure from the database is treated as a model, not only Stored Procedures but also tables.

 
First let us create a controller for displaying the list of technologies available and the number of topics and replies under each technology, also the last posted question information.
 
Create a controller and name it "Technology" and replace the code with the following code:
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.Mvc;  
  6. namespace mvcForumapp.Controllers  
  7. {  
  8.     public class TechnologyController : Controller  
  9.     {  
  10.         //  
  11.         // GET: /Technology/  
  12.         newForumDBEntities db = new newForumDBEntities();  
  13.         public ActionResult Index()  
  14.         {  
  15.             List<mvcForumapp.selectStats_Result_Result> userview = db.selectStats_Result().ToList();  
  16.             return View(userview);  
  17.         }  
  18.     }  
  19. }
Create an empty View by right-clicking on "Index" and replace the view with the following:
  1. @model IEnumerable<mvcForumapp.selectStats_Result_Result>  
  2. @{  
  3.     ViewBag.Title = "Main";  
  4.     Layout = "~/Views/Shared/_Layout.cshtml";  
  5. }  
  6. <div id="secondary_nav">  
  7.     <ul class="left" id="breadcrumb">  
  8.         <li class="first"><a href="">MVC-Forum Community</a></li>  
  9.     </ul>  
  10. </div>  
  11. <div class="clear" id="content">  
  12.     <a id="j_content"></a>  
  13.     <h2 class="hide">  
  14.         Board Index</h2>  
  15.     <div class="clearfix" id="board_index">  
  16.         <div class="no_sidebar clearfix" id="categories">  
  17.             <!-- CATS AND FORUMS -->  
  18.             <div class="category_block block_wrap">  
  19.                 <h3 class="maintitle" id="category_47">  
  20.                     <a title="View category" href="../Home/Main">Technology related questions</a></h3>  
  21.                 <div class="table_wrap">  
  22.                     <table summary="Forums within the category 'GimpTalk'" class="ipb_table">  
  23.                         <tbody>  
  24.                             <tr class="header">  
  25.                                 <th class="col_c_icon" scope="col">  
  26.                                        
  27.                                 </th>  
  28.                                 <th class="col_c_forum" scope="col">  
  29.                                     Forum  
  30.                                 </th>  
  31.                                 <th class="col_c_stats stats" scope="col">  
  32.                                     Stats  
  33.                                 </th>  
  34.                                 <th class="col_c_post" scope="col">  
  35.                                     Last Post Info  
  36.                                 </th>  
  37.                             </tr>  
  38.                             <tr class="row1">  
  39.                                 <td class="altrow">  
  40.                                 </td>  
  41.                                 <td>  
  42.                                     @foreach (var item in Model)  
  43.                                     {  
  44.                                         string techname = item.TechName;  
  45.                                         @Html.ActionLink(techname, "Details""Home"new { TechID = item.TechnID }, null)  
  46.                                         <br />  
  47.                                         <br />  
  48.                                         @Html.DisplayFor(modelItem => item.TechDesc)  
  49.                                         <br />  
  50.                                         <br />  
  51.                                     }  
  52.                                 </td>  
  53.                                 <td class="altrow stats">  
  54.                                     @foreach (var item in Model)  
  55.                                     {  
  56.                                         @Html.DisplayFor(modelItem => item.Totalposts)  
  57.                                         @Html.Label("  ");  
  58.                                         @Html.Label("Topics")  
  59.                                         <br />  
  60.                                                          if (item.ReplyCount != null)  
  61.                                                          {  
  62.                                         @Html.DisplayFor(modelItem => item.ReplyCount)  
  63.                                         @Html.Label("  ");  
  64.                                         @Html.Label("Replies")  
  65.                                         <br />  
  66.                                         <br />  
  67.                                                          }  
  68.                                                          else  
  69.                                                          {  
  70.                                         @Html.DisplayFor(modelItem => item.ReplyCount)  
  71.                                         @Html.Label("  ");  
  72.                                         @Html.Label("0 Replies")  
  73.                                         <br />  
  74.                                         <br />  
  75.                                                          }  
  76.                                     }  
  77.                                 </td>  
  78.                                 <td>  
  79.                                     @foreach (var item in Model)  
  80.                                     {  
  81.                                         if (item.DatePosted != null)  
  82.                                         {  
  83.                                             DateTime dt = Convert.ToDateTime(item.DatePosted);  
  84.                                             string strDate = dt.ToString("dd MMMM yyyy - hh:mm tt");  
  85.                                         @Html.Label(strDate)  
  86.                                         <br />  
  87.                                         }  
  88.                                         else  
  89.                                         {  
  90.                                         <br />  
  91.                                         }  
  92.                                         if (item.QuestionTitle != null)  
  93.                                         {  
  94.                                         @Html.Label("IN : ");  
  95.                                         @Html.Label("  ");  
  96.                                                          string QuestionTitle = item.QuestionTitle;  
  97.                                         @Html.ActionLink(QuestionTitle, "displayIndividual""Display"new { QuestionID = item.QuestionID }, null)  
  98.                                         <br />  
  99.                                         }  
  100.                                         else  
  101.                                         {  
  102.                                         <br />  
  103.                                         }  
  104.                                         if (item.Username != null)  
  105.                                         {  
  106.                                         @Html.Label("By : ");  
  107.                                         @Html.Label("  ");  
  108.                                                          string User = item.Username;  
  109.                                         @Html.ActionLink(User, "Details""Home"new { Username = item.Username }, null)  
  110.                                         <br />  
  111.                                         <br />  
  112.                                         }  
  113.                                         else  
  114.                                         {  
  115.                                         @Html.ActionLink("Start New Topic""PostQuestion""Home"new { TechID = item.TechnID }, null)  
  116.                                         <br />  
  117.                                         <br />  
  118.                                         }  
  119.                                     }  
  120.                                 </td>  
  121.                             </tr>  
  122.                         </tbody>  
  123.                     </table>  
  124.                 </div>  
  125.             </div>  
  126.         </div>  
  127.     </div>  
  128. </div>
Earlier I set the default routing view as Index from Register, so let us change that so when someone hits, the default view will be shown with the list of questions.

Changes in "RouteConfig.cs" that is in the "App_Start" folder:
  1. public static void RegisterRoutes(RouteCollection routes)  
  2. {  
  3.     routes.IgnoreRoute("{resource}.axd/{*pathInfo}");  
  4.   
  5.     routes.MapRoute(  
  6.         name: "Default",  
  7.         url: "{controller}/{action}/{id}",  
  8.         defaults: new { controller = "Technology", action = "Index", id = UrlParameter.Optional }  
  9.     );  
  10. }
This is how your view looks when you run the application:
tech.jpg
 
Ok since I have questions in each and every Technology, this was displayed. Add a new technology in the tblTechnology table and run your application, when there are no question in that technology you will have a chance to post new questions in that technology.
 
start.jpg
Currently we haven't implemented anything for that; it will show an error page instead. We will see how to post new questions later on. First let me show you how to display all questions available in the selected Technology. 
 
For the existing "Technology" controller I will add a few methods or you can add a new controller if you need to. I am adding the "a" method to the existing controller i.e "Technology" as follows:
  1. public ActionResult DisplayQuestions()  
  2. {  
  3.     int TechID = Convert.ToInt16(Request.QueryString["TechID"].ToString());  
  4.     List<mvcForumapp.QuestionList_Result> disp = db.QuestionList(TechID).ToList();  
  5.     return View(disp);  
  6. }  
Create a view by right-clicking on "DisplayQuestions" and replace it with the following code:
  1. @model IEnumerable<mvcForumapp.QuestionList_Result>  
  2. @{  
  3.     ViewBag.Title = "Details";  
  4. }  
  5. <style type="text/css">  
  6.     .disabled  
  7.     {  
  8.         /* Text and background colour, medium red on light yellow */  
  9.         float: right;  
  10.         margin-right: 20px;  
  11.         background: #999;  
  12.         background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#dadada), to(#f3f3f3));  
  13.         border-top: 1px solid #c5c5c5;  
  14.         border-right: 1px solid #cecece;  
  15.         border-bottom: 1px solid #d9d9d9;  
  16.         border-left: 1px solid #cecece;  
  17.         color: #8f8f8f;  
  18.         box-shadow: none;  
  19.         -moz-box-shadow: none;  
  20.         -webkit-box-shadow: none;  
  21.         cursor: not-allowed;  
  22.         text-shadow: 0 -1px 1px #ebebeb;  
  23.     }  
  24.     .active  
  25.     {  
  26.         box-shadow: none;  
  27.         -moz-box-shadow: none;  
  28.         -webkit-box-shadow: none;  
  29.         cursor: allowed;  
  30.     }  
  31. </style>  
  32. <br />  
  33. <br />  
  34. <div style="float: left; margin-left: 20px;">  
  35.     @Html.ActionLink("Back""Index""Technology")  
  36. </div>  
  37. <div id='ipbwrapper'>  
  38.     <ul class="comRigt">  
  39.         <li>  
  40.             <br />  
  41.             <img alt="Start New Topic" src="http://www.gimptalk.com/public/style_images/master/page_white_add.png" />  
  42.             @if (Session["UserName"] != null)  
  43.             {  
  44.                 int techID = Convert.ToInt16(@Request.QueryString["TechID"]);  
  45.                 if (Model.Count() == 0)  
  46.                 {  
  47.                 @Html.ActionLink("Start New Topic""PostQuestion""Question"new { @class = "active", onclick = "javascript:return true;", TechID = techID }, null)  
  48.                 }  
  49.                 else  
  50.                 {  
  51.                     foreach (var item in Model)  
  52.                     {     
  53.                 @Html.ActionLink("Start New Topic""PostQuestion""Question"new { @class = "active", onclick = "javascript:return true;", TechID = item.TechID }, null)  
  54.                         break;  
  55.                     }  
  56.                 }  
  57.             }  
  58.             else  
  59.             {  
  60.                 int techID = Convert.ToInt16(@Request.QueryString["TechID"]);  
  61.                 if (Model.Count() == 0)  
  62.                 {  
  63.                 @Html.ActionLink("Start New Topic""PostQuestion""Home"new {title = "Please login to post Questions", @class = "disabled", onclick = "javascript:return false;", TechID = techID })  
  64.                 }  
  65.                 else  
  66.                 {  
  67.                     foreach (var item in Model)  
  68.                     {  
  69.                 @Html.ActionLink("Start New Topic""PostQuestion""Home"new {title = "Please login to post Questions", TechID = item.TechID, @class = "disabled", onclick = "javascript:return false;" })  
  70.                         break;  
  71.                     }  
  72.                 }  
  73.             }  
  74.         </li>  
  75.     </ul>  
  76.     <br />  
  77.     @if (Model.Count() != 0)  
  78.     {  
  79.         <div class="category_block block_wrap">  
  80.             <table id="forum_table" summary="Topics In This Forum "GimpTalk News and Updates""  
  81.                 class="ipb_table topic_list">  
  82.                 <div class="maintitle">  
  83.                     <span class="main_forum_title">  
  84.                         @foreach (var item in Model)  
  85.                         {  
  86.                             string strTopic = "A forum where you can post questions regarding " + item.TechName;  
  87.                             @Html.Label("Topic", strTopic)  
  88.                             break;  
  89.                         }  
  90.                     </span>  
  91.                 </div>  
  92.                 <tbody>  
  93.                     <tr class="header">  
  94.                         <th class="col_f_icon" scope="col">  
  95.                                
  96.                         </th>  
  97.                         <th class="col_f_topic" scope="col">  
  98.                             Topic  
  99.                         </th>  
  100.                         <th class="col_f_starter short" scope="col">  
  101.                             Started By  
  102.                         </th>  
  103.                         <th class="col_f_views stats" scope="col">  
  104.                             Stats  
  105.                         </th>  
  106.                         <th class="col_f_post" scope="col">  
  107.                             Last Post Info  
  108.                         </th>  
  109.                     </tr>  
  110.                     <tr id="trow_49752" class="row1">  
  111.                         <td class="short altrow">  
  112.                         </td>  
  113.                         <td class="__topic __tid49752" id="anonymous_element_3">  
  114.                             @foreach (var item in Model)  
  115.                             {  
  116.                                 <br />  
  117.                                 string QuestionTitle = item.QuestionTitle;  
  118.                                 @Html.ActionLink(QuestionTitle, "displayIndividual""Display"new { QuestionID = item.QuestionID }, null)  
  119.                                 <br />  
  120.                                 <br />  
  121.                             }  
  122.                         </td>  
  123.                         <td class="short altrow">  
  124.                             @foreach (var item in Model)  
  125.                             {  
  126.                                 <br />  
  127.                                 string QuestionTitle = item.UserName;  
  128.                                 @Html.ActionLink(QuestionTitle, "Details""Home"new { Username = item.UserName }, null)  
  129.                                 <br />  
  130.                                 <br />  
  131.                             }  
  132.                         </td>  
  133.                         <td class="stats">  
  134.                             <ul>  
  135.                                 <li>  
  136.                                     @foreach (var item in Model)  
  137.                                     {  
  138.                                         @Html.DisplayFor(modelItem => item.ReplyCount)  
  139.                                         @Html.Label("  ");  
  140.                                         @Html.Label("Replies")  
  141.                                         <br />  
  142.                                         @Html.DisplayFor(modelItem => item.viewCount)  
  143.                                         @Html.Label("  ");  
  144.                                         @Html.Label("Views")  
  145.                                         <br />  
  146.                                         <br />  
  147.                                     }  
  148.                                 </li>  
  149.                             </ul>  
  150.                         </td>  
  151.                         <td class="altrow">  
  152.                             @foreach (var item in Model)  
  153.                             {  
  154.                                 if (item.date != null)  
  155.                                 {  
  156.                                     DateTime dt = Convert.ToDateTime(item.date);  
  157.                                     string strDate = dt.ToString("dd MMMM yyyy - hh:mm tt");  
  158.                                 @Html.Label(strDate)  
  159.                                 }  
  160.                                 else  
  161.                                 {  
  162.                                     DateTime dt = Convert.ToDateTime(item.DatePosted);  
  163.                                     string strDate = dt.ToString("dd MMMM yyyy - hh:mm tt");  
  164.                                 @Html.Label(strDate)  
  165.                                 }  
  166.                                 <br />  
  167.                                 @Html.Label("By : ")  
  168.                                 @Html.Label("  ")  
  169.                                 if (item.RepliedName != null)  
  170.                                 {  
  171.                                     string User = item.RepliedName;  
  172.                                 @Html.ActionLink(User, "Details""Home"new { Username = item.RepliedName }, null)  
  173.                                 }  
  174.                                 else  
  175.                                 {  
  176.                                     string User = item.UserName;  
  177.                                 @Html.ActionLink(User, "Details""Home"new { Username = item.UserName }, null)  
  178.                                 }  
  179.                                 <br />  
  180.                                 <br />  
  181.                             }  
  182.                         </td>  
  183.                     </tr>  
  184.                 </tbody>  
  185.             </table>  
  186.         </div>  
  187.     }  
  188.     else  
  189.     {  
  190.         <div class="category_block block_wrap">  
  191.             <table id="forum_table1" summary="Topics In This Forum "GimpTalk News and Updates""  
  192.                 class="ipb_table topic_list">  
  193.                 <div class="maintitle">  
  194.                     <span style="font-size:larger; margin-left:450px;">No topics available</span>  
  195.                 </div>  
  196.             </table>  
  197.         </div>  
  198.     }  
  199.     @if (Model.Count() != 0)  
  200.     {  
  201.         <ul class="comRigt">  
  202.             <li>  
  203.                 <br />  
  204.                 <img alt="Start New Topic" src="http://www.gimptalk.com/public/style_images/master/page_white_add.png" />  
  205.                 @if (Session["UserName"] != null)  
  206.                 {  
  207.                     foreach (var item in Model)  
  208.                     {     
  209.                     @Html.ActionLink("Start New Topic""PostQuestion""Question"new { @class = "active", onclick = "javascript:return true;", TechID = item.TechID }, null)  
  210.                         break;  
  211.                     }  
  212.                 }  
  213.                 else  
  214.                 {  
  215.                     foreach (var item in Model)  
  216.                     {  
  217.                     @Html.ActionLink("Start New Topic""PostQuestion""Home"new {title = "Please login to post Questions", TechID = item.TechID, @class = "disabled", onclick = "javascript:return false;" })  
  218.                         break;  
  219.                     }  
  220.                 }  
  221.             </li>  
  222.         </ul>  
  223.     }  
  224. </div>
What will happen is, by selecting a particular technology in the image above will display all the questions related to that technology.
 
questins.jpg
In this you can start a new Topic or post a new question if the user was logged in. 
 
So far so good. Let us create the final step in this i.e creating questions and posting replies, first let us see how to create questions.
 
Create a class in the model with the name "Questions"; your class should be as follows:
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.ComponentModel.DataAnnotations;  
  6. namespace mvcForumapp.Models  
  7. {  
  8.     public class Questions  
  9.     {  
  10.         [Required(ErrorMessage = "Title required")]  
  11.         [Display(Name = "Enter Title")]  
  12.         [StringLength(20, MinimumLength = 4)]  
  13.         public string TopicTitle { getset; }  
  14.         [Required(ErrorMessage = "Description required")]  
  15.         [Display(Name = "Enter Description")]  
  16.         [StringLength(20, MinimumLength = 10)]  
  17.         public string TopicDescription { getset; }  
  18.         [Required(ErrorMessage = "Content required")]  
  19.         [StringLength(Int32.MaxValue, MinimumLength = 10)]  
  20.         public string TopicContent { getset; }  
  21.     }  
  22. }   
Create a controller with the name "Question" and replace the code with this:
  1. public class QuestionController : Controller  
  2. {  
  3.     [HttpGet]  
  4.     public ActionResult PostQuestion()  
  5.     {  
  6.         int techID = Convert.ToInt16(Request.QueryString["TechID"].ToString());  
  7.         return View();  
  8.     }  
  9. }   
This is how it is viewed when you route to the "PostQuestion" view:
 
postques.jpg
 
Create another method in the same controller with HttpPost to post the question:
  1. [HttpPost]  
  2. public ActionResult PostQuestion(mvcForumapp.Models.Questions user)  
  3. {  
  4.     int techID = 0;  
  5.     if (ModelState.IsValid)  
  6.     {  
  7.         techID = Convert.ToInt16(Request.QueryString["TechID"].ToString());  
  8.         using (var db = new newForumDBEntities())  
  9.         {  
  10.             var userdets = db.tblQuestions.CreateObject();  
  11.             userdets.TechID = Convert.ToInt16(Request.QueryString["TechID"].ToString());  
  12.             userdets.QuestionTitle = user.TopicTitle;  
  13.             userdets.QuestionDesc = user.TopicContent;  
  14.             userdets.DatePosted = DateTime.Now;  
  15.             userdets.UserName = Session["UserName"].ToString();  
  16.             userdets.viewCount = 0;  
  17.             userdets.ReplyCount = 0;  
  18.             db.tblQuestions.AddObject(userdets);  
  19.             db.SaveChanges();  
  20.             return RedirectToAction("DisplayQuestions""Technology"new { TechID = techID });  
  21.         }  
  22.     }  
  23.     return View(user);  
  24. } 
After a successful post you will be routed to the list of questions for that technology.
 
You can do the same for replys by creating a class in "Model" with a name called "Replys" and adding the necessary for that. This is how it is displayed when a post has replys.

For viewing the questions with replies add "View" and "Controller" correspondingly and your code should be as follows in the controller:
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Web;  
  5. using System.Web.Mvc;  
  6. using System.Data.SqlClient;  
  7. using System.Data;  
  8.   
  9. namespace mvcForumapp.Controllers  
  10. {  
  11.     public class Question_AnswerController : Controller  
  12.     {  
  13.         newForumDBEntities db = new newForumDBEntities();  
  14.         int vwcnt = 0;  
  15.   
  16.         [HttpGet]  
  17.         public ActionResult displayQuestionwithAnswers()  
  18.         {  
  19.             var paramQuesID = new SqlParameter("@QuestionID", SqlDbType.Int);  
  20.             var paramRepCnt = new SqlParameter("@viewcount", SqlDbType.Int);  
  21.             int quesID = Convert.ToInt16(Request.QueryString["QuestionID"].ToString());  
  22.             paramQuesID.Value = quesID;  
  23.   
  24.             var viewcount = db.tblQuestions.Where(e1 => e1.QuestionID == quesID).FirstOrDefault();  
  25.             vwcnt = viewcount.viewCount;  
  26.             if (vwcnt == 0)  
  27.             {  
  28.                 vwcnt++;  
  29.                 paramRepCnt.Value = vwcnt;  
  30.                 var v = db.ExecuteStoreCommand("UPDATE tblQuestions SET viewCount = @viewcount WHERE QuestionID = @QuestionID", paramRepCnt, paramQuesID);  
  31.             }  
  32.   
  33.             else  
  34.             {  
  35.                 vwcnt = vwcnt + 1;  
  36.                 paramRepCnt.Value = vwcnt;  
  37.                 var v = db.ExecuteStoreCommand("UPDATE tblQuestions SET viewCount = @viewcount WHERE QuestionID = @QuestionID", paramRepCnt, paramQuesID);  
  38.             }  
  39.   
  40.             List<mvcForumapp.Questionwithreplys_Result> disp = db.Questionwithreplys(quesID).ToList();  
  41.             return View(disp);  
  42.         }  
  43.   
  44.         [HttpGet]  
  45.         public ActionResult GetPhoto()  
  46.         {  
  47.             //RouteData.Values["QuesID"]  
  48.             int quesID = Convert.ToInt16(Request.QueryString["QuestionID"]);  
  49.             byte[] photo = null;  
  50.   
  51.             var usrname = (from a in db.tblQuestions  
  52.                            where a.QuestionID == quesID  
  53.                            select new { a.UserName });  
  54.             var v = db.tblUsers.Where(p => p.UserName == usrname.FirstOrDefault().UserName).Select(img => img.Photo).FirstOrDefault();  
  55.             photo = v;  
  56.             return File(photo, "image/jpeg");  
  57.         }  
  58.         [HttpGet]  
  59.         public ActionResult ReplyPhoto()  
  60.         {  
  61.             //RouteData.Values["QuesID"]  
  62.             int quesID = Convert.ToInt16(Request.QueryString["QuestionID"]);  
  63.             byte[] photo = null;  
  64.   
  65.             var usrname = (from a in db.tblReplies  
  66.                            where a.ReplyID == quesID  
  67.                            select new { a.UserName });  
  68.             var v = db.tblUsers.Where(p => p.UserName == usrname.FirstOrDefault().UserName).Select(img => img.Photo).FirstOrDefault();  
  69.             photo = v;  
  70.             return File(photo, "image/jpeg");  
  71.         }  
  72.     }  
  73. }   
View for the corresponding controller:
  1. @model IEnumerable<mvcForumapp.Questionwithreplys_Result>  
  2.    
  3. @{  
  4.     ViewBag.Title = "Index";  
  5.     Layout = "~/Views/Shared/_Layout.cshtml";  
  6. }  
  7. <style type="text/css">  
  8.     .disabled  
  9.     {  
  10.         /* Text and background colour, medium red on light yellow */  
  11.         float: right;  
  12.         margin-right: 20px;  
  13.         background: #999;  
  14.         background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#dadada), to(#f3f3f3));  
  15.         border-top: 1px solid #c5c5c5;  
  16.         border-right: 1px solid #cecece;  
  17.         border-bottom: 1px solid #d9d9d9;  
  18.         border-left: 1px solid #cecece;  
  19.         color: #8f8f8f;  
  20.         box-shadow: none;  
  21.         -moz-box-shadow: none;  
  22.         -webkit-box-shadow: none;  
  23.         cursor: not-allowed;  
  24.         text-shadow: 0 -1px 1px #ebebeb;  
  25.     }  
  26.     .active  
  27.     {  
  28.         box-shadow: none;  
  29.         -moz-box-shadow: none;  
  30.         -webkit-box-shadow: none;  
  31.         cursor: allowed;  
  32.     }  
  33. </style>  
  34. <br />  
  35. <div style="float: left; margin-left: 20px;">  
  36.     @foreach (var item in Model)  
  37.     {  
  38.         @Html.ActionLink("Back""DisplayQuestions""Technology"new { TechID = item.TechID }, null)  
  39.         break;  
  40.     }  
  41. </div>  
  42. <div class="topic_controls">  
  43.     <br />  
  44.     <ul class="comRigt" runat="server" id="lnkTopic">  
  45.         <li>  
  46.             <img alt="Add Reply" src="http://www.gimptalk.com/public/style_images/master/arrow_rotate_clockwise.png" />  
  47.             @if (Session["UserName"] != null)  
  48.             {  
  49.   
  50.    
  51.                 foreach (var item in Model)  
  52.                 {     
  53.                 @Html.ActionLink("Add Reply""PostReply""Home"new { @class = "active", onclick = "javascript:return true;", QuestionID = item.QuestionID, TechID = item.TechID }, null)  
  54.                     break;  
  55.                 }  
  56.             }  
  57.             else  
  58.             {  
  59.                 foreach (var item in Model)  
  60.                 {  
  61.                 @Html.ActionLink("Add Reply""PostReply""Home"new { title = "Please login to post replys", TechID = item.QuestionID, @class = "disabled", onclick = "javascript:return false;" })  
  62.                     break;  
  63.                 }  
  64.             }  
  65.         </li>  
  66.     </ul>  
  67.     <br />  
  68.     <h2 class="maintitle">  
  69.         <span class="main_topic_title">  
  70.             @foreach (var item in Model)  
  71.             {  
  72.                 string strTopic = item.QuestionTitle;  
  73.                 @Html.Label("Topic", strTopic)  
  74.                 break;  
  75.             }  
  76.         </span>  
  77.     </h2>  
  78.     <br />  
  79.     <div class="post_wrap">  
  80.         <h3>  
  81.               <span class="author vcard">  
  82.                 @foreach (var item in Model)  
  83.                 {  
  84.                     string User = item.quesaskedby;  
  85.                     @Html.ActionLink(User, "Details""Home"new { Username = item.quesaskedby }, null)  
  86.                     break;  
  87.                 }  
  88.                 @*<asp:linkbutton id="lnkUsername" runat="server" text='<%#Eval("UserName") %>' font-underline="false"></asp:linkbutton>*@  
  89.             </span>  
  90.         </h3>  
  91.         <div class="authornew">  
  92.             <ul>  
  93.                 <li class="avatar">  
  94.                     @foreach (var item in Model)  
  95.                     {  
  96.                         <img alt="" src="@Url.Action("GetPhoto", "Question_Answer", new { QuestionID = item.QuestionID })" height="100" width="100" class="photo" />  
  97.                         break;  
  98.                     }  
  99.                 </li>  
  100.             </ul>  
  101.         </div>  
  102.         <div class="postbody">  
  103.             <p class="postnew">  
  104.                 @foreach (var item in Model)  
  105.                 {  
  106.                     DateTime dt = Convert.ToDateTime(item.DatePosted);  
  107.                     string strDate = dt.ToString("dd MMMM yyyy - hh:mm tt");  
  108.                     @Html.Label(strDate)  
  109.                     break;  
  110.                 }  
  111.                 @*<asp:label id="lblDateposted" text='<%#Eval("DatePosted") %>' font-underline="false"  
  112.                     runat="server" cssclass="edit"></asp:label>*@  
  113.             </p>  
  114.             <br />  
  115.             <br />  
  116.             <div class="post entry-content ">  
  117.                 @*<asp:label id="Label1" text='<%#Eval("QuestionDesc") %>' font-underline="false" runat="server"  
  118.                     cssclass="edit"></asp:label>*@  
  119.                 @foreach (var item in Model)  
  120.                 {  
  121.                     @Html.Label(item.QuestionDesc)  
  122.                     break;  
  123.                 }  
  124.             </div>  
  125.         </div>  
  126.     </div>  
  127.     <br />  
  128.     <br />  
  129.     <br />  
  130.     <ul style="background-color: #e4ebf3; text-align: right; background-image: url(http://www.gimptalk.com/public/style_images/master/gradient_bg.png);  
  131.         background-repeat: repeat-x; background-position: 40%; font-size: 1em; text-align: right;  
  132.         padding: 6px 10px 10px 6px; clear: both;">  
  133.         <li>  
  134.             <img alt="Add Reply" src="http://www.gimptalk.com/public/style_images/master/comment_add.png" />  
  135.             @if (Session["UserName"] != null)  
  136.             {  
  137.                 foreach (var item in Model)  
  138.                 {  
  139.                 @Html.ActionLink("Add Reply""PostReply""Home"new { @class = "active", onclick = "javascript:return true;", QuestionID = item.QuestionID, TechID = item.TechID }, null)  
  140.                     break;  
  141.                 }  
  142.             }  
  143.             else  
  144.             {  
  145.                 foreach (var item in Model)  
  146.                 {  
  147.                 @Html.ActionLink("Add Reply""PostReply""Home"new { title = "Please login to post replys", @class = "disabled", onclick = "javascript:return false;", TechID = item.QuestionID })  
  148.                     break;  
  149.                 }  
  150.             }  
  151.             @*<asp:linkbutton id="lnkpostReply" runat="server" onclick="lnkpostReply_Click" text="Reply"></asp:linkbutton>*@  
  152.         </li>  
  153.     </ul>  
  154. </div>  
  155. <br />  
  156. <br />  
  157. <div>  
  158.     @foreach (var item in Model)  
  159.     {  
  160.         if (item.ReplyUser != null)  
  161.         {  
  162.         <div class="topic_controls">  
  163.             <div class="post_wrap">  
  164.                 <h3>  
  165.                        
  166.                     @if (item.ReplyUser != null)  
  167.                     {  
  168.                         <span class="author vcard">  
  169.                             @Html.ActionLink(item.ReplyUser.ToString(), "Details""Home"new { Username = item.ReplyUser },  
  170.                      null)</span>  
  171.                     }  
  172.                     <br />  
  173.                     @*<asp:linkbutton id="lnkUsername" runat="server" text='<%#Eval("UserName") %>' font-underline="false"></asp:linkbutton>*@  
  174.                 </h3>  
  175.                 <div class="authornew">  
  176.                     <ul>  
  177.                         <li class="avatar">  
  178.                             @if (item.ReplyID != null)  
  179.                             {  
  180.                                 <img alt="" src="@Url.Action("ReplyPhoto", "Question_Answer", new { QuestionID = item.ReplyID })"  
  181.                     height="100" width="100" class="photo" />  
  182.                             }  
  183.                             <br />  
  184.                         </li>  
  185.                     </ul>  
  186.                 </div>  
  187.                 <div class="postbody">  
  188.                     <p class="postnew">  
  189.                         @if (item.date != null)  
  190.                         {  
  191.                             @Html.Label(item.date.Value.ToString("dd MMMM yyyy - hh:mm tt"))  
  192.                         }  
  193.                         <br />  
  194.                         @*<asp:label id="lblDateposted" text='<%#Eval("DatePosted") %>' font-underline="false"  
  195.                     runat="server" cssclass="edit"></asp:label>*@  
  196.                     </p>  
  197.                     <br />  
  198.                     <br />  
  199.                     <div class="post  
  200.                     entry-content ">  
  201.                         @if (item.ReplyMsg != null)  
  202.                         {  
  203.                             @Html.Label(item.ReplyMsg)  
  204.                         }  
  205.                         <br />  
  206.                     </div>  
  207.                     @if (item.ReplyID != null)  
  208.                     {  
  209.                         <ul style="background-color: #e4ebf3; text-align: right; background-image: url(http://www.gimptalk.com/public/style_images/master/gradient_bg.png);  
  210.                             background-repeat: repeat-x; background-position: 40%; font-size: 1em; text-align: right;  
  211.                             padding: 6px 10px 10px 6px; clear: both;">  
  212.                             <li>  
  213.                                 <img alt="Add Reply" src="http://www.gimptalk.com/public/style_images/master/comment_add.png" />  
  214.                                 @*<asp:linkbutton id="lnkpostReply" runat="server" onclick="lnkpostReply_Click" text="Reply"></asp:linkbutton>*@  
  215.                                 @if (Session["UserName"] == null)  
  216.                                 {  
  217.                                   
  218.                                     @Html.ActionLink("Add Reply""PostReply""Home"new { title = "Please login to post replys", @class = "disabled", onclick = "javascript:return false;", TechID = item.QuestionID })  
  219.                                   
  220.                                 }  
  221.                                 else  
  222.                                 {  
  223.                                     @Html.ActionLink("Add Reply""PostReply""Home"new { @class = "active", onclick = "javascript:return true;", QuestionID = item.QuestionID, TechID = item.TechID }, null)  
  224.                                 }  
  225.                             </li>  
  226.                         </ul>  
  227.                     }  
  228.                 </div>  
  229.             </div>  
  230.         </div>  
  231.         }  
  232.     }  
  233. </div>  
The result is as follows:
 
replies.jpg
 

 
That's it; the forums application is over.
 
Download the code and test it by creating the database with the given tables by adding the entity model to the application.

Check out my sample video for the demo, no audio in that just to show an overview of how the application runs.

If any queries please feel free to ask.