【ASP.NET Web API教程】2.3.7 创建首页

简介: 原文:【ASP.NET Web API教程】2.3.7 创建首页注:本文是【ASP.NET Web API系列教程】的一部分,如果您是第一次看本博客文章,请先看前面的内容。 Part 7: Creating the Main Page 第7部分:创建首页 本文引自:http://www.
原文: 【ASP.NET Web API教程】2.3.7 创建首页

注:本文是【ASP.NET Web API系列教程】的一部分,如果您是第一次看本博客文章,请先看前面的内容。

Part 7: Creating the Main Page
第7部分:创建首页

本文引自:http://www.asp.net/web-api/overview/creating-web-apis/using-web-api-with-entity-framework/using-web-api-with-entity-framework,-part-7

Creating the Main Page
创建首页

In this section, you will create the main application page. This page will be more complex than the Admin page, so we’ll approach it in several steps. Along the way, you'll see some more advanced Knockout.js techniques. Here is the basic layout of the page:
在这一小节中将创建主应用程序的首页。这个页面要比Admin页面更复杂些。因此,我们将采用几个步骤。在此过程中,你将看到一些更高级的Knockout.js技术。以下是此页面的基本布局(见图2-26):

WebAPI2-26

图2-26. 首页布局

  • "Products" holds an array of products.
    “产品”放置产品数组。
  • "Cart" holds an array of products with quantities. Clicking “Add to Cart” updates the cart.
    “购物车”放置带有订购数的产品数组。点击“加入购物车”会对购物车进行更新。
  • "Orders" holds an array of order IDs.
    “订单”放置订单的ID数组(订单号数组)。
  • "Details" holds an order detail, which is an array of items (products with quantities)
    “细节”放置一份订单细节,这是一个条目数组(带有订购数的产品)。

We’ll start by defining some basic layout in HTML, with no data binding or script. Open the file Views/Home/Index.cshtml and replace all of the contents with the following:
我们将以无数据的绑定或脚本首先定义一些HTML的基本布局。打开Views/Home/Index.cshtml文件,并将全部内容替换如下:

<div class="content"> 
    <!-- List of products(产品列表) --> 
    <div class="float-left"> 
    <h1>Products</h1> 
    <ul id="products"> 
    </ul> 
    </div> 
    <!—Cart(购物车) --> 
    <div id="cart" class="float-right"> 
    <h1>Your Cart</h1> 
        <table class="details ui-widget-content"> 
    </table> 
    <input type="button" value="Create Order"/> 
    </div> 
</div> 
<div id="orders-area" class="content" > 
    <!-- List of orders --> 
    <div class="float-left"> 
    <h1>Your Orders</h1> 
    <ul id="orders"> 
    </ul> 
    </div> 
   <!-- Order Details(订单细节) --> 
    <div id="order-details" class="float-right"> 
    <h2>Order #<span></span></h2> 
    <table class="details ui-widget-content"> 
    </table> 
    <p>Total: <span></span></p> 
    </div> 
</div>

Next, add a Scripts section and create an empty view-model:
下一步,添加一个脚本片段,并创建一个空的视图模型:

@section Scripts { 
  <script type="text/javascript" src="@Url.Content("~/Scripts/knockout-2.1.0.js")"></script> 
  <script type="text/javascript"> 
    function AppViewModel() { 
        var self = this; 
        self.loggedIn = @(Request.IsAuthenticated ? "true" : "false"); 
    } 
    $(document).ready(function () { 
        ko.applyBindings(new AppViewModel()); 
    }); 
  </script> 
}

Based on the design sketched earlier, our view model needs observables for products, cart, orders, and details. Add the following variables to the AppViewModel object:
基于前面的设计框架,我们的视图需要产品、购物车、订单以及订单细节的可见对象(observables)。将以下变量添加到AppViewModel对象:

self.products = ko.observableArray(); 
self.cart = ko.observableArray(); 
self.orders = ko.observableArray(); 
self.details = ko.observable();

Users can add items from the products list into the cart, and remove items from the cart. To encapsulate these functions, we'll create another view-model class that represents a product. Add the following code to AppViewModel:
用户可以把产品列表中的条目添加到购物车中,以及从购物车删除条目。为了封装这些函数,我们将创建另一个表示产品的视图模型类。将以下代码添加到AppViewModel

function AppViewModel() { 
    // ... 
    // NEW CODE 
    // 新代码
    function ProductViewModel(root, product) { 
        var self = this; 
        self.ProductId = product.Id; 
        self.Name = product.Name; 
        self.Price = product.Price; 
        self.Quantity = ko.observable(0); 
        self.addItemToCart = function () { 
            var qty = self.Quantity(); 
            if (qty == 0) { 
                root.cart.push(self); 
            } 
            self.Quantity(qty + 1); 
        }; 
        self.removeAllFromCart = function () { 
            self.Quantity(0); 
            root.cart.remove(self); 
        }; 
    } 
}

The ProductViewModel class contains two functions that are used to move the product to and from the cart: addItemToCart adds one unit of the product to the cart, and removeAllFromCart removes all quantities of the product.
这个ProductViewModel类包含两个函数,用于对购物车添加或删除产品:addItemToCart将一个产品单位添加到购物车(即,产品订购数加1 — 译者注),而removeAllFromCart删除产品的全部订购数。

Users can select an existing order and get the order details. We'll encapsulate this functionality into another view-model:
用户可以选择一个已有订单,并获取该订单细节。我们将把这个功能封装到另一个视图模型之中:

function AppViewModel() { 
    // ... 
    // NEW CODE 
    // 新代码
    function OrderDetailsViewModel(order) { 
        var self = this; 
        self.items = ko.observableArray(); 
        self.Id = order.Id; 
        self.total = ko.computed(function () { 
            var sum = 0; 
            $.each(self.items(), function (index, item) { 
                sum += item.Price * item.Quantity; 
            }); 
            return '$' + sum.toFixed(2); 
        }); 
        $.getJSON("/api/orders/" + order.Id, function (order) { 
            $.each(order.Details, function (index, item) { 
                self.items.push(item); 
            }) 
        }); 
    }; 
}

The OrderDetailsViewModel is initialized with an order, and it fetches the order details by sending an AJAX request to the server.
OrderDetailsViewModel用一个订单进行初始化,并能通过向服务器发送一个AJAX请求来捕捉该订单的细节。

Also, notice the total property on the OrderDetailsViewModel. This property is a special kind of observable called a computed observable. As the name implies, a computed observable lets you data bind to a computed value—in this case, the total cost of the order.
另外,要注意到OrderDetailsViewModel上的total属性。这个属性是一个叫做“已计算可见对象”的特殊类型的可见对象。正如其名称所暗示的那样,一个已计算可见对象可以让你把数据绑定到一个已计算的值 — 在此例中是订单的总费用(total cost)。

Next, add these functions to AppViewModel:
接下来,把这些函数添加到AppViewModel

  • resetCart removes all items from the cart.
    resetCart删除购物车的所有条目。
  • getDetails gets the details for an order (by pusing pushing a new OrderDetailsViewModel onto the details list).
    getDetails获取一份订单的细节(通过把一个新的OrderDetailsViewModel推入details列表)。
  • createOrder creates a new order and empties the cart.
    createOrder创建一个新的订单,并清空购物车。
function AppViewModel() { 
    // ... 
    // NEW CODE
    // 新代码
    self.resetCart = function() { 
        var items = self.cart.removeAll(); 
        $.each(items, function (index, product) { 
            product.Quantity(0); 
        }); 
    } 
    self.getDetails = function (order) { 
        self.details(new OrderDetailsViewModel(order)); 
    } 
    self.createOrder = function () { 
        var jqxhr = $.ajax({ 
            type: 'POST', 
            url: "api/orders", 
            contentType: 'application/json; charset=utf-8', 
            data: ko.toJSON({ Details: self.cart }), 
            dataType: "json", 
            success: function (newOrder) { 
                self.resetCart(); 
                self.orders.push(newOrder); 
            }, 
            error: function (jqXHR, textStatus, errorThrown) { 
                self.errorMessage(errorThrown); 
            }   
        }); 
    }; 
};

Finally, initialize the view model by making AJAX requests for the products and orders:
最后,通过发送对产品和订单的AJAX请求的办法,对这个视图模型进行初始化:

function AppViewModel() { 
    // ... 
    // NEW CODE 
    // 新代码
    // Initialize the view-model. 
    $.getJSON("/api/products", function (products) { 
        $.each(products, function (index, product) { 
            self.products.push(new ProductViewModel(self, product)); 
        }) 
    }); 
    $.getJSON("api/orders", self.orders); 
};

OK, that's a lot of code, but we built it up step-by-step, so hopefully the design is clear. Now we can add some Knockout.js bindings to the HTML.
好了,代码很多,但我们一步步把它建立起来了,希望这一设计是清晰的。现在,我们可以对这个HTML添加一些Knockout.js绑定。

Products
产品

Here are the bindings for the product list:
以下是对产品列表的绑定:

<ul id="products" data-bind="foreach: products"> 
    <li> 
        <div> 
            <span data-bind="text: Name"></span>  
            <span class="price" data-bind="text: '$' + Price"></span> 
        </div> 
        <div data-bind="if: $parent.loggedIn"> 
            <button data-bind="click: addItemToCart">Add to Order</button> 
        </div> 
    </li> 
</ul>

This iterates over the products array and displays the name and price. The "Add to Order" button is visible only when the user is logged in.
它对产品数组进行了循环,并显示名称和价格。“加入购物车”按钮只在用户登录时才是可见的。

The "Add to Order" button calls addItemToCart on the ProductViewModel instance for the product. This demonstrates a nice feature of Knockout.js: When a view-model contains other view-models, you can apply the bindings to the inner model. In this example, the bindings within the foreach are applied to each of the ProductViewModel instances. This approach is much cleaner than putting all of the functionality into a single view-model.
“加入购物车”按钮针对(所选)产品调用ProductViewModel实例上的addItemToCart。这演示了Knockout.js的一个很好的特性:当一个视图模型含有其它视图模型时,你可以把绑定运用于内部模型。在这个例子中,在foreach中的绑定被运用于每个ProductViewModel实例。这种办法要比把所有功能放在一个单一的视图模型中要清晰得多。

Cart
购物车

Here are the bindings for the cart:
以下是对购物车的绑定:

<div id="cart" class="float-right" data-bind="visible: cart().length > 0"> 
<h1>Your Cart</h1> 
    <table class="details ui-widget-content"> 
    <thead> 
        <tr><td>Item</td><td>Price</td><td>Quantity</td><td></td></tr> 
    </thead>     
    <tbody data-bind="foreach: cart"> 
        <tr> 
            <td><span data-bind="text: $data.Name"></span></td> 
            <td>$<span data-bind="text: $data.Price"></span></td> 
            <td class="qty"><span data-bind="text: $data.Quantity()"></span></td> 
            <td><a href="#" data-bind="click: removeAllFromCart">Remove</a></td> 
        </tr> 
    </tbody> 
</table> 
<input type="button" data-bind="click: createOrder" value="Create Order"/>

This iterates over the cart array and displays the name, price, and quantity. Note that the "Remove" link and the "Create Order" button are bound to view-model functions.
这是对购物车的循环,并且显示名称、价格和数据。注意,“删除”链接和“创建订单”按钮都被绑定到视图模型的函数上。

Orders
订单

Here are the bindings for the orders list:
以下是对订单列表的绑定:

<h1>Your Orders</h1> 
<ul id="orders" data-bind="foreach: orders"> 
<li class="ui-widget-content"> 
    <a href="#" data-bind="click: $root.getDetails"> 
        Order # <span data-bind="text: $data.Id"></span></a> 
</li> 
</ul>

This iterates over the orders and shows the order ID. The click event on the link is bound to the getDetails function.
它对订单进行了循环,并显示订单ID。链接上的点击事件被绑定到getDetails函数。

Order Details
订单细节

Here are the bindings for the order details:
以下是对订单细节的绑定:

<div id="order-details" class="float-right" data-bind="if: details()"> 
<h2>Order #<span data-bind="text: details().Id"></span></h2> 
<table class="details ui-widget-content"> 
    <thead> 
        <tr><td>Item</td><td>Price</td><td>Quantity</td><td>Subtotal</td></tr> 
    </thead>     
    <tbody data-bind="foreach: details().items"> 
        <tr> 
            <td><span data-bind="text: $data.Product"></span></td> 
            <td><span data-bind="text: $data.Price"></span></td> 
            <td><span data-bind="text: $data.Quantity"></span></td> 
            <td> 
                <span data-bind="text: ($data.Price * $data.Quantity).toFixed(2)"></span> 
            </td> 
        </tr> 
    </tbody> 
</table> 
<p>Total: <span data-bind="text: details().total"></span></p> 
</div>

This iterates over the items in the order and displays the product, price, and quanity quantity. The surrounding div is visible only if the details array contains one or more items.
它对订单中的条目进行循环,并显示产品、价格和数量。div所包围的部分只在订单细节数组含有一个或多个条目时才会显示。

Conclusion
结论

In this tutorial, you created an application that uses Entity Framework to communicate with the database, and ASP.NET Web API to provide a public-facing interface on top of the data layer. We use ASP.NET MVC 4 to render the HTML pages, and Knockout.js plus jQuery to provide dynamic interactions without page reloads.
在这个教程中,你创建了一个应用程序,它用实体框架与数据库进行通信,并用ASP.NET Web API提供了一个建立在数据层之上的面向公众的接口。我们使用了ASP.NET MVC 4来渲染HTML页面,并用Knckout.js加jQuery来提供不必进行页面重载的动态交互。

Additional resources:
其它资源:

看完此文如果觉得有所收获,恳请给个推荐

目录
相关文章
|
1月前
|
开发框架 数据可视化 .NET
.NET 中管理 Web API 文档的两种方式
.NET 中管理 Web API 文档的两种方式
48 14
|
3月前
|
开发框架 .NET 程序员
驾驭Autofac,ASP.NET WebApi实现依赖注入详细步骤总结
Autofac 是一个轻量级的依赖注入框架,专门为 .NET 应用程序量身定做,它就像是你代码中的 "魔法师",用它来管理对象的生命周期,让你的代码更加模块化、易于测试和维护
122 4
驾驭Autofac,ASP.NET WebApi实现依赖注入详细步骤总结
|
5月前
|
开发框架 监控 前端开发
在 ASP.NET Core Web API 中使用操作筛选器统一处理通用操作
【9月更文挑战第27天】操作筛选器是ASP.NET Core MVC和Web API中的一种过滤器,可在操作方法执行前后运行代码,适用于日志记录、性能监控和验证等场景。通过实现`IActionFilter`接口的`OnActionExecuting`和`OnActionExecuted`方法,可以统一处理日志、验证及异常。创建并注册自定义筛选器类,能提升代码的可维护性和复用性。
|
6月前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
87 0
|
6月前
|
存储 开发框架 .NET
ASP.NET Web Api 使用 EF 6,DateTime 字段如何取数据库服务器当前时间
ASP.NET Web Api 使用 EF 6,DateTime 字段如何取数据库服务器当前时间
|
6月前
|
开发框架 .NET API
如何在 ASP.NET Core Web Api 项目中应用 NLog 写日志?
如何在 ASP.NET Core Web Api 项目中应用 NLog 写日志?
304 0
|
4月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
285 3
|
3月前
|
开发框架 搜索推荐 数据可视化
Django框架适合开发哪种类型的Web应用程序?
Django 框架凭借其强大的功能、稳定性和可扩展性,几乎可以适应各种类型的 Web 应用程序开发需求。无论是简单的网站还是复杂的企业级系统,Django 都能提供可靠的支持,帮助开发者快速构建高质量的应用。同时,其活跃的社区和丰富的资源也为开发者在项目实施过程中提供了有力的保障。
168 62
|
2月前
|
前端开发 安全 JavaScript
2025年,Web3开发学习路线全指南
本文提供了一条针对Dapp应用开发的学习路线,涵盖了Web3领域的重要技术栈,如区块链基础、以太坊技术、Solidity编程、智能合约开发及安全、web3.js和ethers.js库的使用、Truffle框架等。文章首先分析了国内区块链企业的技术需求,随后详细介绍了每个技术点的学习资源和方法,旨在帮助初学者系统地掌握Dapp开发所需的知识和技能。
2025年,Web3开发学习路线全指南
|
3月前
|
设计模式 前端开发 数据库
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
296 45

热门文章

最新文章