ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第三章:搜索、高级过滤和视图模型

  在这一章中,我们首先添加一个搜索产品的模块以增强站点的功能,然后使用视图模型而不是ViewBag向视图传递复杂数据。

注意:如果你想按照本章的代码编写示例,你必须完成第二章或者直接从www.apress.com下载第二章的源代码。

3.1 添加产品搜索

  为了执行产品搜索,我们将添加一些功能使其能够按照产品名称、描述和分类进行搜索,从而让用户有一个更好的选择来查找相关结果。

  之所以将分类也包含在内,是因为如果用户输入的是“clothes”,而不是一件特定的衣服,那么所有的衣服都会被搜索到。如果我们不将分类作为搜索条件,用户可能不会搜索到任何结果,这是因为产品的名称或描述字段中可能没有包含“clothes”这个单词。

  我们将使用LINQ to Entities中的方法来搜索相关产品信息。

3.1.1 修改控制器以进行产品搜索

  修改Controllers\ProductsController.cs文件中的Index方法以添加产品搜索功能,代码如下所示:

 1 public ActionResult Index(string category, string search)
 2 {
 3     var products = db.Products.Include(p => p.Category);
 4
 5     if (!string.IsNullOrEmpty(category))
 6     {
 7         products = products.Where(p => p.Category.Name == category);
 8     }
 9
10     if (!string.IsNullOrEmpty(search))
11     {
12         products = products.Where(p => p.Name.Contains(search) || p.Description.Contains(search) || p.Category.Name.Contains(search));
13     }
14
15     return View(products.ToList());
16 }

  首先,在Index方法中添加了一个名为search的参数,然后,判断该参数是否为null或空,如果不为null或空,则我们使用下面的代码来进行产品的搜索:

1 if (!string.IsNullOrEmpty(search))
2 {
3     products = products.Where(p => p.Name.Contains(search) || p.Description.Contains(search) || p.Category.Name.Contains(search));
4 }

  按照直白的说法,上面的代码表示的含义是:如果产品的名称、产品的描述以及产品的分类名称中含有search,则这些产品都会被作为结果返回。这段代码也使用了lambda表达式,但是这个表达式更加复杂,并且使用了逻辑或(||)操作符。注意,在lambda操作符(=>)左边依然只有一个参数,虽然在其右边的代码中有多条语句。当这条语句提交到数据库时,Contains方法被转换为SQL的LIKE操作,并且它不是大小写敏感的。

3.1.2 测试产品搜索

  点击【开始调试(不执行)】菜单项启动应用程序以测试新的搜索功能,在首页中点击产品链接,打开产品索引(Index)页面,在URL后面手动添加?search=red,然后回车,我们将会看到如图3-1所示的结果。

图3-1:通过URL手动搜索含有“red”的产品

  为了测试按照分类名称搜索产品是否能够正确工作,我们修改URL为/Products?search=clothes。这个查询现在将匹配在产品名称或产品描述或分类名称中含有clothes这个单词的所有产品,结果如图3-2所示。

图3-2:通过修改URL搜索属于clothes分类的产品

3.1.3 在站点主导航栏中添加搜索框

  我们不应该期望用户能够手动输入URL以搜索产品,因此,我们有必要在站点中添加一个搜索框。我们将在站点的主导航栏中添加这个搜索框,以便用户可以一直看到它,并可以在任何页面中使用它。

  就像在第一章讲述的那样,主导航栏是站点布局页的一部分,因此它包含在Views\Shared\_Layout.cshtml文件中。

  首先,删除站点中的关于和联系方式连接。在这个例子中不会使用到它们,并且它们还占用空间。为了完成此工作,从Views\Shared\_Layout.cshtml文件中删除以下代码:

1 <li>@Html.ActionLink("关于", "About", "Home")</li>
2 <li>@Html.ActionLink("联系方式", "Contact", "Home")</li>

  为了添加一个搜索框,编辑Views\Shared\_Layout.cshtml文件中class属性为“navbar-collapse collapse”的div,将其代码修改为如下高亮显示的代码:

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 5     <meta charset="utf-8" />
 6     <meta name="viewport" content="width=device-width, initial-scale=1.0">
 7     <title>@ViewBag.Title - 我的 ASP.NET 应用程序</title>
 8     @Styles.Render("~/Content/css")
 9     @Scripts.Render("~/bundles/modernizr")
10
11 </head>
12 <body>
13     <div class="navbar navbar-inverse navbar-fixed-top">
14         <div class="container">
15             <div class="navbar-header">
16                 <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
17                     <span class="icon-bar"></span>
18                     <span class="icon-bar"></span>
19                     <span class="icon-bar"></span>
20                 </button>
21                 @Html.ActionLink("Baby Store", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
22             </div>
23             <div class="navbar-collapse collapse">
24                 <ul class="nav navbar-nav">
25                     <li>@Html.ActionLink("主页", "Index", "Home")</li>
26                     <li>@Html.ActionLink("分类", "Index", "Categories")</li>
27                     <li>@Html.ActionLink("产品", "Index", "Products")</li>
28                 </ul>
29                 @using (Html.BeginForm("Index", "Products", FormMethod.Get, new { @class = "navbar-form navbar-left" }))
30                 {
31                     <div class="form-group">
32                         @Html.TextBox("Search", null, new { @class = "form-control", @placeholder = "Search Products" })
33                     </div>
34                     <button type="submit" class="btn btn-default">Submit</button>
35                 }
36                 @Html.Partial("_LoginPartial")
37             </div>
38         </div>
39     </div>
40     <div class="container body-content">
41         @RenderBody()
42         <hr />
43         <footer>
44             <p>&copy; @DateTime.Now.Year - 我的 ASP.NET 应用程序</p>
45         </footer>
46     </div>
47
48     @Scripts.Render("~/bundles/jquery")
49     @Scripts.Render("~/bundles/bootstrap")
50     @RenderSection("scripts", required: false)
51 </body>
52 </html>

  表单使用GET而不是POST请求以便搜索条件可以在URL中看到。因此,用户可以复制它然后使用其他方式分享它,比如e-mail或社交媒体。按照惯例,GET请求用于查询数据库中的数据,而不是修改数据库中的数据。

  在这段代码中还涉及了前面我们没有使用过的HTML5的placeholder特性,它主要用于在页面首次加载时,在搜索框架中显示“Search Products”文本,以向用户提示该搜索框的用途。这主要通过在代码@Html.TextBox("Search", null, new { @class = "form-control", @placeholder = "Search Products"})中向htmlAttributes参数对象传递额外的条目完成的。文本框的name属性被指定为Search,MVC框架将其与搜索参数Search匹配。图3-3显示了导航栏的最终效果。

图3-3:完成搜索框之后的导航栏

  使用搜索框执行一些搜索,结果应该和手动在URL中输入搜索条件的效果一样。

3.1.4 如何使用Bootstrap添加样式

  Bootstrap是一个HTML、CSS和JavaScript的框架,起初由Twitter创建。使用基架的ASP.NET项目默认使用它来样式化站点的外观。在网上有一大堆关于Bootstrap的可用信息,因此,我们不会讨论关于它的任何细节,但是,当我们引入新的知识时,我们会解释为什么我们会那样样式化它。

  那么,我们如何知道搜索框的样式?答案在于Thomas Park创建的站点http://www.bootswatch.com。这个站点提供了几个免费的Bootstrap主题,还提供了许多元素的HTML预览。如果我们点击Themes按钮中的某个主题,然后往下拉动页面,并且将鼠标悬停在某个元素上,这个时候<>符号将会出现在该元素的右上角,如图3-4所示。如果点击这个符号,HTML预览就会出现,如图3-5所示。

图3-4:在bootswatch.com站点上出现在某个元素右上角的预览符号<>

图3-5:来自于bootswatch.com的HTML预览。高亮部分显示了如何样式化一个搜索框以及如何在导航中加入表单

3.2 使用ViewBag按照分类过滤搜索结果

  下面,我们添加一个新功能以便用户可以按照分类过滤搜索结果。在这个例子中,我们将在搜索结果页面中使用ViewBag来显示一个含有分类信息的下拉框。我们将这个下拉框与用户输入的搜索条件相关联,以便在下拉框中只显示与搜索结果相关的分类,同时不允许用户选择一个空的分类。

3.2.1 修改ProductsController控制器的Index方法以实现按照分类进行过滤

  按下面的代码修改Controllers\ProductsController.cs文件中的Index方法,以便在ViewBag中存储当前搜索的条件,并且生成一个去除重复值的分类列表,并将其作为SelectList对象存储在ViewBag中。

 1 public ActionResult Index(string category, string search)
 2 {
 3     var products = db.Products.Include(p => p.Category);
 4
 5     if (!string.IsNullOrEmpty(category))
 6     {
 7         products = products.Where(p => p.Category.Name == category);
 8     }
 9
10     if (!string.IsNullOrEmpty(search))
11     {
12         products = products.Where(p => p.Name.Contains(search) || p.Description.Contains(search) || p.Category.Name.Contains(search));
13         ViewBag.Search = search;
14     }
15
16     var categories = products.OrderBy(p => p.Category.Name).Select(p => p.Category.Name).Distinct();
17
18     ViewBag.Category = new SelectList(categories);
19
20     return View(products.ToList());
21 }

  将搜索条件保存在VeiwBag中,以便当用户点击分类过滤时可以重用该搜索条件。如果我们不保存该搜索条件,那么这个搜索条件将会被丢弃,产品信息将不会被正确地被过滤。

  代码var categories = products.OrderBy(p => p.Category.Name).Select(p => p.Category.Name).Distinct();生成了一个按字母排序并且去除重复值的分类列表。这个分类列表是不全面的,它只包含与搜索条件相关的产品所包含的分类信息。

  最后,我们根据categories变量生成了一个SelectList对象,并将其保存在ViewBag中,以便在视图中使用。

3.2.2 向产品的索引(Index)页面添加过滤功能

  为了使\Products\Index.cshtml文件生成的HTML页面具有按分类过滤的功能,我们需要添加一个新的HTML表单以提交过滤请求。我们在Views\Products\Index.cshtml文件的Create New链接后面添加一个带有下列列表的新表单,代码如下所示:

1 <p>
2     @Html.ActionLink("Create New", "Create")
3     @using(Html.BeginForm("Index", "Products", FormMethod.Get))
4     {
5         <label>Filter by category:</label> @Html.DropDownList("Category", "All")
6         <input type="submit" value="Filter"/>
7         <input type="hidden" name="Search" id="Search" value="@ViewBag.Search"/>
8     }
9 </p>

  这段代码添加了一个表单,该表单使用GET方法向ProductsController控制器的Index动作方法提交请求,因此,查询字符串所包含的值一并被提交到服务端。使用代码@Html.DropDownList("Category", "All")生成一个下拉列表,该下拉列表使用了ViewBag.Category属性所提供的值,参数“All”对下拉列表指定了一个默认值。添加的提交按钮Filter可以让用户提交表单并执行过滤。一个隐藏的HTML元素被用来存储当前的搜索条件,当按分类过滤产品信息并提交表单时,可以保证用户最初输入的搜索条件被保存下来。

  不调试启动站点,图3-6显示了搜索“Red”单词后的产品的索引(Index)页面的样子,注意All是过滤下拉框的默认值。

图3-6:带有过滤功能的产品索引(Index)页面

  看起来代码都像预期的一样被正确执行,然而,代码存在一个小问题。图3-7显示了搜索“Red”之后,又按照Clothes分类过滤之后的效果。

图3-7:搜索“Red”后按照Clothes过滤后的页面

  这个问题是在在按照Clothes分类过滤后,在分类列表中的Toys分类消息了。修正这个问题很简单,但是它强调了需要按正确的顺序来创建我们的查询。为了修正这个问题,向如下所示的代码一样修改\Controllers\ProductsController.cs文件中的Index方法,以使按照分类过滤产品的代码放在categories变量已被赋值的后面:

 1 public ActionResult Index(string category, string search)
 2 {
 3     var products = db.Products.Include(p => p.Category);
 4
 5     if (!string.IsNullOrEmpty(search))
 6     {
 7         products = products.Where(p => p.Name.Contains(search) || p.Description.Contains(search) || p.Category.Name.Contains(search));
 8         ViewBag.Search = search;
 9     }
10
11     var categories = products.OrderBy(p => p.Category.Name).Select(p => p.Category.Name).Distinct();
12
13     if (!string.IsNullOrEmpty(category))
14     {
15         products = products.Where(p => p.Category.Name == category);
16     }
17
18     ViewBag.Category = new SelectList(categories);
19
20     return View(products.ToList());
21 }

  不调试启动站点,如果我们现在执行一个搜索,然后按照分类进行过滤,我们会发现在分类下拉列表中的Toys分类依然存在,如图3-8所示。

图3-8:搜索“Red”,然后按Clothes分类过滤之后,Toys分类依然可以让用户进行选择

3.3 使用视图模型实现更加复杂的过滤

  一旦我们使用ViewBag将多个数据由控制器传递给视图时,我们的代码会变得难以维护,这主要归咎于ViewBag的动态特性,Visual Studio没有对ViewBag可用的属性提供智能提示功能,这很容易造成ViewBag属性的拼写错误。

  由控制器向视图传递信息更好的一种方法是使用视图模型,而不是ViewBag。然后视图基于这种模型,而不是基于域模型(到目前为止,我们的视图都是基于域模型的)。一些开发人员将这种概念进一步细分,将他们所有的视图都仅仅基于视图模型。在本书中,我们混用视图模型和域模型。

  在这个例子中,我们将学习对于每一个分类,如何实现在下拉列表中同时显示该分类所对的产品数量。为了实现这个功能,我们需要一个视图模型保存我们传递给视图的所有信息。

3.3.1 创建视图模型

  在BabyStore项目下创建一个名为“ViewModels”的新文件夹,然后在其添加一个名为ProductIndexViewModel的类,然后在该类中编写如下代码:

 1 using System.Collections.Generic;
 2 using System.Linq;
 3 using System.Web.Mvc;
 4 using BabyStore.Models;
 5
 6 namespace BabyStore.ViewModels
 7 {
 8     public class CategoryWithCount
 9     {
10         public int ProductCount { get; set; }
11         public string CategoryName { get; set; }
12         public string CatNameWithCount
13         {
14             get
15             {
16                 return CategoryName + " (" + ProductCount.ToString() + ")";
17             }
18         }
19     }
20
21     public class ProductIndexViewModel
22     {
23         public IQueryable<Product> Products { get; set; }
24         public string Search { get; set; }
25         public IEnumerable<CategoryWithCount> CatsWithCount { get; set; }
26         public string Category { get; set; }
27
28         public IEnumerable<SelectListItem> CatFilterItems
29         {
30             get
31             {
32                 var allCats = CatsWithCount.Select(cc => new SelectListItem
33                 {
34                     Value = cc.CategoryName,
35                     Text = cc.CatNameWithCount
36                 });
37
38                 return allCats;
39             }
40         }
41     }
42 }

  这个类文件看起来比我们之前使用的代码都要复杂,因此,我们将一步一步地解释每个属性的用途。

  首先,这个文件包含两个类,分别为CategoryWithCount和ProductIndexViewModel。

  CategoryWithCount类比较简单,主要用于保存分类的名字和该分类所包含该的产品数量。

  第一个属性ProductCount用于保存该分类中所包含的产品数量。

  第二个属性CategoryName用于保存分类的名称。

  第三个属性CatNameWithCount返回ProductCount和CategoryName合并之后的格式化字符串,例如:Clothes (2)。

  ProductIndexViewModel类需要保存先前使用ViewBag传递给视图的信息组合以及模型IEnumerable<BabyStore.Models.Product>(该模型出现在/Views/Products/Index.cshtml文件的顶部)。

  在这个类中的第一个属性public IQueryable<Product> Products { get; set; },将会用于替换在当前视图中使用的模型。

  第二个属性是public string Search { get; set; },将会用于替换在当前ProductsController类中使用的ViewBag.Search。

  第三个属性是public IEnumerable<CategoryWithCount> CatsWithCount { get; set; },将会用于存储CategoryWithCount类型的集合,该集合用于视图中的下拉列表中。

  第四个属性Category将会用作视图中的下拉列表的名称。

  最后一个属性public IEnumerable<SelectListItem> CatFilterItems用于返回一个SelectListItem类型的列表,该属性将会利用第三个属性CatsWithCount生成SelectListItem对象,该对象的Value对应CategoryWithCount的CategoryName,Text对应CategoryWithCount的CatNameWithCount;Value用于视图中下拉列表的值,Text用于视图中下拉列表的显示文本。

3.3.2 修改ProductsController控制器的Index方法以使用视图模型

  更新\Controllers\ProductsController.cs文件的Index方法以便它匹配下列代码。改动的代码使用粗体高亮显示:使用视图模型而不是ViewBag返回项目的计数。首先,在该文件的上方添加一个using语句,以使该类可以访问我们刚刚创建的ProductIndexViewModel类。

 1 using BabyStore.ViewModels;
 2
 3 public ActionResult Index(string category, string search)
 4 {
 5     // instantiate a new view model
 6     ProductIndexViewModel viewModel = new ProductIndexViewModel();
 7
 8     var products = db.Products.Include(p => p.Category);
 9
10     if (!string.IsNullOrEmpty(search))
11     {
12         products = products.Where(p => p.Name.Contains(search) || p.Description.Contains(search) || p.Category.Name.Contains(search));
13         viewModel.Search = search;
14     }
15
16     // group search results into categories and count how many item in each category
17     viewModel.CatsWithCount = from matchinngProducts in products
18                               where matchinngProducts.CategoryID != null
19                               group matchinngProducts by matchinngProducts.Category.Name into catGroup
20                               select new CategoryWithCount()
21                               {
22                                   CategoryName = catGroup.Key,
23                                   ProductCount = catGroup.Count()
24                               };
25
26     if (!string.IsNullOrEmpty(category))
27     {
28         products = products.Where(p => p.Category.Name == category);
29     }
30
31     viewModel.Products = products;
32
33     return View(viewModel);
34 }

  在这个方法内的第一处改动的代码是创建一个视图模型:ProductIndexViewModel viewModel = new ProductIndexViewModel();

  代码viewModel.Search = search;将变量search赋值给viewModel而不是ViewBag。

  第三处代码改动是LINQ语句,该语句将一个CategoryWithCount对象的列表赋值给viewModel的CatsWithCount属性。在这个例子中,因为这个查询比较复杂,我们使用了另外一种形式的LINQ,该形成称之为查询语法(query syntax),该语法使得查询语句更容易阅读。

  该语句的下列代码,首先使用where子句过滤掉分类ID为null的产品,然后按照分类名称进行分组。

from matchinngProducts in products
where matchinngProducts.CategoryID != null
group matchinngProducts by matchinngProducts.Category.Name into catGroup

  对于每一个分组,分类的名称和该分类所对应的产品数量被赋值给一个CategoryWithCount对象。

select new CategoryWithCount()
{
  CategoryName = catGroup.Key,
  ProductCount = catGroup.Count()
};

  最后一处改动的代码将products变量赋值给viewModel的Products属性,而不是将它传递给视图。紧接着,我们将viewModel传递给视图,代码如下:

viewModel.Products = products;

return View(viewModel);

  注意,不属于任何分类的的产品将不会显示在分类的下拉列表中,但是依然能够被搜索到。

3.3.3 修改视图以便使用视图模型完成新过滤功能

  更新\Views\Products\Index.cshtml文件,以便使用视图模型生成过滤下拉列表、检索搜索字符串、显示表格标题以及显示产品列表。进行一下更改:

 1 @model BabyStore.ViewModels.ProductIndexViewModel
 2
 3 @{
 4     ViewBag.Title = "Index";
 5 }
 6
 7 <h2>Index</h2>
 8
 9 <p>
10     @Html.ActionLink("Create New", "Create")
11     @using(Html.BeginForm("Index", "Products", FormMethod.Get))
12     {
13         <label>Filter by category:</label>@Html.DropDownListFor(vm => vm.Category, Model.CatFilterItems, "All");
14         <input type="submit" value="Filter"/>
15         <input type="hidden" name="Search" id="Search" value="@Model.Search"/>
16     }
17 </p>
18 <table class="table">
19     <tr>
20         <th>
21             @Html.DisplayNameFor(model => model.Category)
22         </th>
23         <th>
24             @Html.DisplayNameFor(model => model.Products.First().Name)
25         </th>
26         <th>
27             @Html.DisplayNameFor(model => model.Products.First().Description)
28         </th>
29         <th>
30             @Html.DisplayNameFor(model => model.Products.First().Price)
31         </th>
32         <th></th>
33     </tr>
34
35 @foreach (var item in Model.Products) {
36     <tr>
37         <td>
38             @Html.DisplayFor(modelItem => item.Category.Name)
39         </td>
40         <td>
41             @Html.DisplayFor(modelItem => item.Name)
42         </td>
43         <td>
44             @Html.DisplayFor(modelItem => item.Description)
45         </td>
46         <td>
47             @Html.DisplayFor(modelItem => item.Price)
48         </td>
49         <td>
50             @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
51             @Html.ActionLink("Details", "Details", new { id=item.ID }) |
52             @Html.ActionLink("Delete", "Delete", new { id=item.ID })
53         </td>
54     </tr>
55 }
56
57 </table>

  对此文件所做的代码修改十分简单,但意义重大。第一处改动@model BabyStore.ViewModels.ProductIndexViewModel只是简单地告诉视图使用ProductIndexViewModel作为该视图基于的模型。注意该模型现在是一个单一的类,而不是一个可枚举的集合。

  第二处改动@Html.DropDownListFor(vm => vm.Category, Model.CatFilterItems, "All");基于视图模型的CatFilterItems属性生成一个下拉列表,第二个参数用于生成下拉列表中的显示数据以及值。第一个参数vm => vm.Category指定该下拉列表的名称,当提交该表单时,该下拉列表的名称将出现在URL的查询字符串部分。因为该控件的名称是Category,因此,我们先前在URL中查找Category参数的代码将会继续正确地工作。

  第三次改动保确保隐藏域现在引用的是视图模型而不是ViewBag:

<input type="hidden" name="Search" id="Search" value="@Model.Search" />

  当我们需要生成表格标题时,不像看起来那么简单,因为HTML辅助器的DisplayNameFor方法不适用于集合,因此,我们基于视图模型的Products属性来显示标题。分类标题十分简单,因为这是视图模型的一个属性。但是,显示Product类的Description属性的名字不能使用类似这样的代码@Html.DisplayNameFor(model => model.Products.Description),而是要求我们使用First()方法,强制辅助器使用自于products集合中的,一个实际的Product实体,代码如下:

@Html.DisplayNameFor(model => model.Products.First().Description)

  这段代码将会生成一个基于Product类的Description属性的表格标题。如果在数据库中的Products表中没有数据,该代码也会正确工作。

  提示:当HTML辅助器的DisplayNameFor方法用于集合而不是单一对象时,使用First()方法以便访问我们要想显示的属性的名称。

  最后一处改动是@foreach (var item in Model.Products) {,确保我们现在使用视图模型的Products属性来显示产品信息。

  不调试启动站点,然后点击产品链接,我们会发现在分类下拉列表中的每个分类都带有一个数量,这反映出每个分类所包含的产品的数量。图3-9显示了我们在搜索框中输入“Red”后,下拉列表所显示的条目。

图3-9:在下拉列表中的每一个分类都包含所匹配的产品数量

3.4 小节

  在这一章中,我们学习了如何添加搜索功能,包括如何使用Bootstrap添加一个搜索框,然后学习了怎样发现更多关于使用Boootstrap如何样式化的站点的信息。我们还演示了如何使用ViewBag添加一个对于搜索结果的过滤,以及如何使用视图模型添加一个更加复杂的过滤。

时间: 2024-08-07 04:31:02

ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第三章:搜索、高级过滤和视图模型的相关文章

ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第六章:管理产品图片:多对多关系(上)

这章介绍了怎样创建一个新的实体来管理图片,怎样使用HTML窗体来上传图片文件和使用多对多关系来使它们与产品相关,并且怎样来保存图片到文件系统中.这章也介绍了更多复杂的错误处理增加客户端错误到模型中为了把它们显示回给用户.在这章中播种数据库使用的产品图片可能在在第六章的从Apress网页站点下载代码中. 注意:如果你想遵从这章的代码,你必须完成第五章的代码或者从www.apress.com下载第五章的源代码作为一个起点. 创建实体保存图片文件名 这个项目,我们正要使用文件系统在Web项目中存储图片

ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之目录导航

ASP.NET MVC with Entity Framework and CSS是2016年出版的一本比较新的.关于ASP.NET MVC.EF以及CSS技术的图书,我将尝试着翻译本书以供日后查阅.但是,由于本人英语水平有限,难免有翻译不准确或错误的地方,请大家踊跃提出宝贵的意见,以进行修正.本书一共18章,下面列出各章的英文目录: Chapter 1: Building a Basic MVC Web Site Chapter 2: Creating Views, Controllers,

ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第一章:创建基本的MVC Web站点

在这一章中,我们将学习如何使用基架快速搭建和运行一个简单的Microsoft ASP.NET MVC Web站点.在我们马上投入学习和编码之前,我们首先了解一些有关ASP.NET MVC和Entity Framework的背景信息,然后再详细学习如何搭建开发环境. 1.1 MVC和ASP.NET MVC 这本书涵盖Microsoft版本的MVC,即ASP.NET MVC.在写本书的时候,ASP.NET MVC的生产版本为MVC5,因此,本书的示例代码都使用ASP.NET MVC 5编写.在本书中

ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第二章:利用模型类创建视图、控制器和数据库

在这一章中,我们将直接进入项目,并且为产品和分类添加一些基本的模型类.我们将在Entity Framework的代码优先模式下,利用这些模型类创建一个数据库.我们还将学习如何在代码中创建数据库上下文类.指定数据库连接字符串以及创建一个数据库.最后,我们还将添加视图和控制器来管理和显式产品和分类数据. 注意:如果你想按照本章的代码编写示例,你必须完成第一章或者直接从www.apress.com下载第一章的源代码. 2.1 添加模型类 Entity Framework的代码优先模式允许我们从模型类创

ASP.NET MVC+EasyUI+Entity FrameWork 整合开发

本文详细讲解怎么用ASP.NET MVC+EasyUI+Entity FrameWork 来开发一个项目 对于ASP.NET MVC的Jscript库,主要引用 <script type="text/javascript" src="@Url.Content("~/Scripts/jquery-1.7.2.min.js")"></script> <script src="@Url.Content("

《Entity Framework 6 Recipes》中文翻译系列 目录篇 -持续更新

为了方便大家的阅读和学习,也是响应网友的建议,在这里为这个系列做一个目录.在目录开始这前,我先来回答之前遇到的几个问题. 1.为什么要学习EF? 这个问题很简单,项目需要.这不像学校,没人强迫你学习! 我学习EF的原因主要是: a.EF是微软推荐的数据库访问技术: b.能提高我的开发效率,我不喜欢写那密密麻麻的SQL: c.比我写的SQL更合理,更快.目前EF生成的SQL的质量已经很高了.你比较熟悉SQL的话,那它在速度上肯定比不上你,新手的话就别跟我争快慢了,能写一像样的SQL就不错了.至少我

《Entity Framework 6 Recipes》中文翻译系列 (20) -----第四章 ASP.NET MVC中使用实体框架之在MVC中构建一个CRUD示例

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第四章  ASP.NET MVC中使用实体框架 ASP.NET是一个免费的Web框架,它支持3种不同的技术来创建websites(网站)和Web应用:他们分别是,Web Pages,Web Forms,和MVC.虽然MVC是一种非常流行的,有完整的用于软件开发模式理论的技术,但它在ASP.NET中却是一种新的技术. 目前最新的版本是2012年发布的ASP.NET MVC4.自从2008年发布

Asp.Net MVC 使用Entity Framework创建模型类

先来说说LINQ to SQL和Entity Framework的区别: LINQ to SQL和Entity Framework都是一种包含LINQ功能的对象关系映射技术.他们之间的本质区别在于EF对数据库架构和我们查询的类型实行了更好的解耦.使用EF,我们查询的对象不再是完全对应数据库架构的C#类,而是更高层的抽象:Entity Data Model.这为我们提供了额外的灵活性,但是在性能和简单性上面也会有所损失. LINQ to SQL和Entity Framework各有所长,LINQ

《Entity Framework 6 Recipes》中文翻译系列 (45) ------ 第八章 POCO之获取原始对象与手工同步对象图和变化跟踪器

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 8-6  获取原始对象 问题 你正在使用POCO,想从数据库获取原始对象. 解决方案 假设你有如图8-7所示的模型.你正在离线环境下工作,你想应用在获取客户端修改之前,使用Where从句和FirstDefault()方法从数据库中获取原始对象. 图8-7.包含一个单独实体Item的模型 按代码清单8-9的方式,在获取实体之后,使用新值更新实体并将其保存到数据库中. 代码清单8-9. 获取最新