6.3 ASP.NET Core Web API技术选择

6.3 ASP.NET Core Web API技术选择

控制器父类

Controller继承自ControllerBase,只不过增加了视图相关的方法,一般mvc项目选用Controller而Web API项目选择ControllerBase即可。

操作方法的返回值和状态码

ASP.NET Core Web API中的操作方法返回值如果是普通数据类型,则返回值默认被序列化为JSON格式的响应报文体返回。

ASP.NET Core Web API也支持IActionResult<T>类型

	[Route("api/[controller]/[action]")]
    [ApiController]
    public class TestController : ControllerBase
    {
        [HttpGet("{id}")]
        public ActionResult<Person> GetPerson(int id)
        {
            if (id <= 0)
            {
                return BadRequest("id必须是正数");//继承自ACtionResult
            }
            else if (id == 1)
            {
                return new Person(1, "tom", 18);
            }
            else if (id == 2)
            {
                return new Person(2, "Zack", 8);
            }
            else
            {
                return NotFound("人员不存在");//继承自ACtionResult
            }
        }
    }

对于失败的请求,一般要统一响应报文体的格式以便在客户端进行处理。

public record ErrorInfo(int Code, string? Message);声明一个表示错误的详细信息类

其中code参数表示错误的自定义业务代码

//使用ErrorInfo改造GetPerson方法
[HttpGet("{id}")]
public ActionResult<Person> GetPerson(int id)
{
    if (id <= 0)
    {
        return BadRequest(new ErrorInfo(1,"id必须是正数"));
    }
    else if (id == 1)
    {
        return new Person(1, "tom", 18);
    }
    else if (id == 2)
    {
        return new Person(2, "Zack", 8);
    }
    else
    {
        return NotFound(new ErrorInfo(2,"人员不存在"));
    }
}
//使用BadRequest或者NotFound等可以使得错误码不一致,供开发人员调试
id返回结果
-1在这里插入图片描述
2在这里插入图片描述
9在这里插入图片描述

操作方法的参数

给服务器传递参数的时候,有URL、QueryString、请求报文体3种方式

  • 访问路径中的值

    可以在[HttpGet]、[HttpPost]等中使用占位符{}来捕捉路径中的内容。案例:

请求路径/Student/GetAll/school/MIT/class/A001

GetAll方法添加了[HttpGet("schllo/{schoolName}/class/{classNo}")]

**结果:**schoolName=MIT和classNo=A001。如果GetAll方法的参数中有和占位符名字同名的参数,那么这个参数就会被自动赋值。如果占位符名字与参数名称不一致,则使用[FromRoute]的Name属性来设置匹配的占位符的名字,例如:

[HttpGet("schllo/{schoolName}/class/{classNo}")]
public ActionResult<Student[]> GetAll(string schoolName,[FromRoute(Name="classNo")]string calssNum) //classNum的参数想获得占位符{classNo}的值
  • QueryString中的值

使用[FromQuery]来获取,如果操作方法的参数名字和QueryString的名字一致,只需要为参数添加[FromQuery],否则,就要设定[FromQuery]的name属性指定名字

//URL的QueryString为pageNum=8&pSize=10
public ActionResult<Student[]> GetAll([FromQuery]string pageNum,[FromQuery)(Name="psize")]int pageSize)
  • 混合使用
//可以处理/Student/GetAll/school/MIT/class/A001?pageNum=8&pSize=10
[HttpGet("schllo/{schoolName}/class/{classNo}")]
public ActionResult<Student[]> GetAll(string schoolName,[FromRoute(Name="classNo")]string calssNum,[FromQuery]string pageNum,[FromQuery)(Name="psize")]int pageSize)
  • 请求报文体

目前JSON是主流的请求报文体格式,本文讲JSON报文体

案例:

需求:前端浏览器向服务器发送的报文体:{“name”:“qs”,“age”:“18”}

直接声明一个Person类定义Name和age两个属性

[HttpPost]
public ActionResult AddNew(Person p)

客户端只要向/Person/AddNew提交Post提交即可

也可以从URL中获取参数、从请求报文体获取数据混合使用

[HttpPost("classId/{classId}")]
public ActionResult<long> AddNew(long classId,Person s)
//客户端只要向/Students/AddNew/classId/8,伴随报文体{“name”:"yzk","age":"18"}
//通过classId获取8,s参数则是报文体

**注意:**一定设置请求报文头中Content-Type为application/JSON

案例

public record ProcessInfo(int Id,string ProcessName,long WorkingSet64);
public record LoginResult(bool isok, ProcessInfo[]? Process);
public record LoginRequeset(string username,string password);
//Login方法用来判断请求的用户名、密码是否正确,如果正确的话服务器会返回当前计算机的所有进程信息
[Route("api/[controller]/[action]")]
[ApiController]
public class LoginController : ControllerBase
{
    [HttpPost]
    public ActionResult<LoginResult> Login(LoginRequeset loginreq)
    {
        if (loginreq.username =="admin" && loginreq.password =="123456")
        {
            var process = Process.GetProcesses().Select(p => new ProcessInfo(p.Id, p.ProcessName, p.WorkingSet64)).ToArray();
            return new LoginResult(true, process);
        }
        else
        {
            return new LoginResult(false, null);
        }
    }
}

前端页面

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>dddd</title>
</head>
<body>
    <div id="app">
        <div>
            <label>账户:</label>
            <input type="text" placeholder="账户" v-model="acount" />
            <label>账户:</label>
            <input type="password" placeholder="密码" v-model="password" />
            <button @click="queryprocess">
                搜 索
            </button>
        </div>
        <div>
            <ul>
            <li v-for="(process,index) in processarr">
               id: {{process.id}} == processName: {{process.processName}} == workingSet64: {{process.workingSet64}} 
            </li>
            </ul>
        </div>
    </div>

    <script src="./vue.js"></script>
    <script src="./axios.min.js"></script>
    <script>
        var app = new Vue({
            el: "#app",
            data: {
                processarr: [],
                acount: "",
                password: ""
            },
            methods: {
                queryprocess() {
                    var that = this;
                    axios.post("http://localhost:7285/api/Login/Login", {
                        username: this.acount,
                        password: this.password
                    }).then(res => {
                        if(!res.data.isok)
                        {
                            alert("账户密码错误!");
                            return;
                        }
                        that.processarr = res.data.process;
                        console.log(res);
                    }, err => { alert("访问出错");});
                },
            }
        });
    </script>
</body>
</html>

启动服务后,发现浏览器没有反应,这是因为前端和后端不在同一个域名下(不同的端口也认为是不同的域名),浏览器默认是禁止AJAX跨域。我们可以采用CORS方式,CORS是浏览器中标准的跨域通信方式。CORS的原理是在服务器的响应报文头文件中通过access-control-allow-origin告诉浏览器允许跨域访问的域名。

我们需要在后端项目中启用CORS,并且设定前端项目的域名。

//在项目Program.cs中的var app = builder.Build();前面加上
string[] urls = new[] { "http://127.0.0.1:5500" };//允许跨域访问的域名
builder.Services.AddCors(options =>
    options.AddDefaultPolicy(builder => builder.WithOrigins(urls)
    .AllowAnyMethod().AllowAnyHeader().AllowCredentials()));
//最后在app.UseHttpsRedirection();前面加上app.UseCors();

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
目 录 1 引言 1.1 电子商务的现状 (1) 1.2 本文研究方向 (1) 1.3 可行性分析 (2) 1.3.1 经济可行性 (2) 1.3.2 技术可行性 (2) 1.3.3 操作可行性 (2) 1.4 本文结构 (3) 2 开发工具及环境简介 2.1 SQL Server 2005 简介 (4) 2.2 ASP.NET 2.0简介 (5) 2.3 Microsoft Visual Web Developer 2005 速成版介绍 (6) 3 系统设计 3.1 系统体系结构 (7) 3.2 功能需求分析 (7) 3.3 非功能需求分析 (8) 3.4 系统结构分析 (8) 4 系统详细设计 4.1 系统功能模块设计 (9) 4.1.1 管理员模块 (9) 4.1.2 用户模块 (9) 4.2 数据库的设计 (10) 4.2.1 概念设计 (10) 4.2.2 详细设计 (10) 5 系统的实现 5.1 产品发布子系统 (12) 5.1.1 产品展示模块 (12) 5.1.2 产品管理模块 (13) 5.2 新闻发布子系统 (15) 5.2.1 新闻展示模块 (15) 5.2.2 新闻管理模块 (17) 5.3 会员子系统 (19) 5.3.1 会员功能模块 (19) 5.3.2 会员管理模块 (21) 5.4 在线订购子系统 (22) 5.4.1 在线订购模块 (22) 5.4.2 订单管理模块 (23) 5.5 其他 (24) 5.5.1 导航 (24) 5.5.2 样式控制 (24) 5.5.3 数据连接 (24) 5.5.4 数据库操作类: (25) 6. 系统测试、性能分析 6.1 环境测试 (26) 6.1.1 硬件环境 (26) 6.1.2 软件环境 (26) 6.2 主要模块测试 (26) 6.2.1 登录模块测试 (26) 6.2.2 后台管理测试 (28) 6.2.3 产品订购测试 (28) 6.3 性能分析 (29) 结 论 (30) 致 谢 (31) 参考文献 (32)
以下是使用 Python Web3 6.3 获取 UniswapV2 合约价格的示例代码: ```python from web3 import Web3 import json # 合约地址和ABI uniswapv2_address = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D" uniswapv2_abi = json.loads(''' [ { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, { "inputs": [ { "internalType": "address", "name": "tokenA", "type": "address" }, { "internalType": "address", "name": "tokenB", "type": "address" } ], "name": "getPair", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "WETH", "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], "stateMutability": "view", "type": "function" } ] ''') # 初始化 Web3 web3 = Web3(Web3.HTTPProvider("https://mainnet.infura.io/v3/your-project-id")) # 获取 UniswapV2 合约 uniswapv2_contract = web3.eth.contract(address=uniswapv2_address, abi=uniswapv2_abi) # 获取 WETH 地址 weth_address = uniswapv2_contract.functions.WETH().call() # 获取 ETH/USDT 交易对地址 eth_address = web3.toChecksumAddress("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2") usdt_address = web3.toChecksumAddress("0xdac17f958d2ee523a2206206994597c13d831ec7") eth_usdt_pair_address = uniswapv2_contract.functions.getPair(eth_address, usdt_address).call() # 获取 ETH/USDT 交易对合约 eth_usdt_pair_contract = web3.eth.contract(address=eth_usdt_pair_address, abi=uniswapv2_abi) # 获取 ETH/USDT 交易对 ETH 和 USDT 的余额 eth_balance, usdt_balance, _ = eth_usdt_pair_contract.functions.getReserves().call() # 计算 ETH/USDT 交易对价格 eth_price = usdt_balance / eth_balance print(f"ETH/USDT price: {eth_price}") ``` 请注意,此示例代码仅适用于以太坊主网。如果您使用的是其他网络,请相应地更改 Web3 提供程序的 URL。另外,请确保您拥有正确的 Infura 项目 ID。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

步、步、为营

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值