ASP.NET MVC实现仪表程序

在大多数情况下,我们的Web程序不仅仅需要给用户提供具体数据,在一些情况下,我们还需要给高级的用户或管理者提供数据汇总和分析图表之类的功能。

如果我们不想显示一大堆烦心的数据,希望通过饼图或条形图来直观地显示数据,这是我们可以考虑使用图表控件显示。

在接下来的文章中,我们将向大家介绍数据仪表板程序的实现。

之前有一篇文章关于StackOverflow上的编程趋势,它通过条形和区域图,向我们展示了Stackoverflow上的热门的问题标签。

图1 Stackoverflow的热门标签

通过上图,我们可以直观地了解Stackoverflow上的热门标签的变化趋势,现在,我们通过仪表程序实现同样的功能。

在仪表程序界面中,我们会通过饼状图、区域图和条形图显示数据,这里我们使用Google Charts控件来显示饼状图、区域图和条形图数据图。

Google Charts通过Javascript实现动态图片的绘制,它的使用非常简便,我们只需给相应的绘图函数传递相应的数据,就可以生成相应的数据图表了。

UI设计

图2 Dashboard界面

现在,我们要在主界面(Dashboard)中,显示数据的饼状图、区域图和条形图,那么我们使用Google Charts控件动态地把三种图形加载到Index.cshtml页面中,下面是Index.cshtml页面代码:

<!-- Dashboard UI START -->
<body>
 <div>
  @{ Html.RenderAction("Dashboard_Pie", "DashBoard"); }
 </div>
 <div>
  @{ Html.RenderAction("Dashboard_AreaChart", "DashBoard"); }
 </div>
 <div>
  @{ Html.RenderAction("Dashboard_ColumnChart", "DashBoard"); }
 </div>
</body>
<!-- Dashboard UI END -->

上面,我们定义了三个div元素,Index.cshtml页面动态地加载Dashboard_Pie、Dashboard_AreaChart以及Dashboard_ColumnChart的内容。

接下来,我们要定义Dashboard_Pie(饼状图)、Dashboard_AreaChart(区域图)和Dashboard_ColumnChart(条形图)页面,在定义数据图界面之前,首先让我们介绍Google Charts的使用。

Javascript
前面我们提到Google Charts的使用十分方便,首先我们需要引用jsapi库,在页面代码中添加如下代码:

<!-- Adds Google js api reference.-->
<script type="text/javascript" src="https://www.google.com/jsapi"></script>

Google的JSAPI,不仅可以加载Google自身提供的AJAX API(如:Google Map API、Google Search API和Google Earth API),它还可以加载各种常用的JS库(如:jQuery、jQuery UI、Prototype、MooTools和Dojo等)。

现在,我们在页面中添加如下Javascript代码,引用Google的visualization库:

<script type="text/javascript">
 google.load("visualization", "1", { packages: ["corechart"] });
 google.setOnLoadCallback(drawPieChart);

</script>

上面,我们使用google的load()方法加载了visualization库,并且定义了加载成功后的回调函数为drawPieChart()。

也许有人会问:“为什么不直接用Google CDN中提供Javascript库呢?”有两个原因,首先我们在Google CDN中没有找到和visualization库相关的引用地址(如有请告诉一下),其次,google的load()方法会加载一系列相关的资源(如:Javascript和CSS),这样我们就无需一个个引用了。

前面,我们定义了回调函数drawPieChart(),但还没有实现该方法,接下来,我们需要实现回调函数drawPieChart(),它负责获绘制数据图,具体实现如下:

/**
* Draws the pie chart.
**/
function drawPieChart() {

 // Gets data from GetLanguageRank().
 $.ajax({
  type: 'GET',
  dataType: 'json',
  url: '<%= Url.Content("") %>',
  data: {},
  success: function(data) {
   var dt = new google.visualization.DataTable();

   dt.addColumn('string', 'Language');
   dt.addColumn('number', 'Question');

   // Adds data.
   for (var i = 0; i < data.length; i++) {
    dt.addRow([data[i].Name, data[i].Question]);
   }

   var options = {
    title: "Top 25 programming language"
   };

   // Draws pie implemention.
   var chart = new google.visualization.PieChart(document.getElementById('pieChart'));
   chart.draw(dt, options);
  },
  error: function(xhr, textStatus, e) {
   console.log('Status: ' + textStatus + ' Error: ' + e.toString());
  },
  complete: function() {
  }

 });
}

上面,我们实现了回调函数drawPieChart(),它通过调用$.ajax()方法从后端中获取数据,如果数据获取成功,就把数据传递给draw()方法绘制数据图表。

接着,我们实现Dashboard_Pie数据图界面,具体代码如下:

<!-- Pie chart page -->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 <title></title>
</head>
<body>
 <form id="form2" runat="server">
  <div id="pieChart">
  </div>
 </form>
</body>
</html>

上面,我们在form元素中添加了一个div元素,由于我们在回调函数drawPieChart()中,指定了饼状图的加载位置,所以我们需要在页面中添加饼状图的div元素。

前面,我们提到回调函数drawPieChart(),通过$.ajax()方法从后端中获取数据,现在,我们需要提供API方法,让客户端通过调用API获取相应的数据。

这里,我们使用Stackoverflow Jan/01/2010到July/01/2013的热门标签数据。

由于数据是CSV格式的,所以我们可以使用Excel查看数据。

图3 热门标签数据

通过上图中的数据,我们定义Language类,它包含四个字段分别是Id、Name、Question和CreateOn,具体定义如下:

图4 Language类

/// <summary>
/// The language model.
/// </summary>
public class QuestionTag
{
 public int Id { get; set; }
 public string Name { get; set; }
 public int Question { get; set; }
 public DateTime CreateOn { get; set; }
}

上面,我们定义了QuestionTag类,接下来,我们需要定义控制器类,它负责返回后端数据,所以我们在Controllers文件中创建DashboardController类,并且我们添加GetLanguageRank()方法,具体实现如下:

图5 DashboardController类

/// <summary>
/// Gets language rank data.
/// </summary>
/// <returns>JSON arrary.</returns>
public JsonResult GetLanguageRank()
{
 // Gets data from database.
}

导入数据
上面,我们定义了DashboardController类,它包含GetLanguageRank()方法,接下来我们把CSV数据保存到数据库中。首先,我们在数据库中创建数据表,具体SQL代码如下:

-- =============================================
-- Description: Table for storing question tag data
-- =============================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[QuestionTags](
 [Name] [varchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL,
 [Question] [int] NOT NULL,
 [CreateOn] [datetime] NOT NULL
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF

接着,我们CSV数据导入到SQL Server中,具体实现如下:

-- =============================================
-- Description: Imports csv data into database.
-- =============================================
BULK INSERT QuestionTags
FROM 'C:\Users\Administrator\Desktop\Stackoverflow Tags Data.csv'
WITH
(
 FIRSTROW = 2,   -- Start row excludes header.
 FIELDTERMINATOR = ',', --CSV field delimiter
 ROWTERMINATOR = '\n', --Use to shift the control to next row
 ERRORFILE = 'C:\Users\Administrator\Desktop\ErrorLog.csv',?
 TABLOCK
)

上面,我们直接使用SQL语句把CSV数据导入到数据库中,其中,我们定义了导入数据的源文件和数据格式,并且定义了ErrorLog文件记录导入失败的数据,最后,我们在表QuestionTags中添加自增型的Id主键。

图6 导入CSV数据

ASP.NET控制器
现在,我们已经把数据储存到数据库中了,接下来我们将使用EF获取数据库中的数据,接触过EF的应该都知道EF的编程模型有3种:

  • Database First:数据库先行
  • Model First:模型先行
  • Code First:代码先行

由于,前面我们已经把数据表定义好了,所以我们将使用数据库先行(Database First)模型对数据库进行访问。

接下来,让我们实现GetLanguageRank()方法,具体代码如下:

/// <summary>
/// Gets language rank data.
/// </summary>
/// <param name="index">Specifies the range of data,
/// for instance, when index is 0, then get the data range from Jan/1/2010 till Feb/2/2010.
/// </param>
/// <returns>JSON Array</returns>
public JsonResult GetLanguageRank(int index = 0)
{
 using (var db = new DashboardDbContext())
 {
   var result = (from tags in db.QuestionTags
       orderby tags.CreateOn ascending
   select new { tags.Id, tags.Name, tags.Question, tags.CreateOn }).Skip((index % 42) * 25).Take(25).ToList();
   return Json(result, JsonRequestBehavior.AllowGet);
 }
}

我们实现了GetLanguageRank()方法,它根据index值获取指定时间的数据,然后通过JSON数据格式返回给客户端。

现在,我们已经实现了饼状图(Dashboard_Pie)了,接下来,让我们运行Index.cshtml页面查看运行的效果吧!

图7 饼状图

我们注意到图1是一个动态图,它直观的展示了Stackoverflow热门标签的变化趋势,如果我们也要实现动态生成数据图该如何实现呢?

其实,问题转化为实时获取数据,然后生成数据图就OK了,如果要实现实时获取时间,我们想到的方法有:

  • 1.Timer()
  • 2.方法二数据库实时方法数据(SqlDependency)
  • 3.Other(请大家分享好方法)

接下来,我们将使用Javascript中Timer()函数来定时访问GetLanguageRank()方法,所以我们需要修改Javascript代码,通过Timer()函数定时调用drawColumnChart()方法,具体实现如下:

<script type="text/javascript">
 google.load("visualization", "1", { packages: ["corechart"] });
 google.setOnLoadCallback(timerStart);

 var cnt = 0, t;
 function timerStart() {
  t = window.setInterval(drawColumnChart, 1000);
 }

 function timerStop() {
  clearTimeout(t);
 }

 function drawColumnChart() {

  $.ajax({
   type: 'GET',
   dataType: 'json',
   url: '<%= Url.Content("~/Dashboard/GetLanguageRank") %>',
   data: { index: cnt },
   success: function(data) {
    var dt = new google.visualization.DataTable();

    dt.addColumn('string', 'Language');
    dt.addColumn('number', 'Question');

    for (var i = 0; i < data.length; i++) {
     dt.addRow([data[i].Name, data[i].Question]);
    }

    var dateTime = new Date(parseInt(data[0].CreateOn.substr(6)));

    var options = {
    title: "Top 25 programming language on " +
     (dateTime.getMonth() + 1) + '/' + dateTime.getDate() + '/' + dateTime.getFullYear(),
     //width: 600,
     height: 500
    };

    var chart = new google.visualization.ColumnChart(document.getElementById('columnChart'));
    chart.draw(dt, options);
   },
   error: function(xhr, textStatus, e) {
    timerStop();
    console.log('Status: ' + textStatus + ' Error: ' + e.toString());
   },
   complete: function() {
    cnt = cnt + 1;
   }

  });
 }
</script>

当Google的visualization库加载完毕后,访问回调函数timerStart(),然后使用setInterval()方法每隔1s就调用drawColumnChart()绘制新的柱状图。

图8 柱状图

现在,我们通过Timer()函数实时的访问API接口,数据通过柱状图动态地显示出来。

页面样式
现在,我们已经完成了饼状图和柱状图,接下来,我们需要给仪表程序添加一些简单的CSS效果,具体代码如下:

/*Dashboard APP CSS*/
.pageHeader
{
 height: 20px;
 background-color: #2C2C2C;
 padding: 10px 10px;
 margin-bottom: 10px;
 color: White;
 position: relative;
}

 .pageHeader h1
 {
  font: normal 1.2em Arial;
  color: White;
  margin: 0;
  padding: 0;
 }

 .pageHeader .platformular
 {
  position: absolute;
  top: 10px;
  right: 10px;
 }

.pageBody
{
 margin: 0 10px;
}

.pageFooter
{
 clear: both;
 padding-top: 10px;
 width: 100%;
 text-align: center;
 font-size: 0.8em;
 color: #686868;
 margin: 25px 0 0 0;
 border-top: solid 1px #e7e7e7;
}

现在,我们重新运行程序查看页面效果。

图10仪表程序

在本文中,我们通过使用ASP.NET MVC和EF的Database First实现了简单的仪表程序,使用Google Charts控件来显示数据图,这只是一个简单的程序,我们还有很大的改善空间,提供一个内容丰富和功能强大的程序是每个程序员的目标。

以上就是本文的全部内容,希望对大家的学习有所帮助。

(0)

相关推荐

  • ASP.NET MVC命名空间时引起错误的解决方法

    使用VS2012新建了一个Asp.net mvc5的项目,并把项目的命名空间名称更改了(Src更改为UXXXXX),然后就导致了以下错误 刚开始以后是项目的属性中的命名空间没有更改过来的问题,但我在重命名时更改的是全局的名称,而且所有文件的命名空间都已经更改过来了 稍候思考了一下并在解决方案里搜索了"Src"除了页面中引用的js脚本外还发现Views/web.config文件中包含"Src" Asp.net MVC自动生成的代码如下,可以看到自动生成的代码将View

  • 详解ASP.NET MVC Form表单验证

    一.前言 关于表单验证,已经有不少的文章,相信Web开发人员也都基本写过,最近在一个个人项目中刚好用到,在这里与大家分享一下.本来想从用户注册开始写起,但发现东西比较多,涉及到界面.前端验证.前端加密.后台解密.用户密码Hash.权限验证等等,文章写起来可能会很长,所以这里主要介绍的是登录验证和权限控制部分,有兴趣的朋友欢迎一起交流. 一般验证方式有Windows验证和表单验证,web项目用得更多的是表单验证.原理很简单,简单地说就是利用浏览器的cookie,将验证令牌存储在客户端浏览器上,co

  • ASP.NET Mvc开发之EF延迟加载

    先来看看定义 EF延迟加载:就是使用Lamabda表达式或者Linq 从 EF实体对象中查询数据时,EF并不是直接将数据查询出来,而是在用到具体数据的时候才会加载到内存. 一.实体对象的Where方法返回一个什么对象? 大家来看一下上一篇文章的代码来分析一下: #region 查询文章列表+ActionResult Article() /// <summary> /// 查询文章列表 /// </summary> /// <returns></returns>

  • ASP.NET Mvc开发之查询数据

    对于.NET平台上开发WebForm项目,程序员操作数据的方法主要是通过使用ADO.NET.而我们MVC操作数据库呢?与ADO.NET相比又有怎样的优势呢? 一.大家都在谈的EF到底是什么? EF,全称EntityFramWork.就是微软以ADO.NET为基础发展的所谓ORM(对象关系映射框架,或者说是数据持久化框架). 简单的来说就是根据实体对象操作数据表中数据的一种面向对象的操作框架,具体的底层也是调用ADO.NET. 下面我们就来演示怎么使用EF来操作数据库: 在数据库关系图中,表之间的

  • ASP.NET MVC4 HtmlHelper扩展类,实现分页功能

    1.扩展HtmlHelper类方法ShowPageNavigate public static HtmlString ShowPageNavigate(this HtmlHelper htmlHelper, int currentPage, int pageSize, int totalCount) { var redirectTo = htmlHelper.ViewContext.RequestContext.HttpContext.Request.Url.AbsolutePath; page

  • ASP.NET MVC @Helper辅助方法和@functons自定义函数的使用方法

    ASP.NET Razor 视图具有.cshtml后缀,可以轻松的实现c#代码和html标签的切换,大大提升了我们的开发效率.但是Razor语法还是有一些棉花糖值得我们了解一下,可以更加强劲的提升我们的开发效率,减少开发bug的出现. Razor 采用的是@尾巴符号,正是这个符号成就了MVC开发效率的提升.下面了解一下和@相关的两个可以重用的helper.functions. 作为现代化的程序员,我们尽可能的遵守一个原则.不要重复你自己.所以能够重构的代码我们都会合并,但是这是对于后台代码C#来

  • ASP.NET Mvc开发之删除修改数据

    之前那篇文章介绍了ASP.NET MVC使用EF来查询数据和EF中DbQuery<T>泛型对象对数据的延迟加载.今天我们就来看看我们怎么使用EF来删除数据. 其实现在的Web开发通用的模式就是前端使用Js和JQuery来和后端进行数据交互.那么我们就在前端来加两个删除和更新的脚本.代码如下: <!--遍历 Action方法 设置给 ViewData 的集合数据,生成HTML代码--> @foreach (BlogArticle a in ViewData["DataLis

  • asp.net MVC利用自定义ModelBinder过滤关键字的方法(附demo源码下载)

    本文实例讲述了MVC利用自定义ModelBinder过滤关键字的方法.分享给大家供大家参考,具体如下: 前面一篇主要讲解了如何利用ActionFilter过滤关键字,这篇主要讲解如何利用自己打造的ModelBinder来过滤关键字. 首先,我们还是利用上一篇<asp.net MVC利用ActionFilterAttribute过滤关键字的方法>中的实体类,但是我们需要加上DataType特性,以便于我们构造的ModelBinder通过DataTypeName识别出来: using System

  • ASP.NET MVC中HtmlHelper控件7个大类中各个控件使用详解

    HtmlHelper类在命令System.Web.Mvc.Html之中,主要由7个静态类组成,它们分别是FormExtensions类,InputExtensions类,LinkExtensions类,SelectExtensions类,TextExtensions类,ValidationExtensions类,RenderPartialExtensions类. 为了方便开发者使用HtmlHelper控件,在视图ViewPage类中设置了一个属性Html它就是HtmlHelper类型. 一.Fo

  • ASP.NET MVC使用ActionFilterAttribute实现权限限制的方法(附demo源码下载)

    本文实例讲述了ASP.NET MVC使用ActionFilterAttribute实现权限限制的方法.分享给大家供大家参考,具体如下: ActionFilterAttribute是Action过滤类,该属于会在执行一个action之前先执行.而ActionFilterAttribute是 MVC的一个专门处理action过滤的类.基于这个原理 我们做一个权限限制 例如:如何访问 HomeController  里的test  action using System; using System.C

  • 解决asp.net mvc UpdateModel更新对象后出现null问题的方法

    在用asp.net mvc 4.0做项目的时候遇到的这种情况: 情况分析: "在填写表单的时候,有一些表单没有填写,留空,然后直接post 提交表单,action中用UpdateModel 来更新model,结果发现那些没有填写的表单字段全部变成null." 原因分析: 项目中做了判断null不能提交更新到数据库中,所以导致一直提交不上去 后来网上查了一下找到了解决办法,我在这里分享一下,方便以后遇到这种情况的朋友可以方便解决 解决方法: 新建一个类继承DefaultModelBind

随机推荐