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

草图

真正的后端是不管前端是什么平台,用什么语言的,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];
            for (int i = 0, 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));
            if (cmdresult == 0)
            {
                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));
            if (cmdresult == 0)
            {
                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
select top(@size) * from (select *,ROW_NUMBER() over(order by 编号)as 行号 from EmpView)as e where e.行号>(@index-1)*@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, null).Tables[0];
            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[0].Value = index; pars[0].Direction = ParameterDirection.Input;
            pars[1].Value = size; pars[1].Direction = ParameterDirection.Input;
            pars[2].Direction = ParameterDirection.Output;
            DataTable dt = SqlHelper.GetDataSet(CommandType.StoredProcedure, sql, pars).Tables[0];
            int.TryParse(pars[2].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啊

时间: 2024-10-12 14:24:57

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

ASP.NET WebAPI --- 简单实现增删改查

先理解一下WebAPI的概念,官方给的很详细: 什么是Web API? 在我们了解什么是Web API之前,让我们看看什么是API(应用程序编程接口). 根据维基百科的API定义:在计算机编程中,应用程序编程接口(API)是一组用于构建软件和应用程序的子例程定义,协议和工具. 简单来说,API是某种接口,它具有一组允许程序员访问应用程序,操作系统或其他服务的特定功能或数据的功能. Web API顾名思义,是一个可以使用HTTP协议访问的Web上的API.这是一个概念,而不是一种技术.我们可以使用

使用ASP.Net WebAPI构建REST服务(四)——参数绑定

默认绑定方式 WebAPI把参数分成了简单类型和复杂类型: 简单类型主要包括CLR的primitive types,(int.double.bool等),系统内置的几个strcut类型(TimeSpan.Guid等)以及string.对于简单类型的参数,默认从URI中获取. 复杂类型的数据也可以直接作为参数传入进来,系统使用media-type formatter进行解析后传给服务函数.对于复杂类型,默认从正文中获取, 例如,对于如下函数 HttpResponseMessage Put(int

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

我们在开发完Asp.Net WebAPI程序后,可以使用WebHost寄宿方式或者SelfHost寄宿方式来部署Asp.Net WebAPI.所谓WebHost寄宿就是通过Asp.Net来实现:所谓SelfHost就是可以通过控制台.WinForm.WPF等方式寄宿.下面我们通过简单的例子来看看WebHost方式和SelfHost方式. 该Demo中包含一个类库项目.一个控制台项目以及一个空的WebForm项目.其中类库项目有一个继承自ApiController的名为HomeController

mongodb+asp.net webapi开放平台系列

一步一步,从未知到懵懂到…… 脚印从来没有停止过…… mongodb+asp.net webapi开放平台系列渐行渐近…… 梳理此项目中的知识点包括mongodb,asp.net webapi  oauth2 elasticsearch mvc mongodb基础知识学习 Mongodb学习笔记一(Mongodb环境配置) Mongodb学习笔记二(Mongodb基本命令) Mongodb学习笔记三(Mongodb索引操作及性能测试) Mongodb学习笔记四(Mongodb聚合函数) asp.

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

此PPT讲述了Asp.Net WebAPI及相关Web服务技术发展历史. 共80多页,Asp.Net WebAPI在讲到第36页的时候才会出现,因为这个技术不是凭空产生的,它有着自己的演变进化的历史.我们要先弄清它从哪里来的?然后再说它能做什么事. 这个PPT涉及到的技术名词有: XML-RPC,SOAP,REST, SOA Asp.Net WebForm,WebService, WCF Asp.Net WebAPI, Asp.Net MVC,JSON Asp.Net Routing, MVVM

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

由于给予REST的Web服务非常简单易用,它越来越成为企业后端服务集成的首选方法.本文这里介绍一下如何通过微软的Asp.Net WebAPI快速构建REST-ful 服务. 首先创建一个Asp.Net Web应用程序(我这里用的是Visual Studio 2013,它已经内置了Web API2). 在出来的模板中选择Empty(空项目),并勾选WebAPI.点击确定后,就创建了一个空的WebAPI服务. 此时只有一个空项目,还没有任何功能,在进行下一步之前,首先我们来看一下REST的基本操作模

[简约webAPI]分别以asp|jsp|php简单粗暴实现webAPI,输出json数据

原本打算使用golang编写一个RESTful API,但因为环境所限,此次采用“偷懒的方式”,其实也不算偷懒,至少编写代码上面没有偷懒,只是在部署上偷懒了,三台机器物理地址以及公网地址均不同,说白了就是这三玩意儿没在一块,嘛都没在,好嘛,服务器环境也均然不同,分别为asp.java.php编写部署的系统. 既然都是脚本语言,那就暴力解决此次问题,灵活性毕竟很高嘛. ASP+sqlServer 废话不多说上代码 <%@LANGUAGE="VBSCRIPT" CODEPAGE=&q

ASP.NET WebAPI 08 Message,HttpConfiguration,DependencyResolver

Message WebAPI作为通信架构必定包含包含请求与响应两个方法上的报文,在WebAPI它们分别是HttpRequestMessage,HttpResponseMessage.对于HttpResponseMessage之前在WebAPI返回结果中有应用. HttpRequestMessage 请求报文包含请求地址(RequestUri),请求方法(Method),头信息(Headers),报文信息(Content)以及Http版本(Versions) public class HttpRe

使用ASP.Net WebAPI构建REST服务(六)——Self-Host

Asp.Net WebAPI生成的是一个程序集,并不是独立的进程,因此,要运行的时候必须将其承载在相应的宿主上,一般比较常见的是IIS承载.很多时候,我们为了简化部署或者功能集成,需要将其承载到独立的进程上,这种方式一般称之为Self-Host,本文就简单的介绍一下WebAPI的SefHost方法. 首先在Nuget上安装Microsoft.AspNet.WebApi.SelfHost库. 附上我们的WebAPI控制器 publicclassValuesController : ApiContr