ساخت یک پروژه بلاگ با قابلیت شخصی سازی در MVC

جمعه 23 بهمن 1394

در این مقاله به پیاده سازی یک پروژه ساده وبلاگ خواهیم پرداخت .در این پروژه از بانک برای نگه داری اطلاعات استفاده نخواهیم کرد بلکه برای ذخیره و تبادل اطلاعات از Json کمک خواهیم گرفت بنابراین در طول این مقاله با مفاهیم اصلی MVC و همچنین کار با Json به صورت عملی آشنا خواهید شد .

ساخت یک پروژه بلاگ با قابلیت شخصی سازی در MVC

در این مقاله به پیاده سازی یک پروژه ساده وبلاگ خواهیم پرداخت .در این پروژه از بانک برای نگه داری اطلاعات استفاده نخواهیم کرد بلکه برای ذخیره و تبادل اطلاعات از Json کمک خواهیم گرفت بنابراین در طول این مقاله با مفاهیم اصلی MVC و همچنین کار با Json به صورت عملی آشنا خواهید شد .

 همیشه قبل از شروع کار عملی کمی راجع به مفاهیم اولیه صحبت خواهیم کرد .همان طور که می دانید فرآیند تبدیل یک شی به رشته برای ذخیره کردن در حافظه را Serialization می گویند .همچنین عکس این عمل یعنی تبدیل رشته به شی را deserialize می گویند.

Json یک فرمت تبادل اطلاعات است که زبان جاوااسکریپت به صورت خودکار آن را می فهمد ولی برای سایر زبان ها نیاز داریم که فرم ورک هایی را به برنامه اضافه کنیم تا بتوانیم با این فرمت تبادل اطلاعات یعنی json کار کنیم .

برای کار با json رفرنس System.web.Extensions.dll را به برنامه اضافه می کنیم .سپس یک نمونه شی از JavaScriptSerializer ایجاد می کنیم .در داخل این کلاس دو متد مهم Serialize و deSerialize  قرار دارد که با استفاده از این دو متد به deserialize و Serialize کردن اشیا می پردازیم .

همچنین به روش دیگری هم می توان با json کار کرد و آنهم این است که در کد زیر یک لیستی از اشیا (هر شی ایی فرقی نمی کند ) را به متد json داده ایم و همچنین در پارامتر دوم مشخص کرده ایم که json می تواند به داده ها دسترسی داشته باشد .

 

return Json(ObjEmp, JsonRequestBehavior.AllowGet);

این خط باعث می شود که داده هایی از نوع json را به سمت view ارسال کنیم اگر که قصد داشته باشیم از این داده ها در داخل viewخود استفاده کنیم و به همان صورت json نمایش داده نشود لازم است که در سمت view به صورت زیر عمل کنیم که ابتدا رفرنس jquery را به پروژه می دهیم سپس در داخل صفحه view و در اسکریپتی که می نویسیم با کد زیر

$.getJSON("Home/EmpDetails",

اطلاعاتی که اکشن ما به صورت json داده بود را گرفته و آن را به شیوه دلخواه نمایش می دهیم .مثلا می توان آنها را به صورت جداول و در داخل سطر هایی نشان داد به کد زیر توجه کنید .

<script>

    $(document).ready(function () {

        //Call EmpDetails jsonResult Method

        $.getJSON("Home/EmpDetails",

        function (json) {

        var tr;

        //Append each row to html table

        for (var i = 0; i < json.length; i++) {

                tr = $('<tr/>');

                tr.append("<td>" + json[i].Id + "</td>");

                tr.append("<td>" + json[i].Name + "</td>");

                tr.append("<td>" + json[i].City + "</td>");

                tr.append("<td>" + json[i].Address + "</td>");

                $('table').append(tr);

            }

        });

    });

</script>

<table class="table table-bordered table-condensed table-hover table-striped">

        <thead>

        <tr>

        <th>Id</th>

        <th>Name</th>

        <th>City</th>

        <th>Address</th>

        </tr>

        </thead>

        <tbody></tbody>

</table>

حال که تا حدی با json آشنا شدید به پروژه عملی خود باز می گردیم . در این جا قصد داریم یک بلاگ ایجاد کنیم .همان طور که می دانید بلاگ مکانی است که در آن موضوعات مورد علاقه اخبار و تبلیغاتی را با افراد دیگر در اینترنت Share می کنیم .انواع مختلفی از بلاگ ها وجود دارند که از آن جمله می توان به Microblogs ، Personal blogs، Media blogs اشاره کرد .در واقع همان وب سایت است فقط شاید کمی جنبه تجاری و اداری آن کمتر باشد .

یک پروژه از نوع mvc و به صورت Empty ایجاد می کنیم . برای اینکه بتوان با json کار کرد کنابخانه آن را به پروژه خود اضافه می کنیم این کار توسط nuget به راحتی انجام می شود .در داخل tool=>nugget Package Manager=>Package Manager Consol رفته و دستور زیر را در آن تایپ و اینتر را بزنید

PM> Install-Package Newtonsoft.Json -Version 7.0.1

مدل

اگر تجربه ساخت پروژه با mvc را داشته باشید می دانید که بهتر است ابتدا مدل پروژه خود را تعیین کنید این کار به شما ایده ایجاد کنترلر و viewهای مربوط به آن را میدهد .مدلی که در اینجا به آن احتیاج داریم یک مدل برای Post است .ساختار این مدل در زیر آورده شده است



using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using Newtonsoft.Json;

namespace PersonalBlogTemplateWithServices.Models
{
     public class BlogPostModel
     {
         // General properties
         public int ID { get; set; }
         public string Title { get; set; }
         public string Content { get; set; }
         public List<string> Tags { get; set; }
         // Time based properties
         public DateTime CreateTime { get; set; }
        // Other properties and settings may include UserID, RoleID etc.
      }
      // The class to manage the data-sources
      public class PostManager
      {
          // Define the members

          private static string PostsFile = HttpContext.Current.Server.MapPath("~/App_Data/Posts.json");

          private static List<BlogPostModel> posts = new List<BlogPostModel>();
          // The CRUD functions
          public static void Create(string postJson)
          {
              var obj = JsonConvert.DeserializeObject<BlogPostModel>(postJson);

              if(posts.Count > 0)
              {
                  posts = (from post in posts
                           orderby post.CreateTime
                           select post).ToList();
                  obj.ID = posts.Last().ID + 1;
              } else
              {

                  obj.ID = 1;
            }
          }
          posts.Add(obj);
          save();
      }
      public static List<BlogPostModel> Read()

      {

          // Check if the file exists.

          if(!File.Exists(PostsFile))
          {
              File.Create(PostsFile).Close();
              File.WriteAllText(PostsFile, "[]"); // Create the file if it doesn't exist.
          }
          posts = JsonConvert.DeserializeObject<List<BlogPostModel>>(File.ReadAllText(PostsFile));
          return posts;
      }
      public static void Update(int id, string postJson)
      {
          Delete(id);
          Create(postJson);
          save();
      }
      public static void Delete(int id)
      {
          posts.Remove(posts.Find(x => x.ID == id));
          save();
     }
      // Output function

      private static void save()

      {

          File.WriteAllText(PostsFile, JsonConvert.SerializeObject(posts));
       }
    }

در این مدل که آیتم های آن شامل id, title و .... است به تعریف کنترلرها  و viewهای مربوطه خواهیم پرداخت .همان طور که دیدید در این مدل چهار عمل اصلی را هم پیاده سازی کرده ایم .حال نوبت این است که یک کنترلر ایجاد کنیم .این کنترلر حاوی اکشن هایی است که توسط آن دیتاهای خود که در اینجا فقط post است را دستکاری می کنیم .

مدل ما از دو کلاس تشکیل شده است یکی BlogPostModel است که در آن ساختار کلاس واشیا خود را مشخص کرده ایم و دیگری PostManager است که در آن چهار عمل اصلی را پیاده سازی کرده ایم .خود این کلاس از نوع public است اما متدهایی که در داخل آن تعریف شده اند به صورت Static هستند .

نام کنترلری که ایجاد کرده ایم Blog است .کد آن را در زیر می بینید

using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using PersonalBlogTemplateWithServices.Models;
using Newtonsoft.Json;
namespace PersonalBlogTemplateWithServices.Controllers
{
    public class BlogController : Controller
    {
        // GET: Blog
        public ActionResult Index()
        {
            // Read the list

            var blogs = PostManager.Read();

            if (blogs == null)
            {
                 ViewBag.Empty = true;
                 return View();
            }
            else
            {
                 // Just for sorting.

                 blogs = (from blog in blogs
                          orderby blog.CreateTime descending
                         select blog).ToList();
                 ViewBag.Empty = false;
                 return View(blogs);
           }
        }
       [Route("blog/read/{id}")] // Set the ID parameter
        public ActionResult Read(int id)
        {
            // Read one single blog
            var blogs = PostManager.Read();
            BlogPostModel post = null;
            if(blogs != null && blogs.Count > 0)
            {
                post = blogs.Find(x => x.ID == id);
            }

           if(post == null)
            {
                ViewBag.PostFound = false;

                return View();

            } else

            {
                ViewBag.PostFound = true;
                return View(post);
            }
        }
       public ActionResult Create()
        {
            if (Request.HttpMethod == "POST")
            {
                 // Post request method
                 var title = Request.Form["title"].ToString();

                 var tags = Request.Form["tags"].ToString().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

                 var content = Request.Form["content"].ToString();


                 // Save content

                 var post = new BlogPostModel { Title = title, CreateTime = DateTime.Now, Content = content, Tags = tags.ToList() };
                 PostManager.Create(JsonConvert.SerializeObject(post));
                // Redirect
                 Response.Redirect("~/blog");
            }
            return View();
        }
        [Route("blog/edit/{id}")]

        public ActionResult Edit(int id)

        {

             if(Request.HttpMethod == "POST")
             {
                 // Post request method
                 var title = Request.Form["title"].ToString();
                 var tags = Request.Form["tags"].ToString().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

                 var content = Request.Form["content"].ToString();
                 // Save content
                 var post = new BlogPostModel { Title = title, CreateTime = DateTime.Now, Content = content, Tags = tags.ToList() };

                 PostManager.Update(id, JsonConvert.SerializeObject(post));
                // Redirect
                Response.Redirect("~/blog");
            } else
            {
                // Find the required post.

                 var post = PostManager.Read().Find(x => x.ID == id);
                if (post != null)
                 {
                     // Set the values
                     ViewBag.Found = true;
                     ViewBag.PostTitle = post.Title;
                     ViewBag.Tags = post.Tags;
                    ViewBag.Content = post.Content;
                 }
                 else

                 {

                     ViewBag.Found = false;
               }
             }
             // Finally return the view.

             return View();
         }
    }
}

در این کنترلر چهار اکشن وجود دارد .در داخل اکشن index ابتدا یک متغیر var به نام blogs تعریف کرده ایم .این متغیر را با post هایی که داریم پر می کنیم .یعنی با نوشتن PostManager.Read  این متغیر را با لیستی از post های خود پر کرده ایم .

برای ساخت view مربوط به این اکشن از کدهای زیر استفاده می کنیم

@model List<Blog.Models.BlogPostModel>
@{
    ViewBag.Title = "My Blog";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
@if(ViewBag.Message != null)
{
    <h4>@ViewBag.Message</h4>
}
@if (Model == null || Model.Count == 0)
{
    <div class="thumbnail">

        <h4>Blog empty</h4>

        <p>Either under development, or author is busy. Visit back again later! :-)</p>

        <a href="~/blog/create">ایجاد پست جدید</a>
    </div>
}
else
{
    <div class="panel panel-success">

        <div class=" panel-heading" style="margin-top:20px"><h4>وبلاگ شخصی من</h4>

        </div>
        <div class="panel-body">
            <p>پست های من که در زیر لیست شده اند را بخوانید </p>
            <br />
            <div class="thumbnail">

                <a href="~/blog/create">ایجاد پست جدید</a>

                @foreach (var post in Model)

                {
                int tagIndex = 1;
                <h4>
                   <a href="~/blog/read/@post.ID">@post.Title</a>
                </h4>
                foreach (var tag in post.Tags)
                {
                if(tagIndex == post.Tags.Count)

               {
                <span class="tag"><a href="~/blog/tag/@tag">@tag</a></span>

                    <hr />
                }
                else
                {
                <span class="tag"><a href="~/blog/tag/@tag">@tag</a></span>

                }


                tagIndex++;
                }
                }
            </div>
        </div>
    </div>
}

در این صفحه ابتدا چک کرده ایم که اگر لیست پست های ما خالی بود پیامی به کاربر نمایش داده شود .و در غیر این صورت به ازای هر پست در داخل مدل لینکی با محتوای همان پست ایجاد می کنیم .

اکشن Create

در داخل این اکشن Create ابتدا تعیین می کنیم که نوع درخواست ما از نوع post است .اگر بود وارد بلاک if می شویم در این بلاک تمام اطلاعات را از داخل فرم خوانده و یک شی BlogPostModel ایجاد می کنیم .سپس این شی را به متد create از کلاس PostManager می دهیم .البته توجه کنید که پارامتر این تابع از نوع string است .بنابراین توسط متد( JsonConvert.SerializeObject(post شی post را که ایجاد کرده بودیم به یک رشته تبدیل کرده و به این متد پاس می دهیم .

در داخل متد create دوباره این رشته را به شی از نوع BlogPostModel تبدیل می کنیم .بعد در داخل فولدر AppData خود یک فایل متنی به نام posts داریم این فایل حکم دیتابیس ما را دارد .در متد create چک کرده ایم که اگر این پوشه خالی بود یک شی BlogPostModel با id برابر یک برای ما ایجاد کند و در غیر این صورت با id یک به علاوه بزرگترین id موجود شی را برای ما ساخته و داخل posts ذخیره کند

view مربوط به create به صورت زیر است

@{

    ViewBag.Title = "New Post";

}


<h2>Create new blog post</h2>


<form method="post">

    <label>Title</label>

    <input type="text" name="title" class="form-control" placeholder="The headline goes here..." /><br />

    <label>Tags</label>

    <input type="text" name="tags" class="form-control" placeholder="Separate each tag using a comma ','." /><br />

    <label>Content</label>

    <textarea name="content" class="form-control" style="height: 300px;" placeholder="What would you like to write?"></textarea><br />

    <input type="submit" style="width: auto; font-weight: 600;" value="Post" /><br />

</form>

اگر این viewرا اجرا کنیم شکل زیر را خواهیم دید .

بعد از اینکه پست جدید ایجاد کنید و دکمه post را بزنید به صفحه ایندکس هدایت خواهید شد

اکشن read به این صورت است که در آن به کلاس PostManager و بعد تابع read رفته و همه مطالب داخل posts را به صورت شی BlogPostModel ایجاد کرده و آن را به اکشن باز می گردانیم .

View مربوط به این اکشن به صورت زیر است

@model Blog.Models.BlogPostModel
@{
    ViewBag.Title = Model.Title;
    var tagIndex = 1;
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="panel panel-success">

    <div class=" panel-heading" style="margin-top:20px">متن پست مورد نظر شما</div>

    <div class="panel-body">

        <h4 style="font-weight: bold;">@Model.Title</h4><p>@Html.Raw(Model.Content.Replace("\r", "\nbr />"))</p>

    </div>
    <div class="panel-footer"><p>پست شده توسط &mdash;برنامه نویسان &mdash; on @Model.CreateTime.ToString("MMMM dd, yyyy 'at' hh:mm tt")</p></div>
</div>
<p>
    Tagged under:
    @foreach (var tag in Model.Tags)
    {
        <span class="tag"><a href="~/blog/tag/@tag">@tag</a></span>
        if (tagIndex == Model.Tags.Count)
        {
                    // In the end, write the edit hyperlink
            <br />
            <span><a href="~/blog/edit/@Model.ID">Edit</a></span>
        }
       }
    </p>

   همان طور که می بینید مدلی که به این ویو پاس داده ایم از نوع BlogPostModel است .و بعد آیتم های آن را به زیر نمایش داده ایم .

و در اخر متد Edit را پیاده سازی می کنیم .در این اکشن هم دوباره از داخل صفحه view خود اطلاعات را خوانده و یک شی از نوع BlogPostModel ایجاد می کنیم .بعد از این کار متد update از کلاس BlogManager را فراخوانی می کنیم .در داخل این متد متدهای دیگر کلاس BlogManager را به ترتیب ابتدا Delete(id); سپس Create(postJson); و نهایتا  save(); را فراخوانی می کنیم .

صفحه view مربوط به این اکشن به صورت زیر است .

@{
    ViewBag.Title = "Edit the post";
    Layout = "~/Views/Shared/_Layout.cshtml";
    var tags = string.Join(", ", ViewBag.Tags as List<string>);
}
<h2>Edit the post</h2>
<form method="post">
    <label>Title</label>
    <input type="text" name="title" class="form-control" value="@ViewBag.PostTitle" placeholder="The headline goes here..." /><br />
    <label>Tags</label>
    <input type="text" name="tags" class="form-control" value="@tags" placeholder="Separate each tag using a comma ','." /><br />
    <label>Content</label>
    <textarea name="content" class="form-control" style="height: 300px;" placeholder="What would you like to write?">@ViewBag.Content</textarea><br />

    <input type="submit" style="width: auto; font-weight: 600;" value="Post" /><br />
</form>

اگر این ویو را اجرا کنیم شکل زیر را خواهیم دید

فایل های ضمیمه

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید