利用ASP.NET快速开发一款Web应用

需要用到的技术

.NET CORE 2.1:一个跨平台的高性能开源框架,用于生成启用云且连接 Internet 的新式应用

ASP.NET MVC:一种使用“模型-视图-控制器”设计模式构建 Web 应用和 API 的框架

ASP Razor Page:一种混合HTML和.NET语言而开发的服务端页面

SQL Server:一种关系型数据库

EF Code First:代码优先实体框架,一种迁移脚手架工具,以代码模型类为驱动的数据库表结构自动构建与更新同步工具。

BootStrap/EChart/jQuery: JS框架,内置丰富的web功能组件,拿来即用

需要实现的功能

通过HTTP请求调取基金接口数据,经过处理结构化后保存至数据库,开发数据增删改的WEB页面,利用URL传参嵌入其他web页面查看基金走势。

最终实现的效果

基金查询页面

根据页面设置的筛选条件,读取并展示数据库保存的数据内容

使用分页查询,一次最多展示12条数据

如果基金类型为货币基金 ,由内嵌页面不支持货币基金查询,故将Details链接移除

利用ASP.NET快速开发一款Web应用_第1张图片

编辑页面

利用脚手架工具自动生成的后台代码和页面

使用基金代码作为主键,更新数据库信息

利用ASP.NET快速开发一款Web应用_第2张图片

明细查询

利用ASP.NET快速开发一款Web应用_第3张图片

主要步骤及解释

1.新建一个基于ASP.NET CORE的Web应用项目

利用ASP.NET快速开发一款Web应用_第4张图片

选择一个模板,不同的模板会集成各自的JS技术框架,便于后面使用对应的框架语法和项目结构进行web开发

利用ASP.NET快速开发一款Web应用_第5张图片

 2.创建基金数据的模型类,并设置注解,方便EF工具自动创建表,其中,类名就是表名,类属性就是字段名,注解与字段属性一一对应

  public class Fund
  {
    [Display(Name = "基金代码")]
    [RegularExpression(@"^[0-9]+$")]
    [StringLength(6)]
    [Required]
    [Key]
    public string Code { get; set; }

    [Display(Name = "基金名称")]
    [Required]
    public string Name { get; set; }

    [Display(Name = "基金种类")]
    [Required]
    public string Type { get; set; }
  }

3.创建数据库上下文类,EF工具会根据该类的类名自动创建数据库和生成相关的文件,后面与数据库的交互(访问数据,更新数据,删除数据)也会使用该类,而不是直接编写SQL语言。总之,使用该类之后,系统已经帮你完成了绝大部分工作,而不用担心数据更新异常,数据校验,并发的问题。

public class FundContext : DbContext
    {
        public FundContext (DbContextOptions options)
            : base(options)
        {
        }

        public DbSet Fund { get; set; }
    }

3,安装并使用迁移工具EF first Core

Install-Package Microsoft.EntityFrameworkCore.SqlServer

4.使用脚手架自动生成增删改页面

利用ASP.NET快速开发一款Web应用_第6张图片

选择自动生成的方式,这里使用MVC

利用ASP.NET快速开发一款Web应用_第7张图片

 选择需要生成的模型类,数据库上下文类(如果之前步骤没有创建该类,这里也可以自动生成,只要点击加号,指定类名称即可)

最下面是需要生成的MVC的控制器类,视图类,也可以指定页面的公共布局页面等利用ASP.NET快速开发一款Web应用_第8张图片

自动生成目录文件和代码依赖注入

利用ASP.NET快速开发一款Web应用_第9张图片

 

 5.使用EF迁移工具

在NuGet Package Manager中打开包管理工具控制台(Package Manager Console (PMC))

 键入如下命令

Add-Migration InitialCreate

Update-Database

第一个命令,系统会自动根据数据库上下文类,生成数据库构建类,上载类和撤销上载类等文件,

利用ASP.NET快速开发一款Web应用_第10张图片

第二个命令,是确认执行命令

[DbContext(typeof(FundContext))]
    partial class FundContextModelSnapshot : ModelSnapshot
    {
        protected override void BuildModel(ModelBuilder modelBuilder)
        {
#pragma warning disable 612, 618
            modelBuilder
                .HasAnnotation("ProductVersion", "2.1.14-servicing-32113")
                .HasAnnotation("Relational:MaxIdentifierLength", 128)
                .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);

            modelBuilder.Entity("WebTest.Models.Fund", b =>
                {
                    b.Property("Code")
                        .ValueGeneratedOnAdd()
                        .HasMaxLength(6);

                    b.Property("Name")
                        .IsRequired();

                    b.Property("Type")
                        .IsRequired();

                    b.HasKey("Code");

                    b.ToTable("Fund");
                });
#pragma warning restore 612, 618
        }
    }

 该类保存创建数据库以及数据库和表之间关系的必要信息

public partial class InitialCreateFund : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.CreateTable(
                name: "Fund",
                columns: table => new
                {
                    Code = table.Column(maxLength: 6, nullable: false),
                    Name = table.Column(nullable: false),
                    Type = table.Column(nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Fund", x => x.Code);
                });
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropTable(
                name: "Fund");
        }
    }

 该类保存了建表语句与撤销建表语句的必要信息

如果后面涉及了表更新,需要重复上述命令,EF工具会自动新增迁移类,以下是增加模型类属性后EF迁移类自动生成的内容

public partial class Rating : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.AddColumn(
                name: "Rating",
                table: "Movie",
                nullable: true);
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropColumn(
                name: "Rating",
                table: "Movie");
        }
    }

EF工具会比较数据库表和模型类之间的差异,如果发现不同,它就会新增迁移类文件,Up方法记录了改表语句,Down方法记录了撤销改表的动作,生成的类允许再次修改,当使用包命令时,实际就是调用了生成的方法间接操作数据库 

更新完成之后,数据库自动增加了一个Schema和两张表

利用ASP.NET快速开发一款Web应用_第11张图片

 向表里增加数据或查询内容

利用ASP.NET快速开发一款Web应用_第12张图片

利用ASP.NET快速开发一款Web应用_第13张图片

 利用ASP.NET快速开发一款Web应用_第14张图片

以上步骤完成之后即可在IIS Express中访问增删改查页面

使用基金接口想数据库中写入数据

在Main方法前初始化数据,调用SeedData.Initialize方法

public static void Main(string[] args)
    {
      IWebHost webHost = CreateWebHostBuilder(args).Build();

      using (var scope = webHost.Services.CreateScope())
      {
        IServiceProvider services = scope.ServiceProvider;

        try
        {
          SeedData.Initialize(services);
        }
        catch (Exception ex)
        {
          var logger = services.GetRequiredService>();
          logger.LogError(ex, "An error occurred seeding the DB.");
        }
      }

      webHost.Run();
    }

 在初始化方法中通过服务器端发送HTTP GET请求获取基金数据

解析JS文本内容,编写LINQ语句,延时执行,防止卡顿

public class SeedData
  {
    public static void Initialize(IServiceProvider serviceProvider)
    {
      using(var context = new FundContext(
          serviceProvider.GetRequiredService<
              DbContextOptions>()))
      {
        // Look for any movies.
        if (!context.Fund.Any())
        {
          string resultstr = Utils.HttpCommon.HttpGet(@"http://fund.eastmoney.com/js/fundcode_search.js?v=" + DateTime.Now.ToString("yyyyMMddHHmmss"));
          //Regex regex = new Regex("var r = (?\\[\\[\"(?[0-9]{6})\",\".*?\",\"(?.*?)\",\"(?.*?)\".*?\\],{0,1})*\\]");
          Regex regex = new Regex("var r = (?\\[(\\[\"(?[0-9]{6})\"\\,\".*?\"\\,\"(?.*?)\"\\,\"(?.*?)\".*?\\][\\,]{0,1})+\\])");

          Match match = regex.Match(resultstr);
          int matchSize = match.Groups["Code"].Captures.Count;

          System.Collections.Generic.IEnumerable s = match.Groups["Code"].Captures.Select((v, i) => new { value = v.Value, index = i }).Join(match.Groups["Name"].Captures.Select((v, i) => new { value = v.Value, index = i }), a => a.index, b => b.index, (a, b) => new { Code = a.value, Name = b.value, a.index }).Join(match.Groups["Type"].Captures.Select((v, i) => new { value = v.Value, index = i }), a => a.index, b => b.index, (a, b) => new Fund { Code = a.Code, Name = a.Name, Type = b.value });

          //var SS = (from code in match.Groups["Code"].Captures select new { VALUE = code.Value, CODE = code.Index }).ToList();


          context.Fund.AddRange(s);
          context.SaveChanges();
        }
      }
    }
  }

 调用SaveChanges方法后,自动完成数据库更新

货币基金移除Details链接

使用Razor Page语法,其中@后面接的是.NET语言,如果使用C#开发,则接C#语言,如果是Visual Basic语言开发,则可以接Visual Basic。该语句仅在服务器端运行,系统会根据编写的语法糖输出符合HTML语法的替换内容,并发送到broswer端渲染并展示

注意到@后的循环语句和条件判断语句,用于生成相应的HTML替换文本


        @foreach (var item in Model.Funds) {
        
            @if (item.Type == "货币型")
            {
                
            }
            else
            {
                
            }
        
        }
    
@Html.DisplayNameFor(model => model.Funds[0].Code) @Html.DisplayNameFor(model => model.Funds[0].Name) @Html.DisplayNameFor(model => model.Funds[0].Type)
@Html.DisplayFor(modelItem => item.Code) @Html.DisplayFor(modelItem => item.Name) @Html.DisplayFor(modelItem => item.Type) Edit | Delete Edit | Details | Delete

Detail页面内容修改,嵌入基金明细页面

HTML CS混合编程,嵌入一个iframe标签,地址参数使用控制器类的变量ViewData["DetailURL"] 

ViewData是一个键值对表,可以在MVC任何地方使用

在View中,对DetailURL赋值,调用了以前开发好的Echart页面,并传递URL参数基金代码

@{
  ViewData["Title"] = "Details";
  ViewData["DetailURL"] = "http://localhost/Works/Echart/%E5%9F%BA%E9%87%91%E6%95%B0%E6%8D%AE.html?fundcode=" + Model.Code;
}

自开发明细WEB页面的处理内容

获取URL参数

// 获取url中的参数
        function getUrlParam(name) {
            var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
            var r = window.location.search.substr(1).match(reg);
            if (r != null) {
                return unescape(r[2]);
            } else {
                return null;
            }
        }  

发送AJAX请求访问基金走势的散点数据

所谓AJAX 就是异步js xml技术,相当于对HTTP请求的封装类,使用它方便从浏览器端发送HTTP请求,并异步处理返回的结果

getScript 方法不仅获取服务器的JS文件资源,而且对对其进行了执行

function viewfunddata(fundcode) {
            var sourcedata = [];
            var time = dateFormat("YYYYmmddHHMMSS", new Date());
            $.getScript('https://fund.eastmoney.com/pingzhongdata/' + fundcode + '.js?v=' + time, function () {
                for (var i = 0; i < Data_netWorthTrend.length; i++) { sourcedata[i] = [Data_netWorthTrend[i].x, Data_netWorthTrend[i].y]; }
                refreshEchardata(fS_name, fS_code, syl_1n, syl_6y, syl_3y, syl_1y, sourcedata);
            });
        }

执行完后,将JS中的变量值通过refreshEchardata方法传递给Echart组件

注意option中的sourcedata关键数据

option = {
                title: {
                    text: fundname + '(' + fundcode + ')'
                },

                visualMap: [{
                    show: true,
                    type: 'continuous',
                    min: 0,
                    max: 5
                }],

                tooltip: {
                    trigger: 'axis',
                    axisPointer: {
                        type: 'cross',
                        label: {
                            backgroundColor: '#6a7985'
                        }
                    }
                },
                xAxis: {
                    min: 1469225600000,
                    type: 'time'
                },
                yAxis: {
                    type: 'value'
                },
                dataZoom: [{
                    show: true,
                    type: 'inside',
                    filterMode: 'none',
                    xAxisIndex: [0],
                }, {
                    show: true,
                    type: 'inside',
                    filterMode: 'none',
                }],
                series: [{
                    symbolSize: 2,
                    data: sourcedata,
                    type: 'line',
                    showSymbol: false,
                    smooth: true,
                    areaStyle: {
                        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
                            offset: 0,
                            color: 'rgb(255, 255, 255,10)'
                        }, {
                            offset: 1,
                            color: 'rgb(255, 200, 231,0)'
                        }])
                    },
                    label: {
                        show: true,
                        position: 'top'
                    },
                    lineStyle: {
                        width: 1,
                        shadowColor: 'rgba(0,0,0,0.3)',
                        shadowBlur: 10,
                        shadowOffsetY: 8
                    },
                }]
            };
            if (option && typeof option === 'object') {
                myChart.setOption(option);
            }

 


  • 关于EF code first更新数据库机制,可以参考

EF应用一:Code First模式 - .NET开发菜鸟 - 博客园

  • Mysql也有相应的脚手架工具,亲测有效,用法与Sql Server相同,貌似在表字符集的映射上还存在点问题,插入中文时报错,也许是我装的版本太低,这个工具是开源的,以后有时间可以去找找原因。

Install-Package Pomelo.EntityFrameworkCore.MySql -Version 2.1.1

  • SQLite数据库也是支持的,安装语句:

Install-Package System.Data.SQLite

  • PostgreSQL数据库的EF脚手架工具安装语句
install-package npgsql -version 3.1.1
Install-Package EntityFramework6.Npgsql -Version 3.1.1

你可能感兴趣的:(BI,C#,ASP.NET,asp.net,前端,mvc)