วันพุธที่ 8 กุมภาพันธ์ พ.ศ. 2560

Asp.net MVC - Enabling Code First Migrations



การเปลี่ยนข้อมูลบน database โดย code

0. ถ้าเราต้องการย้าย database เราก็เปลี่ยน connecttion string ตรง Web.config นะ

1. พิมพ์ PM> Enable-Migrations -ContextTypeName SuaSilverShop_V2.DAL.StoreContext

2. PM> add-migration InitialDatabase

3. เพิ่มโค้ดใน 201702081048235_InitialDatabase

namespace SuaSilverShop_V2.Migrations
{
    using System;
    using System.Data.Entity.Migrations;
    
    public partial class initNewDatabase : DbMigration
    {
        public override void Up()
        {
            CreateTable(
            "dbo.Categories",
            c => new
            {
                ID = c.Int(nullable: false, identity: true),
                Name = c.String(),
            })
            .PrimaryKey(t => t.ID);
            CreateTable(
            "dbo.Products",
            c => new
            {
                ID = c.Int(nullable: false, identity: true),
                Name = c.String(),
                Description = c.String(),
                Price = c.Decimal(nullable: false, precision: 18, scale: 2),
                CategoryID = c.Int(),
            })
            .PrimaryKey(t => t.ID)
            .ForeignKey("dbo.Categories", t => t.CategoryID)
            .Index(t => t.CategoryID);
        }
        public override void Down()
        {
            DropForeignKey("dbo.Products", "CategoryID", "dbo.Categories");
            DropIndex("dbo.Products", new[] { "CategoryID" });
            DropTable("dbo.Products");
            DropTable("dbo.Categories");
        }
    }
}


4. ใน Migrations\Configuration.cs เพิ่ม


namespace SuaSilverShop_V2.Migrations
{
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Migrations;
    using System.Linq;
    using Models;
    using System.Collections.Generic;

    internal sealed class Configuration : DbMigrationsConfiguration<SuaSilverShop_V2.DAL.StoreContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
            ContextKey = "SuaSilverShop_V2.DAL.StoreContext";
        }

        protected override void Seed(SuaSilverShop_V2.DAL.StoreContext context)
        {
           



            var categories = new List<Category>
            {
                new Category { Name = "Clothes" },
                new Category { Name = "Play and Toys" },
                new Category { Name = "Feeding" },
                new Category { Name = "Medicine" },
                new Category { Name= "Travel" },
                new Category { Name= "Sleeping" }
            };
            categories.ForEach(c => context.Categories.AddOrUpdate(p => p.Name, c));
            context.SaveChanges();
            var products = new List<Product>
            {
                new Product { Name = "Sleep Suit", Description="For sleeping or general wear",
                Price=4.99M, CategoryID=categories.Single( c => c.Name == "Clothes").ID },
                new Product { Name = "Vest", Description="For sleeping or general wear",
                Price=2.99M, CategoryID=categories.Single( c => c.Name ==
                "Clothes").ID },
                new Product { Name = "Orange and Yellow Lion", Description="Makes a squeaking noise",
                    Price=1.99M, CategoryID=categories.Single( c => c.Name == "Play and Toys").ID },
                new Product { Name = "Blue Rabbit", Description="Baby comforter", Price=2.99M,
                CategoryID=categories.Single( c => c.Name == "Play and Toys").ID },

                new Product { Name = "3 Pack of Bottles", Description="For a leak free drink everytime",
                    Price=24.99M, CategoryID=categories.Single( c => c.Name == "Feeding").ID },
                new Product { Name = "3 Pack of Bibs", Description="Keep your baby dry when feeding",
                    Price=8.99M, CategoryID=categories.Single( c => c.Name == "Feeding").ID },
                new Product { Name = "Powdered Baby Milk", Description="Nutritional and Tasty",
                    Price=9.99M, CategoryID=categories.Single( c => c.Name == "Feeding").ID },
                new Product { Name = "Pack of 70 Disposable Nappies", Description="Dry and secure nappies with snug fit",
                    Price=19.99M, CategoryID= categories.Single( c => c.Name == "Feeding").ID },
                new Product { Name = "Colic Medicine", Description="For helping with baby colic pains", 
                    Price=4.99M, CategoryID=categories.Single( c => c.Name == "Medicine").ID },
                new Product { Name = "Reflux Medicine", Description="Helps to prevent milk regurgitation and sickness",
                    Price=4.99M, CategoryID=categories.Single( c => c.Name == "Medicine").ID },
                new Product { Name = "Black Pram and Pushchair System", Description="Convert from pram to pushchair, with raincover", 
                    Price=299.99M, CategoryID= categories.Single( c => c.Name == "Travel").ID },
                new Product { Name = "Car Seat", Description="For safe car travel",
                Price=49.99M, CategoryID= categories.Single( c => c.Name == "Travel").ID },
                new Product { Name = "Moses Basket", Description="Plastic moses basket",
                Price=75.99M, CategoryID=categories.Single( c => c.Name == "Sleeping").ID },
                new Product { Name = "Crib", Description="Wooden crib", Price=35.99M,
                CategoryID= categories.Single( c => c.Name == "Sleeping").ID },
                new Product { Name = "Cot Bed", Description="Converts from cot into bed for older children",
                    Price=149.99M, CategoryID=categories.Single( c => c.Name == "Sleeping").ID },
                new Product { Name = "Circus Crib Bale", Description="Contains sheet, duvet and bumper",
                    Price=29.99M, CategoryID=categories.Single( c => c.Name == "Sleeping").ID },
                new Product { Name = "Loved Crib Bale", Description="Contains sheet,duvet and bumper",
                    Price=35.99M, CategoryID=categories.Single( c => c.Name == "Sleeping").ID }
                };
                products.ForEach(c => context.Products.AddOrUpdate(p => p.Name, c));
                context.SaveChanges();


        }
    }

}




5. พิมพ์ PM> Update-Database จบ

Asp.net MVC - การลบ Catalog




เราต้องเข้าใจว่า ใน Table Product มี Catelog เป็น foreign key อยู่


ดังนั้น เมื่อ เราลบ catelog ไป มันจะเกิด error ขึ้น เพราะว่า  Product ที่เป็น

catelog ชนิดนี้อยู่ หายไป






ดังนั้น ที่ function delete ใน CategoriesController
เราต้องเปลี่ยน product ที่ชนิด category นี้ ให้เป็น null



 // POST: Categories/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {          
         
            Category category = db.Categories.Find(id);

            foreach (var p in category.Products)
            {
                p.CategoryID = null;
            }

            db.Categories.Remove(category);
            db.SaveChanges();
            return RedirectToAction("Index");
        }




Asp.net MVC - Product View Model



การออกแบบ view model นั้น
เราต้องกำหนดสิ่งที่ต้องการส่งให้
view ในที่นี้คือ

- Products
- Search          คำค้น
- ชื่อ Category
- สตริง   ชื่อCatagory(จำนวน Items)  เก็บ เป็น List
- SelectListItem   เก็บ เป็น List   ใช้เพื่อ  - สร้างค่า categoryName เพื่อใช้เป็น value
                                                                  - สร้างค่า text display จาก "ชื่อCatagory(จำนวน Items)"





ดังนั้นเราจึงสร้าง class ได้ดังนี้

using SuaSilverShop_V2.Models;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;

namespace SuaSilverShop_V2.ViewModel
{
    public class ProductIndexViewModel
    {
        public IQueryable<Product> Products { get; set; }
        public string Search { get; set; }
        public IEnumerable<CategoryWithCount> CatsWithCount { get; set; }
        public string Category { get; set; }
        public IEnumerable<SelectListItem> CatFilterItems
        {
            get
            {
                var allCats = CatsWithCount.Select(cc => new SelectListItem
                {
                    Value = cc.CategoryName,
                    Text = cc.CatNameWithCount
                });
                return allCats;
            }
        }
    }


    public class CategoryWithCount
    {
        public int ProductCount { get; set; }
        public string CategoryName { get; set; }
        public string CatNameWithCount
        {
            get
            {
                return CategoryName + " (" + ProductCount.ToString() + ")";
            }
        }
    }

}




วิธีใช้ก็ง่ายแสนง่าย Update code ใน ProductsController เป็น

 // GET: Products
        public ActionResult Index(string category , string search)
        {



            ProductIndexViewModel viewModel = new ProductIndexViewModel();


            var products = db.Products.Include(p => p.Category);

            if( !String.IsNullOrEmpty(category) )
            {
                products = products.Where( p => p.Category.Name == category) ;
            }

            if( !String.IsNullOrEmpty(search) )
            {
                products = products.Where(p => p.Name.Contains(search) ||
                                            p.Description.Contains(search) ||
                                            p.Category.Name.Contains(search));
                viewModel.Search = search;

            }



            //group search results into categories and count how many items in each category
            viewModel.CatsWithCount = from matchingProducts in products
                                      where
                                      matchingProducts.CategoryID != null
                                      group matchingProducts by
                                      matchingProducts.Category.Name into
                                      catGroup
                                      select new CategoryWithCount()
                                      {
                                          CategoryName = catGroup.Key,
                                          ProductCount = catGroup.Count()
                                      };




            if (!String.IsNullOrEmpty(category))
            {
                products = products.Where(p => p.Category.Name == category);
            }


            viewModel.Products = products;

            return View(viewModel);

        }









ไปที่ Views\Products\Index.cshtml แล้วโมดิฟาย ซะ

@model SuaSilverShop_V2.ViewModels.ProductIndexViewModel

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")

    @using (Html.BeginForm("Index", "Products", FormMethod.Get))
    {
        <label>Filter by category:</label> @Html.DropDownListFor( vm => vm.Category, Model.CatFilterItems , "All")
        <input type="submit" value="Filter" />
    <input type="hidden" name="Search" id="Search" value="@Model.Search" />
    }

</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Category)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Products.First().Name)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Products.First().Description )
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Products.First().Price )
        </th>
        <th></th>




    </tr>

@foreach (var item in Model.Products) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Category.Name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Description)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Price)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
            @Html.ActionLink("Details", "Details", new { id=item.ID }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.ID })
        </td>
    </tr>
}

</table>


Asp.net MVC - Search simple



หน้าตา


หน้า _Layout.cshtml

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - My ASP.NET Application</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")

</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("Application name", "Index", "Admin", new { area = "" }, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>@Html.ActionLink("Home", "Index", "Admin")</li>
                    <li>@Html.ActionLink("About", "About", "Admin")</li>
                    <li>@Html.ActionLink("Contact", "Contact", "Admin")</li>
                    <li>@Html.ActionLink("จัดการ Categories", "Index", "Categories")</li>
                    <li>@Html.ActionLink("จัดการ Products", "Index", "Products")</li>
                </ul>


                    @using (Html.BeginForm("Index", "Products", FormMethod.Get, new
                    {
                        @class = "navbar-form navbar-left"
                    }))
                    {
                        <div class="form-group">
                            @Html.TextBox("Search", null, new
                            {
                                @class = "form-control",
                                @placeholder = "ค้นสินค้า"
                            })
                        </div>
                        <button type="submit" class="btn btn-default">ค้นหา</button>
                    }

                
                @Html.Partial("_LoginPartial")
            </div>
        </div>
    </div>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
        </footer>
    </div>

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", required: false)
</body>
</html>





หน้า Products/Index.cshtml




@model IEnumerable<SuaSilverShop_V2.Models.Product>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")

    @using (Html.BeginForm("Index", "Products", FormMethod.Get))
    {
        <label>Filter by category:</label> @Html.DropDownList("Category", "All")
        <input type="submit" value="Filter" />
    <input type="hidden" name="Search" id="Search" value="@ViewBag.Search" />
    }

</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Category.Name)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Name)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Description)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Price)
        </th>
        <th></th>




    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Category.Name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Description)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Price)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
            @Html.ActionLink("Details", "Details", new { id=item.ID }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.ID })
        </td>
    </tr>
}

</table>



ฟังก็ชัน Index ใน ProductsController

 public ActionResult Index(string category , string search)
        {
            var products = db.Products.Include(p => p.Category);

            if( !String.IsNullOrEmpty(category) )
            {
                products = products.Where( p => p.Category.Name == category) ;
            }

            if( !String.IsNullOrEmpty(search) )
            {
                products = products.Where(p => p.Name.Contains(search) ||
                                            p.Description.Contains(search) ||
                                            p.Category.Name.Contains(search));
                ViewBag.Search = search;

            }

            var categories = products.OrderBy(p => p.Category.Name).Select(p => p.Category.Name).Distinct();

            if (!String.IsNullOrEmpty(category))
            {
                products = products.Where(p => p.Category.Name == category);
            }


            ViewBag.Category = new SelectList(categories);

            return View(products.ToList());
        }





วันอังคารที่ 7 กุมภาพันธ์ พ.ศ. 2560

Asp.net MVC - CRUD Operation example



CategoriesController



using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using SuaSilverShop_V2.DAL;
using SuaSilverShop_V2.Models;

namespace SuaSilverShop_V2.Controllers
{
    public class CategoriesController : Controller
    {
        private StoreContext db = new StoreContext();

        // GET: Categories
        public ActionResult Index()
        {
            return View(db.Categories.ToList());
        }

        // GET: Categories/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Category category = db.Categories.Find(id);
            if (category == null)
            {
                return HttpNotFound();
            }
            return View(category);
        }

        // GET: Categories/Create
        public ActionResult Create()
        {
            return View();
        }

        // POST: Categories/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "ID,Name")] Category category)
        {
            if (ModelState.IsValid)
            {
                db.Categories.Add(category);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(category);
        }

        // GET: Categories/Edit/5
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Category category = db.Categories.Find(id);
            if (category == null)
            {
                return HttpNotFound();
            }
            return View(category);
        }

        // POST: Categories/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit([Bind(Include = "ID,Name")] Category category)
        {
            if (ModelState.IsValid)
            {
                db.Entry(category).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(category);
        }

        // GET: Categories/Delete/5
        public ActionResult Delete(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Category category = db.Categories.Find(id);
            if (category == null)
            {
                return HttpNotFound();
            }
            return View(category);
        }

        // POST: Categories/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int id)
        {
            Category category = db.Categories.Find(id);
            db.Categories.Remove(category);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                db.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}





Views/Categories/Create


@model SuaSilverShop_V2.Models.Category

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>


@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()
    
    <div class="form-horizontal">
        <h4>Category</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}






Views/Categories/Delete


@model SuaSilverShop_V2.Models.Category

@{
    ViewBag.Title = "Delete";
}

<h2>Delete</h2>

<h3>Are you sure you want to delete this?</h3>
<div>
    <h4>Category</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.Name)
        </dt>

        <dd>
            @Html.DisplayFor(model => model.Name)
        </dd>

    </dl>

    @using (Html.BeginForm()) {
        @Html.AntiForgeryToken()

        <div class="form-actions no-color">            <input type="submit" value="Delete" class="btn btn-default" /> |            @Html.ActionLink("Back to List", "Index")        </div>    }</div>





Views/Categories/Details

@model SuaSilverShop_V2.Models.Category

@{    ViewBag.Title = "Details";}
<h2>Details</h2>
<div>    <h4>Category</h4>    <hr />    <dl class="dl-horizontal">        <dt>            @Html.DisplayNameFor(model => model.Name)        </dt>
        <dd>            @Html.DisplayFor(model => model.Name)        </dd>
    </dl></div><p>    @Html.ActionLink("Edit", "Edit", new { id = Model.ID }) |    @Html.ActionLink("Back to List", "Index")</p>




Views/Categories/Edit

@model SuaSilverShop_V2.Models.Category

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>


@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    
    <div class="form-horizontal">
        <h4>Category</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @Html.HiddenFor(model => model.ID)

        <div class="form-group">
            @Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}





Views/Categories/Index

@model IEnumerable<SuaSilverShop_V2.Models.Category>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Name)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Name)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
            @Html.ActionLink("Details", "Details", new { id=item.ID }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.ID })
        </td>
    </tr>
}


</table>



Asp.net MVC - Connection string ในการเชื่อมต่อ database sql server




<connectionStrings>
    <add name="EFDbContext" connectionString="Data Source=DESKTOP-5D92H48\SQLEXPRESS2014; Initial Catalog=PrimOnlineShoppingSrore; Integrated Security=true" providerName="System.Data.SqlClient"/>
  </connectionStrings>




- EFDbContext คือ ชื่อ context class ที่เราสร้าง

- Data Source=DESKTOP-5D92H48\SQLEXPRESS2014 คือ ชื่อ server

- Initial Catalog=PrimOnlineShoppingSrore   คือ ชื่อ Database

วันศุกร์ที่ 3 กุมภาพันธ์ พ.ศ. 2560

7. Adding Navigation Controls (Menu)




1.  ไปที่ ProductListViewModel.htmlcs แล้วเพิ่ม


using PrimOnlineShoppingStore.Domain.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace PrimOnlineShoppingStore.WebUI.Models
{
    public class ProductsListViewModel
    {

        public IEnumerable<Product> Products { get; set;  }

        public PagingInfo pagingInfo { get; set; }

        public string CurrentCategory { get; set; }

    }
}


2. ไปที่ ProductController.cs   แล้วเพิ่ม

using PrimOnlineShoppingStore.Domain.Abstract;
using PrimOnlineShoppingStore.WebUI.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace PrimOnlineShoppingStore.WebUI.Controllers
{
    public class ProductController : Controller
    {

        public int pageSize = 4;

        private readonly IProductRepository repository;

        public ProductController(IProductRepository repo)
        {
            repository = repo;
        }


        public ViewResult List(string category , int page = 1)
        {

            ProductsListViewModel model = new ProductsListViewModel()
            {
                Products = repository.Products
                .Where( p=> category == null || p.Category == category)
                   .OrderBy(p => p.productID)
                   .Skip((page - 1) * pageSize)
                   .Take(pageSize),
                pagingInfo = new PagingInfo()
                {
                    CurrentPage = page,
                    ItemsPerPage = pageSize,
                    totalItems = repository.Products.Count()
                },
                CurrentCategory = category

            };

            return View(model);
         
        }

    }
}



3. เพื่ออยากให้ Url สวยๆ    ไปที่ RouteConfig.cs   แล้วเปลี่ยนเป็น

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace PrimOnlineShoppingStore.WebUI
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(null, "",
                       new
                       {
                           controller = "Product",
                           action = "List",
                           category = (string)null,
                           page = 1
                       });

            routes.MapRoute(null, "Page{page}",
                new
                {
                    controller = "Product",
                    action = "List",
                    category =
                        (string)null
                },
                new { page = @"\d+" });

            routes.MapRoute(
                null,
                "{category}",
                new { controller = "Product", action = "List" , page = 1 }
            );

            routes.MapRoute(
              null,
              "{category}/Page{page}",
              new { controller = "Product", action = "List" },
              new {page = @"\d+" }
          );

            routes.MapRoute(null, "{controller}/{action}");


        }
    }
}



4. ไปที่ List.cshtml   แล้วเพิ่ม


@model PrimOnlineShoppingStore.WebUI.Models.ProductsListViewModel
@using PrimOnlineShoppingStore.WebUI.HtmlHelpers;


@{
    ViewBag.Title = "Products";

 }

    @foreach (var p in Model.Products)
    {
        @Html.Partial("ProductSummary" , p);

    }



<div class="btn-group pull-right">
   @Html.PageLinks(Model.pagingInfo, x => Url.Action("List", new { page = x  , category = Model.CurrentCategory }) )

</div>


5. ไปที่ folder Controller แล้ว add class NavController

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace PrimOnlineShoppingStore.WebUI.Controllers
{
    public class NavController : Controller
    {
        // GET: Nav
        public string Menu()
        {
            return "return from Controller";
        }
    }
}


6. ไปที่ _Layout.cshtml   แล้วเพิ่ม

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - Prim Online Shopping Store</title>
    <link href="~/Content/bootstrap.min.css" rel="stylesheet" />
    <link href="~/Content/bootstrap-theme.min.css" rel="stylesheet" />
    <script src="~/Scripts/modernizr-2.6.2.js"></script>
</head>
<body>
    <div class="navbar navbar-inverse" role="navigation">
        <a class="navbar-brand" href="#">Prim Online Shopping Store</a>
    </div>

    <div class="row panel">
        <div id="categoris" class="col-lg-3">
            @Html.Action("Menu" , "Nav")
        </div>

        <div class="col-lg-7">
            @RenderBody()
        </div>

    </div>

</body>
</html>




7. แก้โค้ดที่ NavController เป็น


using PrimOnlineShoppingStore.Domain.Abstract;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace PrimOnlineShoppingStore.WebUI.Controllers
{
    public class NavController : Controller
    {

        private IProductRepository repository;

        public NavController(IProductRepository repo)
        {
            repository = repo;
        }



        // GET: Nav
       public PartialViewResult Menu(string category = null)
        {

            ViewBag.SelectedCategory = category;

            IEnumerable<string> categories = repository.Products
                .Select(x => x.Category)
                .Distinct()
                .OrderBy(x => x);
            return PartialView(categories);

        }
    }
}








8. ไปที่ folder Nav ที่อยู่ใน View folder แล้ว add View
     ตั้งชื่อ Menu ค่าต่างๆ  คงเดิม    แล้วเพิ่มโค้ด


@model IEnumerable<string>

@Html.ActionLink("Home", "List", "Product", null,
new { @class = "btn btn-block btn-default btn-lg" })



@foreach( var link in Model)
{

    @Html.RouteLink(link, new
    {
 
        controller = "Product",
        action = "List",
        category = link,
        page = 1
    },
       new {
        @class="btn btn-block btn-default btn-lg"
    + (link == ViewBag.SelectedCategory ? "btn-primary" : "")
    }
    )

}



9. ไปที่ ProductController.cs  แล้ว แก้โค้ด

using PrimOnlineShoppingStore.Domain.Abstract;
using PrimOnlineShoppingStore.WebUI.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace PrimOnlineShoppingStore.WebUI.Controllers
{
    public class ProductController : Controller
    {

        public int pageSize = 4;

        private readonly IProductRepository repository;

        public ProductController(IProductRepository repo)
        {
            repository = repo;
        }


        public ViewResult List(string category , int page = 1)
        {

            ProductsListViewModel model = new ProductsListViewModel()
            {
                Products = repository.Products
                .Where( p=> category == null || p.Category == category)
                   .OrderBy(p => p.productID)
                   .Skip((page - 1) * pageSize)
                   .Take(pageSize),
                pagingInfo = new PagingInfo()
                {
                    CurrentPage = page,
                    ItemsPerPage = pageSize,
                    totalItems = category == null ? repository.Products.Count() : 
                    repository.Products.Where( p => p.Category == category).Count()
                },
                CurrentCategory = category

            };

            return View(model);
           
        }

    }
}