Asp.net WebApi 项目示例(增删改查)

2023-05-16

1.WebApi是什么

       ASP.NET Web API 是一种框架,用于轻松构建可以由多种客户端(包括浏览器和移动设备)访问的 HTTP 服务。ASP.NET Web API 是一种用于在 .NET Framework 上构建 RESTful 应用程序的理想平台。

    可以把WebApi看成Asp.Net项目类型中的一种,其他项目类型诸如我们熟知的WebForm项目,Windows窗体项目,控制台应用程序等。

    WebApi类型项目的最大优势就是,开发者再也不用担心客户端和服务器之间传输的数据的序列化和反序列化问题,因为WebApi是强类型的,可以自动进行序列化和反序列化,一会儿项目中会见到。

    下面我们建立了一个WebApi类型的项目,项目中对产品Product进行增删改查,Product的数据存放在List<>列表(即内存)中。

2.页面运行效果


如图所示,可以添加一条记录; 输入记录的Id,查询出该记录的其它信息; 修改该Id的记录; 删除该Id的记录。

3.二话不说,开始建项目

1)新建一个“ASP.NET MVC 4 Web 应用程序”项目,命名为“ProductStore”,点击确定,如图


2)选择模板“Web API”,点击确定,如图


3)和MVC类型的项目相似,构建程序的过程是先建立数据模型(Model)用于存取数据,

     再建立控制器层(Controller)用于处理发来的Http请求,最后构造显示层(View)用于

     接收用户的输入和用户进行直接交互。


     这里我们先在Models文件夹中建立产品Product类: Product.cs,如下:

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

namespace ProductStore.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Category { get; set; }
        public decimal Price { get; set; }
    }
}

4)试想,我们目前只有一个Product类型的对象,我们要编写一个类对其实现增删改查,以后我们可能会增加其他的类型的对象,再需要编写一个对新类型的对象进行增删改查的类,为了便于 拓展和调用,我们在Product之上构造一个接口,使这个接口约定增删改查的方法名称和参数,所以我们在Models文件夹中新建一个接口:  IProductRepository.cs ,如下:

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

namespace ProductStore.Models
{
    interface IProductRepository
    {
        IEnumerable<Product> GetAll();
        Product Get(int id);
        Product Add(Product item);
        void Remove(int id);
        bool Update(Product item);
    }
}
5)然后,我们实现这个接口,在Models文件夹中新建一个类,具体针对Product类型的对象进行增删改查存取数据,并在该类的构造方法中,向List<Product>列表中存入几条数据,这个类叫:ProductRepository.cs,如下:

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

namespace ProductStore.Models
{
    public class ProductRepository:IProductRepository
    {
        private List<Product> products = new List<Product>();
        private int _nextId = 1;
        public ProductRepository()
        {
            Add(new Product { Name="Tomato soup",Category="Groceries",Price=1.39M});
            Add(new Product { Name="Yo-yo",Category="Toys",Price=3.75M});
            Add(new Product { Name = "Hammer", Category = "Hardware", Price = 16.99M });
        }


        public IEnumerable<Product> GetAll()
        {
            return products;
        }

        public Product Get(int id)
        {
            return products.Find(p=>p.Id==id);
        }

        public Product Add(Product item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            item.Id = _nextId++;
            products.Add(item);
            return item;
        }

        public void Remove(int id)
        {
            products.RemoveAll(p=>p.Id==id);
        }

        public bool Update(Product item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }
            int index = products.FindIndex(p=>p.Id==item.Id);
            if (index == -1)
            {
                return false;
            }
            products.RemoveAt(index);
            products.Add(item);
            return true;
        }
    }
}

    此时,Model层就构建好了。

6)下面,我们要构建Controller层,在此之前,先回顾一下Http中几种请求类型,如下


     get  类型  用于从服务器端获取数据,且不应该对服务器端有任何操作和影响

     post 类型  用于发送数据到服务器端,创建一条新的数据,对服务器端产生影响

     put 类型  用于向服务器端更新一条数据,对服务器端产生影响 (也可创建一条新的数据但不推荐这样用)

     delete 类型 用于删除一条数据,对服务器端产生影响


     这样,四种请求类型刚好可对应于对数据的 查询,添加,修改,删除。WebApi也推荐如此使用。在WebApi

项目中,我们请求的不再是一个具体页面,而是各个控制器中的方法(控制器也是一种类,默认放在Controllers

文件夹中)。下面我们将要建立一个ProductController.cs控制器类,其中的方法都是以“Get Post Put Delete”中

的任一一个开头的,这样的开头使得Get类型的请求发送给以Get开头的方法去处理,Post类型的请求交给Post开头的方法去处理,Put和Delete同理。

    而以Get开头的方法有好几个也是可以的,此时如何区分到底交给哪个方法执行呢?这就取决于Get开头的方法们的传入参数了,一会儿在代码中可以分辨。

   构建Controller层,
在Controllers文件夹中建立一个ProductController.cs控制器类,如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using ProductStore.Models;
using System.Web.Http;
using System.Net;
using System.Net.Http;

namespace ProductStore.Controllers
{
    public class ProductsController : ApiController
    {
        static readonly IProductRepository repository = new ProductRepository();

        //GET:  /api/products
        public IEnumerable<Product> GetAllProducts()
        {
            return repository.GetAll();
        }

        //GET: /api/products/id
        public Product GetProduct(int id)
        {
            Product item = repository.Get(id);
            if (item == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);            
            }
            return item;
        }

        //GET: /api/products?category=category
        public IEnumerable<Product> GetProductsByCategory(string category)
        {
            return repository.GetAll().Where(p=>string.Equals(p.Category,category,StringComparison.OrdinalIgnoreCase));
        }

        //POST: /api/products
        public HttpResponseMessage PostProduct(Product item)
        {
            item = repository.Add(item);

            var response = Request.CreateResponse<Product>(HttpStatusCode.Created,item);
            string uri = Url.Link("DefaultApi", new { id=item.Id});
            response.Headers.Location = new Uri(uri);

            return response;
        }

        //PUT: /api/products/id
        public void PutProduct(int id, Product product)
        {
            product.Id = id;
            if (!repository.Update(product))
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
        }

        //Delete: /api/products/id
        public void DeleteProduct(int id)
        {
            Product item = repository.Get(id);
            if (item == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
            repository.Remove(id);
        }
    }
}

    使该类继承于ApiController类,在其中实现处理各种Get,Post,Put,Delete类型Http请求的方法。

每一个方法前都有一句注释,标识了该方法的针对的请求的类型(取决于方法的开头),以及

要请求到该方法,需要使用的url。

 这些url是有规律的,见下图:


api是必须的,products对应的是ProductsControllers控制器,然后又Http请求的类型和url的

后边地址决定。

这里,我们除了第三个“Get a product by category”,其他方法都实现了。

7)最后,我们来构建View视图层,我们更改Views文件夹中的Home文件夹下的Index.cshtml文件,

这个文件是项目启动页,如下:

<div id="body">
    <script src="~/Scripts/jquery-1.8.2.min.js"></script>
    <section >
          <h2>添加记录</h2>
          Name:<input id="name" type="text" /><br />
          Category:<input id="category" type="text" />
          Price:<input id="price" type="text" /><br />
          <input id="addItem" type="button" value="添加" />
    </section>

    <section>
        <br />
        <br />
          <h2>修改记录</h2>
          Id:<input id="id2" type="text" /><br />
          Name:<input id="name2" type="text" /><br />
          Category:<input id="category2" type="text" />
          Price:<input id="price2" type="text" /><br />
          <input id="showItem" type="button" value="查询" />
          <input id="editItem" type="button" value="修改" />
          <input id="removeItem" type="button" value="删除" />
    </section>

</div>

8)然后我们给页面添加js代码,对应上面的按钮事件,用来发起Http请求,如下:

  <script>
        //用于保存用户输入数据
        var Product = {
            create: function () {
                Id: "";
                Name: "";
                Category: "";
                Price: "";
                return Product;
            }
        }

        //添加一条记录 请求类型:POST  请求url:  /api/Products  
        //请求到ProductsController.cs中的 public HttpResponseMessage PostProduct(Product item) 方法
        $("#addItem").click(function () {
            var newProduct = Product.create();
            newProduct.Name = $("#name").val();
            newProduct.Category = $("#category").val();
            newProduct.Price = $("#price").val();

            $.ajax({
                url: "/api/Products",
                type: "POST",
                contentType: "application/json; charset=utf-8",
                data: JSON.stringify(newProduct),
                success: function () {
                    alert("添加成功!");
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    alert("请求失败,消息:" + textStatus + "  " + errorThrown);
                }
            });
        });

        //先根据Id查询记录  请求类型:GET  请求url:  /api/Products/Id  
        //请求到ProductsController.cs中的 public Product GetProduct(int id) 方法
        $("#showItem").click(function () {
            var inputId = $("#id2").val();
            $("#name2").val("");
            $("#category2").val("");
            $("#price2").val("");
            $.ajax({
                url: "/api/Products/" + inputId,
                type: "GET",
                contentType: "application/json; charset=urf-8",
                success: function (data) {
                    $("#name2").val(data.Name);
                    $("#category2").val(data.Category);
                    $("#price2").val(data.Price);
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    alert("请求失败,消息:" + textStatus + "  " + errorThrown);
                }
            });
        });

        //修改该Id的记录 请求类型:PUT  请求url:  /api/Products/Id  
        //请求到ProductsController.cs中的 public void PutProduct(int id, Product product) 方法
        $("#editItem").click(function () {
            var inputId = $("#id2").val();
            var newProduct = Product.create();
            newProduct.Name = $("#name2").val();
            newProduct.Category = $("#category2").val();
            newProduct.Price = $("#price2").val();

            $.ajax({
                url: "/api/Products/" + inputId,
                type: "PUT",
                data: JSON.stringify(newProduct), 
                contentType: "application/json; charset=urf-8",
                success: function () {
                    alert("修改成功! ");
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    alert("请求失败,消息:" + textStatus + "  " + errorThrown);
                }
            });
        });

        //删除输入Id的记录  请求类型:DELETE  请求url:  /api/Products/Id  
        //请求到ProductsController.cs中的  public void DeleteProduct(int id) 方法
        $("#removeItem").click(function () {
            var inputId = $("#id2").val();
            $.ajax({
                url: "/api/Products/" + inputId,
                type: "DELETE",
                contentType: "application/json; charset=uft-8",
                success: function (data) {                   
                        alert("Id为 " + inputId + " 的记录删除成功!");
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    alert("请求失败,消息:" + textStatus + "  " + errorThrown);
                }
            });
        });
    </script>

    这里,WebApi的一个简单的增删改查项目就完成了,选择执行项目即可测试。注意到,其中用ajax发起请求时,

发送到服务器端的数据直接是一个json字符串,当然这个json字符串中每个字段要和Product.cs类中的每个字段同名对应,在服务器端接收数据的时候,我们并没有对接收到的数据进行序列化,而返回数据给客户端的时候也并没有对数据进行反序列化,大大节省了以前开发中不停地进行序列化和反序列化的时间。



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Asp.net WebApi 项目示例(增删改查) 的相关文章

  • PHP实现上一页下一页翻页代码实例

    lt php 1 xff0c 将数据库的所有记录查询出来 xff0c 然后再一页一页的显示 link 61 mysql connect 39 localhost 39 39 root 39 39 123 39 mysql select db
  • QT项目升级(QT4.6.3到QT5.2)时,遇到的问题和解决方法

    QT4 升级到 QT5 改动 PC部分 xff1a 改 QTDIR 变量 在工程根目录下找到 user 文件 如 InnoTabPlugin vcxproj user 修改指向你的 QT5 根目录 xff1a lt PropertyGrou
  • c++中ifstream一次读取整个文件

    c 43 43 中一次读取整个文件的内容的方法 xff1a 1 读取至char 的情况 cpp view plain copy std ifstream t int length t open 34 file txt 34 open inp
  • webkit/chromuim/CEF3介绍

    一 浏览器主要构成 浏览器的主要构成High Level Structure 浏览器的主要组件包括 xff1a 1 用户界面 xff0d 包括地址栏 后退 前进按钮 书签目录等 xff0c 也就是你所看到的除了用来显示你所请求页面的主窗口之
  • python多文件使用同一个全局变量的定义和使用方法

    Python是一种面向对象的开发语言 xff0c 在函数中使用全局变量 xff0c 一般应作全局变量说明 xff0c 只有在函数内经过说明的全局变量才能使用 xff0c 下面介绍下Python全局变量有关问题 应该尽量避免使用Python全
  • D3VO 2020CVPR论文阅读

    Deep Depth Deep Pose and Deep Uncertainty for Monocular Visual Odometry 论文链接 摘要 xff1a 提出的D3VO单目视觉里程计框架从三个层面上利用了深度学习网络 xf
  • python在windows下获取cpu、硬盘、bios、主板序列号

    此处使用的是wmi库 xff0c 可以去google里面搜索 python wmi import os sys import time import wmi zlib def get cpu info tmpdict 61 tmpdict
  • gcc中调试代码常用的宏

    红色是比较常用的 宏 意义 FILE 本文件名 LINE 本行位于该文件的第几行 FUNCTION 函数名 PRETTY FUNCTION c语言中和同上 xff0c C 43 43 中稍有区别 VA ARGS 格式化输出 VA ARGS
  • Qt基础学习(5)-----抽屉效果之QToolBox

    cpp view plain copy print mydialog h ifndef MYDIALOG H define MYDIALOG H include lt QDialog gt class QToolBox class MyDi
  • linux下c语言抓包库libpcap

    安装命令 xff1a sudo apt get install libpcap dev 由于自己还没仔细研究过 xff0c 暂时也只是想在这里留个记录 xff0c 方便以后需要时使用 下面是百度百科里的例子 include lt pcap
  • scons简易手册

    在编译大程序时免不了要写个makefile来管理 xff0c 但是makefile的规则对于大多数人来说都还太复杂了 于是我找到了autotools工具 xff0c 尽管方便了一些 xff0c 但是还是不够傻瓜 目前scons是我用过最傻瓜
  • Round-Robin负载均衡算法及其实现原理

    第一次在pjsip协议栈中了解到这个实习负载均衡的机制 于是网上查了下资料 xff0c 下面的介绍应该可以很容易理解 轮询调度算法 Round Robin Scheduling 轮询调度算法的原理是每一次把来自用户的请求轮流分配给内部中的服
  • tipc协议详解

    TIPC协议和实现解析 1 TIPC简介TIPC是爱立信公司提出的一种透明进程间通信协议 主要适用于高可用 HAL 和动态集群环境 该软件当前主要由风河 windriver 公司在维护 主要支持Linux Solaris 和 VxWorks
  • python循环方法总结

    1 for循环 语法 xff1a for x in range xff08 100 xff09 补充 xff1a rang xff08 100 xff09 xff1a 数据范围0 99 range xff08 1 xff0c 100 xff
  • Ftp 线程池方式 解决多线程问题

    FTP 线程池 方式 解决多线程问题 1 pom xml中添加依赖 lt ftp gt lt dependency gt lt groupId gt commons net lt groupId gt lt artifactId gt co
  • cannot connect to X server localhost:10.0

    使用SSH连接服务器时 xff0c 打开图形界面 xff0c 若报错 xff1a cannot connect to X server localhost 10 0 可以通过如下设置 xff0c 显示图形界面 xff1a export DI
  • 【VPS + ORB-SLAM2】多人使用手机协同操作调研思考

    1 ORB SLAM3 43 深度学习开源调研 ORB SLAM3 with Docker xff1a https github com petrikvladimir orbslam3 docker 特点 xff1a ORB SLAM3 w
  • 最极致Windows仿Mac2.0【win11可用】——30分钟完成(W001)

    本文原创 禁止转载 2021年12月26日2 0 更新兼容性及bug修复 加图 2022年6月 更改邮箱 2022年12月 投放下载链接 2023年4月16日 更新链接 添加联系方式 喜欢的点个赞再拿走啊啊啊 不看消息 有问题加QQ群 群号
  • 简单介绍阿里内部工具——Arthas

    在阿里巴巴内部 xff0c 有很多自研工具供开发者使用 xff0c 其中有一款工具 xff0c 是几乎每个Java开发都使用过的工具 xff0c 那就是Arthas xff0c 这是一款Java诊断工具 xff0c 是一款牛逼带闪电的工具
  • gstreamer移植qnx(二):交叉编译glib

    一 简介 这里以glib的2 63 0版本 xff0c QNX系统的版本是 xff1a 6 6 这里是为了编译gstreamer的依赖库 xff0c 也就是说最终目标 xff0c 是将gstreamer移植到QNX6 6系统上 我选择的是g

随机推荐

  • repo安装与简单使用

    一 概述 当一个大的项目需要拆分成很多的子项目 xff0c 或者说一个软件系统拆分成多个子系统 每一个子项目或者子系统都对应一个git repository 这种需求在实际项目当中是很常见的 xff0c 有的可能就直接写一个shell脚本来
  • 通过qemu-img命令将raw image转换成VMware虚拟硬盘vmdk

    为了在VMware中跑QNX系统 xff0c 我需要想办法将编译BSP生成的img文件固化到VMware的虚拟硬盘中去 xff0c 之前一直找不到方法 xff0c 到渐渐的只能用很笨的方法几次中专 将生成的img文件通过win32DiskI
  • WSL2 Ubuntu安装Qt(包括QtCreator)

    最近因为需要在Linux下使用qtcreator做一些界面开发的预研和学习 xff0c 主要是因为要交叉编译Qt 但又不想再使用虚拟机了 xff0c 真的太消耗内存了 于是就想着直接使用Windows10 下面的WSL2 怎么安装WSL2这
  • 架构师成长之路工具篇(1):markdown撰写文档

    今天笔者想说的工具就是markdown xff0c 正所谓工欲善其事必先利其器 xff0c 选择高效的工具自然能提升工作效率 笔者使用的markdown工具是 xff1a typora word太重 xff0c 太复杂 xff0c 在写文档
  • 如何优雅的退出qemu虚拟环境

    在console环境下 xff0c 先 按 ctrl 43 a xff0c 释放之后再按 x 键 既可terminate qemu 注 xff1a 1 a 和 x 均为小写 2 必须先释放ctrl 43 a 之后 再按x键
  • xmake经验总结1:解决c++ future/promise抛出std::system_error的问题

    1 背景 1 1 场景 编译器 xff1a gcc 9 4 运行系统 xff1a Ubuntu 20 04 4 LTS xmake v2 6 7 场景 xff1a 其大致场景是使用c 43 43 的future promise功能 xff0
  • 神经网络实现手写数字识别(MNIST)

    一 缘起 原本想沿着 传统递归算法实现迷宫游戏 gt 遗传算法实现迷宫游戏 gt 神经网络实现迷宫游戏的思路 xff0c 在本篇当中也写如何使用神经网络实现迷宫的 xff0c 但是研究了一下 xff0c 感觉有些麻烦不太好弄 xff0c 所
  • 【AI】Auto-GPT:当时代抛弃你的时候,不会和你说一声再见!

    当时代抛弃你的时候 xff0c 不会和你说一声再见 xff01 Auto GPT Code Auto GPT 一个全自动化的GPT 4 Collecting BOTAI Auto GPT 官网网站
  • 解决visio对象在word中显示不全的问题

    作为一个软件工程师 xff0c 编写技术文档是常有的事情 xff0c 使用visio绘制各种图形 如 xff0c 流程图 xff0c 结构图 xff0c 框架图 xff0c 状态图等等 也是再正常不过的事情 如果我们在word中撰写文档时
  • git submodule使用以及注意事项

    一 背景 在平时的软件开发过程中常常会有这样的场景 xff0c 自己负责的某个模块会依赖其他模块或者第三方的library 这时你自己的模块是一个独立的代码仓库 xff0c 你想要实现这样一种功能 xff0c 当你从你的模块的代码仓库里把代
  • Webpack5 - 基本使用

    一 webpack有何作用 webpack是一个Javascript应用程序的模块打包器 它可以递归地构建一个应用程序的模块依赖关系图 xff0c 然后将所有模块打包在一起 为什么需要模块打包器 xff1a 现在的应用程序模块文件很多 xf
  • Vue.js - VueRouter的Hash与History模式 / 手写VueRouter

    一 Hash与History模式 Hash模式History模式url地址外观http localhost 8081 abouthttp localhost 8080 about原理基于锚点 xff0c 监听锚点变化时触发的onhashch
  • Vue.js - Vue.js响应式原理(1/2)

    一 数据驱动 数据响应式 xff1a 数据改变 xff0c 则视图改变 xff0c 避免频繁的Dom操作 xff0c 提高运行效率 双向绑定 xff1a 数据改变 xff0c 则视图改变 xff1b 视图改变 xff0c 则数据也随之改变
  • Vue.js - 模拟Vue.js响应式原理(2/2)

    项目仓库 xff1a https gitee com big right right vue responsive tree master L8 一 类的说明 Vue类 xff1a 保存传入的选项数据 xff0c 把选项data中的成员注入
  • .NET用NCO连接SAP RFC---写数据到SAP

    1 环境 xff1a a win7 43 64位操作系统 b VS2012 c nco3 0 xff08 64bit 下载网址 xff1a http www dllbang com dll sapnco dll xff09 xff0c d
  • .NET Framwork,C#入门开发教程,零基础必看

    初识 NET Framwork和开发过程 一 什么是 NET Framework NETFramework是一个开发平台 xff0c 可以在其上使用多种语言开发程序 xff1a 如C xff0c VB xff0c C 43 43 xff08
  • 如何清除IIS缓存

    问题描述 xff1a 在IIS的默认网站下创建了一个虚拟目录名A xff0c 然后删除这个虚拟目录 后来需要重新创建一个同名虚拟目录 xff0c 映射的还是原来的项目文件 xff0c 只是项目文件的物理路径发生了变化 xff0c 这个新虚拟
  • jqGrid 多选复选框 编辑列

    1 首先看一下效果 2 html代码 lt table id 61 34 grid table 34 gt lt table gt 3 在 function 方法中 xff0c 写如下方法 xff0c 用json数据填充jqGrid xff
  • 【NERF】及其变种

    CVPR 2023 Interactive Segmentation of Radiance Fields Nerf重建加上选中分割 Nerf 调研
  • Asp.net WebApi 项目示例(增删改查)

    1 WebApi是什么 ASP NET Web API 是一种框架 xff0c 用于轻松构建可以由多种客户端 xff08 包括浏览器和移动设备 xff09 访问的 HTTP 服务 ASP NET Web API 是一种用于在 NET Fra