原文请参照:Creating a Stock Widget in ASP.NET MVC Application
Widgets在近年来应用非常广泛,本文利用RenderAction方法在asp.net mvc程序上建立一个股票Stock的Widget。
什么是RenderAction
RenderAction允许调用该页面Controller的某个action,该action的结果插入到这个页面。可以把该action看做与这个页面是相互独立的。
Stock服务
在实际应用里面有许多服务提供商提供Stock的服务,本文利用XML文件提供股票信息,如下显示
<?xml version="1.0" encoding="utf-8" ?> <Stocks> <Stock Name="Day Star" Price="4" LastPrice="15" /> <Stock Name="Starbucks" Price="50" LastPrice="500" /> <Stock Name="Intel" Price="100" LastPrice="1.23" /> </Stocks>
创建Stock Entity和Stock Service
根据XML文件, Stock Entity由以下内容组成:
public class Stock { public string Name { get; set; } public double Price { get; set; } public double LastPrice { get; set; } }
StockService负责读取“StockUpdates.xml”文件的信息,实现如下:
public class StockService { /// <summary> /// Get StockUpdates.xml Infomation
/// </summary> /// <returns></returns> public IList<Stock> GetLaset() { var stocks = new List<Stock>(); // read the StockUpdates.xml files var document = XDocument.Load(HttpContext.Current.Server.MapPath("~/StockUpdates.xml")); var root = document.Root; if (root == null) { throw new ArgumentNullException("Error in XML file. No root elment exist!"); } // read each stock element information var stockElements = root.Elements("Stock"); foreach (var stockElement in stockElements) { var stock = new Stock() { Name = stockElement.Attribute("Name").Value, Price = Convert.ToDouble(stockElement.Attribute("Price").Value), LastPrice = Convert.ToDouble(stockElement.Attribute("LastPrice").Value) } stocks.Add(stock); } return stocks; }
实现LatestStocks部分视图
由于股票信息应该是显示为页面的一小部分,所以其显示应该是作为一个部分视图,如果你对于部分视图不熟悉,可以参考下面的内容:
Understanding Partial Views in ASP.NET MVC Application
Screencast: Introduction to Partial Views in ASP.NET MVC Application
部分视图的实现如下:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Stock>>" %> <%@ Import Namespace="StockWidgetsASPNETMVC.Models" %> <div id="divLatestStocks"> <table> <tr> <td> <b>Name </b> </td> <td> <b>Price </b> </td> <td> <b>Last Price</b> </td> </tr> <% foreach (var stock in Model) { %> <tr> <td> <%= stock.Name %> </td> <td> <% if (stock.Price > stock.LastPrice) { %> <span class="stockUp"> <%= stock.Price %> </span> <% } else { %> <span class="stockDown"> <%= stock.Price %> </span> <% } %> </td> <td> <%= stock.LastPrice %> </td> </tr> <% } %> </table> </div>
对于该部分视图有几个重点内容,首先在文件开始的地方,定义了传递内容的强类型
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Stock>>" %>
另外定义了一个id为divLatestStocks的DIV标签,用来放置每一个widget。
controller action的实现
“LatestStockUpdates”用来显示Stock的信息。 Stock列表的信息通过ViewData dictionary传递给部分视图。实现如下:
private StockService _stockservice = null; public HomeController() { _stockservice = new StockService(); }
public ActionResult LatestStockUpdates() { var stocks = _stockservice.GetLaset(); if (null == stocks) { return View("No Stocks View"); } return View("LatestStocks", stocks); }
调用Html.RenderAction方法
RenderAction方法能在ViewPage里面的任何地方调用,调用方法如下
<% Html.RenderAction<HomeController>(x => x.LatestStockUpdates()); %>
运行结果:
用绿色表示增长,红色表示下降。(也许应该符合国情地反过来)
利用Ajax对Widget进行更新
利用mvc自带的JQuery非常简单,实现如下:
<script type="text/javascript"> setInterval(update, 1000); function update() { $("#divLatestStock").load('/home/LatestStockUpdates'); } </script>
其中’/home/LatestStockUpdates’指向HomeController的LatestStockUpdates Action。
VS2010 与 MVC2的相关问题
由于VS2010只内置了MVC2的Preview版本,并且目前的MVC2的更新只支持VS2008 sp1,不支持VS2010 beta版本。并且RenderAction只存在于mvc2 beta以后的版本,所以不能使用该方法。(可以下载最新的mvc2 dll,进行引用后可以使用RenderAction,但是程序运行时出错,可能仍然不兼容asp.net 4.0) 但是可以直接使用Javascript进行显示。如下,先给定一个要显示的位置:
<div id="divStock"></div> <script type="text/javascript"> $("#divStock").load('/home/LatestStockUpdates'); </script>
代码下载
Update: YUI3更新代码
<script type="text/javascript"> YUI().use('node', 'io', function (Y) { var contain = Y.one('#divStock'); Y.io('/home/LatestStockUpdates', { on: { complete: function (id, data) { contain.set('innerHTML', data.responseText); }, failure: function (id, data) { Y.log("Some error"); } } }); }); </script>