草图

 

真正的后端是不管前端是什么平台,用什么语言的,JSON格式的数据应该可以应对。用ASP.NET WEBAPI尝试做一个后端,实现最基本的CURD,业务逻辑和数据库操作都放在后端,前端只需要正确访问和提供必要的数据就行。

个人习惯

我喜欢先意淫一下需求,然后找出需要的实体和逻辑,而不是先设计数据库,现在EF那么牛逼,完全可以在代码上生成表和表之间的关系,各种查询语句效率并不一定比你写sql语句差。所以我在做东西的时候从来不先考虑数据的。但是今天主要是练习api和复习一下ado.net的CURD,所以没有用EF。长时间用EF不写sql,都忘光了啊。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Model
{
    public class Employee
    {
        public int Id { get; set; }
        public int Age { get; set; }
        public string Number { get; set; }
        public string Name { get; set; }
        public int DepartmentId { get; set; }
        public string Gender { get; set; }
        public string Job { get; set; }
        public string Telephone { get; set; }
        public float Salary { get; set; }
        public DateTime EntryTime { get; set; }
    }
}

Employee

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Model
{
    public class Department
    {
        public int Id { get; set; }
        public string Number { get; set; }
        public string Name { get; set; }
        public string Manager { get; set; }
        public bool IsDel { get; set; }
    }
}

Department

using System.Data;
using System.Data.SqlClient;
using System.Collections;
using System;
using System.Configuration;

namespace DAL
{
    public abstract class SqlHelper
    {
        /// <summary>
        /// 数据库连接字符串
        /// </summary>
        public static readonly string connectionString = ConfigurationManager.ConnectionStrings["conStr"].ToString();

        // 线程安全的哈希表
        private static Hashtable parmCache = Hashtable.Synchronized(new Hashtable());

        /// <summary>
        /// 为执行命令准备参数
        /// </summary>
        /// <param name="cmd">SqlCommand 命令</param>
        /// <param name="conn">已经存在的数据库连接</param>
        /// <param name="cmdType">SqlCommand命令类型 (存储过程, T-SQL语句, 等等。)</param>
        /// <param name="cmdText">Command text,T-SQL语句 例如 Select * from Products</param>
        /// <param name="cmdParms">返回带参数的命令</param>
        private static void PrepareCommand(SqlCommand cmd,
            SqlConnection conn, CommandType cmdType,
            string cmdText, SqlParameter[] cmdParms)
        {
            if (conn.State != ConnectionState.Open)
                conn.Open();
            cmd.Connection = conn;
            cmd.CommandType = cmdType;
            if (cmdParms != null)
                cmd.Parameters.AddRange(cmdParms);
            cmd.CommandText = cmdText;
        }

        public static int NonQuery(CommandType type,string sql,params SqlParameter[]pars)
        {
            SqlCommand cmd = new SqlCommand();
            using (SqlConnection con = new SqlConnection(connectionString))
            {
                PrepareCommand(cmd, con, type, sql, pars);
                int n = cmd.ExecuteNonQuery();
                cmd.Parameters.Clear();
                return n;
            }
        }

        /// <summary>
        /// Execute a SqlCommand that returns a resultset against the database
        /// </summary>
        /// <param name="connectionString">一个有效的数据库连接字符串</param>
        /// <param name="cmdType">SqlCommand命令类型 (存储过程, T-SQL语句, 等等。)</param>
        /// <param name="cmdText">存储过程的名字或者 T-SQL 语句</param>
        /// <param name="commandParameters">以数组形式提供SqlCommand命令中用到的参数列表</param>
        /// <returns>一个SqlDataReader的结果</returns>
        public static SqlDataReader ExecuteReader(CommandType cmdType, string cmdText, params SqlParameter[] commandParameters)
        {
            SqlCommand cmd = new SqlCommand();
            SqlConnection conn = new SqlConnection(connectionString);
            try
            {
                PrepareCommand(cmd, conn,cmdType, cmdText, commandParameters);
                SqlDataReader sdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
                cmd.Parameters.Clear();
                return sdr;
            }
            catch
            {
                conn.Close();
                throw;
            }
        }

        public static DataSet GetDataSet(CommandType type,string sql,params SqlParameter[]pars)
        {
            SqlCommand cmd = new SqlCommand();
            DataSet ds = new DataSet();
            using (SqlConnection con = new SqlConnection(connectionString))
            {
                PrepareCommand(cmd, con, type, sql, pars);
                using (SqlDataAdapter adp = new SqlDataAdapter(cmd))
                {
                    adp.Fill(ds);
                    //cmd.Parameters.Clear();
                }
            }
            return ds;
        }

        #region ExecuteScalar方法

        /// <summary>
        /// 返回第一行的第一列
        /// </summary>
        /// <param name="cmdType">SqlCommand命令类型 (存储过程, T-SQL语句, 等等。)</param>
        /// <param name="cmdText">存储过程的名字或者 T-SQL 语句</param>
        /// <param name="commandParameters">以数组形式提供SqlCommand命令中用到的参数列表</param>
        /// <returns>返回一个对象</returns>
        public static object Scalar(CommandType type, string sql, params SqlParameter[] pars)
        {
            SqlCommand cmd = new SqlCommand();
            using (SqlConnection con = new SqlConnection(connectionString))
            {
                PrepareCommand(cmd, con, type, sql, pars);
                object o = cmd.ExecuteScalar();
                cmd.Parameters.Clear();
                return o;
            }
        }

        #endregion

        /// <summary>
        /// 缓存参数
        /// </summary>
        /// <param name="cacheKey">索引键</param>
        /// <param name="cmdParms">参数数组</param>
        public static void CacheParameters(string cacheKey, params SqlParameter[] commandParameters)
        {
            parmCache[cacheKey] = commandParameters;
        }

        /// <summary>
        /// 通过索引键获取哈希表中的sql参数
        /// </summary>
        /// <param name="cacheKey"></param>
        /// <returns></returns>
        public static SqlParameter[] GetCachedParameters(string cacheKey)
        {
            SqlParameter[] cachedParms = (SqlParameter[])parmCache[cacheKey];
            if (cachedParms == null)
                return null;
            SqlParameter[] clonedParms = new SqlParameter[cachedParms.Length];
            , j = cachedParms.Length; i < j; i++)
                clonedParms[i] = (SqlParameter)((ICloneable)cachedParms[i]).Clone();
            return clonedParms;
        }

        /// <summary>
        /// 检查是否存在
        /// </summary>
        /// <param name="strSql">Sql语句</param>
        /// <returns>bool结果</returns>
        public static bool Exists(string strSql)
        {
            int cmdresult = Convert.ToInt32(Scalar(CommandType.Text, strSql, null));
            )
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        /// <summary>
        /// 检查是否存在
        /// </summary>
        /// <param name="strSql">Sql语句</param>
        /// <param name="cmdParms">参数</param>
        /// <returns>bool结果</returns>
        public static bool Exists(string strSql, params SqlParameter[] cmdParms)
        {
            int cmdresult = Convert.ToInt32(Scalar(CommandType.Text, strSql, cmdParms));
            )
            {
                return false;
            }
            else
            {
                return true;
            }
        }
    }

}

SqlHelper

有一个常用的视图

USE [Demo]
GO

/****** Object:  View [dbo].[EmpView]    Script Date: 2016/8/22 16:06:46 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

create view [dbo].[EmpView]
as
select Employee.Number as 编号,
       Employee.Name as 姓名,
       Department.Name as 部门,
       Employee.Age as 年龄,
       Employee.Gender as 性别,
       Employee.Job as 职位,
       Employee.Telephone as 电话,
       Employee.Salary as 工资,
       Employee.EntryTime as 入职时间

from Employee ,Department
where Department.Id=Employee.DepartmentId

GO

EmpView

开始意淫

分页查询所有的员工信息,以前面的视图为模型。写一个简单的,没有过滤的分页存储过程

USE [Demo]
GO
/****** Object:  StoredProcedure [dbo].[Pager]    Script Date: 2016/8/22 16:26:03 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE procedure [dbo].[Pager]
@index int ,@size int,@count int output
as
begin
declare @c int
)*@size
select @c=count(*) from EmpView
set @count=@c
end

Pager

准备把所有的业务放在API项目中

using Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using DAL;
using System.Data;
using Newtonsoft.Json;
using Newtonsoft;
using System.Data.SqlClient;

namespace WebApiTest
{
    public class BLL
    {
        private dynamic GetLineEmpView(DataRow row)
        {
            return new
            {
                Age = row["年龄"] == DBNull.Value ? string.Empty : row["年龄"].ToString(),
                Salary = row["工资"] == DBNull.Value ? string.Empty : row["工资"].ToString(),
                Name = row["姓名"] == DBNull.Value ? string.Empty : row["姓名"].ToString(),
                Job = row["职位"] == DBNull.Value ? string.Empty : row["职位"].ToString(),
                Number = row["编号"] == DBNull.Value ? string.Empty : row["编号"].ToString(),
                Telephone = row["电话"] == DBNull.Value ? string.Empty : row["电话"].ToString(),
                Gender = row["性别"] == DBNull.Value ? string.Empty : row["性别"].ToString(),
                EntryTime = row["入职时间"] == DBNull.Value ? string.Empty :row["入职时间"].ToString(),
                DepName = row["部门"].ToString()
            };

        }
        public List<dynamic> GetEmpView()
        {
            List<dynamic> list = new List<dynamic>();
            string sql = "select * from EmpView";
            DataTable dt = SqlHelper.GetDataSet(CommandType.Text, sql, ];
            if(dt!=null)
            {
                foreach (DataRow row in dt.Rows)
                    list.Add(GetLineEmpView(row));
                return list;
            }

            return list;
        }
        public List<dynamic> GetEmpView(int index,int size,out int count)
        {
            string sql = "Pager";
            SqlParameter[] pars =
            {
                new SqlParameter("@index",SqlDbType.Int),
                new SqlParameter("@size",SqlDbType.Int),
                new SqlParameter("@count",SqlDbType.Int)
            };
            pars[].Value = index; pars[].Direction = ParameterDirection.Input;
            pars[].Value = size; pars[].Direction = ParameterDirection.Input;
            pars[].Direction = ParameterDirection.Output;
            DataTable dt = SqlHelper.GetDataSet(CommandType.StoredProcedure, sql, pars).Tables[];
            ].Value.ToString(), out count);
            List<dynamic> list = new List<dynamic>();
            if(dt!=null)
            {
                foreach (DataRow row in dt.Rows)
                    list.Add(GetLineEmpView(row));
            }
            return list;
        }
    }
}

BLL

apicontroller调用这个这个类,对外提供2个GET的restful响应api,返回json格式的数据。这里的JSON数据没有处理好,用的.net的JsonResult格式,而不是直接用json.net返回,原因是直拉用json.net返回的时候,把原本排好的json格式又加了“”号和转义\。这个以后再想办法,现在也只是多了几个.net默认的几条数据,不要它就行了。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace WebApiTest.Controllers
{
    public class CompanyController : ApiController
    {
        private BLL bll = new BLL();
        public JsonResult Get()
        {
            return new JsonResult { Data = bll.GetEmpView() };
        }
        public JsonResult Get(int pageIndex,int pageSize)
        {
            int count;
            string data=JsonConvert.SerializeObject( bll.GetEmpView(pageIndex, pageSize, out count));
            var json=new JObject(new JProperty("PageTotalCount", count), new JProperty("EmpList", data));
            return new JsonResult { Data = json };
        }
    }
}

CompanyController

哈哈哈哈,说好的CURD可是从早上到现在只完成一个简单的分页查询,不过我觉得把这个做好了,其它的只是照搬了。那么对于这个简单需求来说,后端的工作已经完成了。再就是前端调用展示了。

前端调用和展示

客户端暂时封装一个对服务的GET请求

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;

namespace TestMVCApp
{
    public class RestClient
    {
        private string BaseUri;
        public RestClient(string baseUri)
        {
            this.BaseUri = baseUri;
        }
        public string Get(string uri)
        {
            //Web访问服务
            string serviceUrl = string.Format("{0}/{1}", this.BaseUri, uri);

            //构造一个Web请求的对象
            HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(serviceUrl);

            //获取web请求的响应的内容
            HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();

            //通过响应流构造一个StreamReader
            StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);
            //string ReturnXml = HttpUtility.UrlDecode(reader.ReadToEnd());
            string ReturnXml = reader.ReadToEnd();
            reader.Close();
            myResponse.Close();
            return ReturnXml;
        }
    }
}

RestClient

虽然我是在一个解决方案里做的,但我假设前端对后端一无所知,只知道自己需要什么,后端能给什么。所以另外搞个视图的模型类,接收数据(Models文件夹中)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace TestMVCApp.Models
{

    public class EmpView
    {
        public string Name { get; set; }
        public string Age { get; set; }
        public string DepName { get; set; }
        public string Salary { get; set; }
        public string Job { get; set; }
        public string Number { get; set; }
        public string Telephone { get; set; }
        public string Gender { get; set; }
        public string EntryTime { get; set; }

    }
    public class EmpData
    {
        public int PageTotalCount { get; set; }
        public List<EmpView> EmpList { get; set; }
    }
}

TestMVCApp.Models

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using TestMVCApp.Models;

namespace TestMVCApp.Controllers
{
    public class HomeController : Controller
    {
        private RestClient client = new RestClient("http://localhost:2154/");
        // GET: Home
        public ActionResult Index()
        {
            string uriGet = "api/Company?pageIndex=1&pageSize=5";
            string json = JObject.Parse(client.Get(uriGet))["Data"].ToString();
            string count = JObject.Parse(json)["PageTotalCount"].ToString();
            string emp = JObject.Parse(json)["EmpList"].ToString();
            List<EmpView> empList = JsonConvert.DeserializeObject<List<EmpView>>(emp);
            EmpData ed = new EmpData();
            ed.PageTotalCount = int.Parse(count);
            ed.EmpList = empList;
            return View(ed);
        }
    }
}

TestMVCApp.Controllers

@{
    Layout = null;
}
@model TestMVCApp.Models.EmpData
<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <link href="~/Content/bootstrap.min.css" rel="stylesheet" />
    <script src="~/Scripts/jquery-1.9.1.min.js"></script>
    <script src="~/Scripts/bootstrap.min.js"></script>
    <title>Index</title>
    <script type="text/javascript">
        $(function () {
            $("#btn").click(function () {
                $.get("http://localhost:2154/api/conpany?pageIndex=" + $("#pageIndex").val() + "&pageSize=" + $("#pageSize").val(),
                    {},
                    function (data) {
                        $("#empBody tr").remove();
                        var json = data.Data
                        var empList = $.parseJSON(json.EmpList)
                        $.each(empList, function (i, item) {
                            $("#empBody").append("<tr><td>"
                                +item.Name+"</td><td>"
                                + item.Number + "</td><td>"
                                + item.DepName + "</td><td>"
                                + item.Gender + "</td><td>"
                                + item.Age + "</td><td>"
                                + item.Telephone + "</td><td>"
                                + item.Salary + "</td><td>"
                                + item.Job + "</td><td>"
                                +item.EntryTime+
                                "</td></tr>")
                        })
                    })
            })
        })
    </script>
</head>
<body>
    <div>
        <table id="empList" class="table">
            <thead>
                <tr>
                    <td>姓名</td>
                    <td>编号</td>
                    <td>部门</td>
                    <td>性别</td>
                    <td>年龄</td>
                    <td>电话</td>
                    <td>工资</td>
                    <td>职位</td>
                    <td>入职时间</td>
                </tr>
            </thead>
            <tbody id="empBody">
                @foreach(var item in Model.EmpList)
                {
                    <tr>
                        <td> @item.Name</td>
                        <td> @item.Number</td>
                        <td> @item.DepName</td>
                        <td> @item.Gender</td>
                        <td> @item.Age</td>
                        <td> @item.Telephone</td>
                        <td> @item.Salary</td>
                        <td> @item.Job</td>
                        <td> @item.EntryTime</td>
                    </tr>
                }
            </tbody>
        </table>

        <input id="pageIndex" type="text" /><input type="text" id="pageSize" />
        <button id="btn">GO</button>
    </div>
</body>
</html>

View

用控制台也测试了一下的

namespace TestConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            RestClient client = new RestClient("http://localhost:2154/");
            string uriGet = "api/Company?pageIndex=1&pageSize=6";
            JObject data =(JObject)JObject.Parse( client.Get(uriGet))["Data"];
            string ed = data.ToString();
            string count = data["PageTotalCount"].ToString();
            List<EmpView> list = JsonConvert.DeserializeObject<List<EmpView>>(data["EmpList"].ToString());
            Console.WriteLine(count);
            Console.WriteLine(list.Count);
            Console.WriteLine(ed);
            Console.ReadKey();
        }
    }
}

TestConsoleApp

其实那个MVC要不要都行,对于这个简单的需求来说,完全可以一个html页面用JQ的异步请求页就可以完成。我靠,几乎全部都没写注释,过段时间估计我自己都理解不了的。看来写注释是很有必要的啊。ASP.NET WEBAPI相对WCF来说还是简单多了,对于简单的应用完全可取代MVC的控制器了嘛,感觉用WEBAPI加JS(JQ)才是真正的MVC啊

ASP.NET WEBAPI 简单CURD综合测试(asp.net MVC,json.net,sql基础存储过程和视图,sqlhelper,json解析)的更多相关文章

  1. ASP.NET WebApi 简单记录

    //获取当前提交过来的Request对象 var request = System.Web.HttpContext.Current.Request;

  2. 路由其实也可以很简单-------Asp.net WebAPI学习笔记(一) ASP.NET WebApi技术从入门到实战演练 C#面向服务WebService从入门到精通 DataTable与List<T>相互转换

    路由其实也可以很简单-------Asp.net WebAPI学习笔记(一)   MVC也好,WebAPI也好,据我所知,有部分人是因为复杂的路由,而不想去学的.曾经见过一位程序猿,在他MVC程序中, ...

  3. 细说Asp.Net WebAPI消息处理管道

    我们在开发完Asp.Net WebAPI程序后,可以使用WebHost寄宿方式或者SelfHost寄宿方式来部署Asp.Net WebAPI.所谓WebHost寄宿就是通过Asp.Net来实现:所谓S ...

  4. Asp.Net WebApi+Microsoft.AspNet.WebApi.Core 启用CORS跨域访问

    WebApi中启用CORS跨域访问 1.安装 Nugget包Microsoft.AspNet.WebApi.Cors This package contains the components to e ...

  5. ASP.NET WebApi技术从入门到实战演练

    一.课程介绍 曾经有一位不知名的讲师说过这么一句名言: 一门RPC技术不会,那么千万万门RPC技术将都不会!在今天移动互联网的时代,作为攻城师的我们,谁不想着只写一套API就可以让我们的Web, An ...

  6. Asp.Net WebAPI及相关技术介绍(含PPT下载)

    此PPT讲述了Asp.Net WebAPI及相关Web服务技术发展历史. 共80多页,Asp.Net WebAPI在讲到第36页的时候才会出现,因为这个技术不是凭空产生的,它有着自己的演变进化的历史. ...

  7. abp(net core)+easyui+efcore实现仓储管理系统——使用 WEBAPI实现CURD (十三)

    abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统——ABP总体介绍(一) abp(net core)+ ...

  8. 使用ASP.Net WebAPI构建REST服务(一)——简单的示例

    由于给予REST的Web服务非常简单易用,它越来越成为企业后端服务集成的首选方法.本文这里介绍一下如何通过微软的Asp.Net WebAPI快速构建REST-ful 服务. 首先创建一个Asp.Net ...

  9. Asp.Net WebApi核心对象解析(下篇)

    在接着写Asp.Net WebApi核心对象解析(下篇)之前,还是一如既往的扯扯淡,元旦刚过,整个人还是处于晕的状态,一大早就来处理系统BUG,简直是坑爹(好在没让我元旦赶过来该BUG),队友挖的坑, ...

随机推荐

  1. nodeJS代码实现计算交社保是否合适

    本文通过nodejs的一个具体示例来对比分析现阶段我们交社保合不合适, 主要是对nodejs的一个小的应用,当然大家也可以改成其他语言的,程序猿们,来算算吧. 按一个普通程序员8000的月收入算就是1 ...

  2. Spring 整合 Redis(二)

    pom构建: <modelVersion>4.0.0</modelVersion> <groupId>com.x.redis</groupId> < ...

  3. [MetroUI-1]无边框模式

    Wpf中取消边框,使用 WindowStyle="None" AllowsTransparency="True"

  4. Hibernate中主键生成策略

    主键生成策略 increment identity sequence native uuid assigned 1) increment 由hibernate完成 主键递增, 原理:select ma ...

  5. Odoo attrs X2many 类型的过滤

    有童鞋在群里问到 attrs 中的 many2many类型的字段该如何进行domain过滤,其实非常简单: Many2many的字段在js中获取的值的格式为[[6,false,[]]] 所以attrs ...

  6. Centos 安装了 Wkhtmltopdf 却依旧显示 无法打印pdf

    Odoo里判断wkhtmlpdf是否安装的代码在 openerp/tools/misc.py 文件中: def find_in_path(name): path = os.environ.get('P ...

  7. html5学习小结,float练习。

    经过两天的H5学习之后,做了一下float属性的练习,要做出来的效果为: 下面为代码部分,所用到的知识不多,不过才现在刚开始,以后要学的东西还有很多,大家继续加油! <!DOCTYPE html ...

  8. redis发布订阅

    命令 : redis-cli打开一个客户端 Redis Psubscribe 命令订阅一个或多个符合给定模式的频道. 每个模式以 * 作为匹配符,比如 it* 匹配所有以 it 开头的频道( it.n ...

  9. JavaScript实现省市级联效果实例

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...

  10. pt-table-checksum使用实践

    在工作中接触最多的就是mysql replication,由于现在公司也还在使用mysql 5.1.x版本,在复制方面还是比较多的问题,比如主库宕机或者从库宕机都会导致复制中断,通常我们需要进行人为修 ...