本文代码仓库地址: gitee码云CSDN笔记仓库地址
先说一下爬的坑,真的就是被我自己蠢到了
一、自己写的接口出现404的情况
- 对于自己独自研究,接触C#没多久,没有人问,不懂只能度娘的我来说,被自己的操作闪了腰
- 跟前面写的接口相比,没有什么区别啊,就是一个是静态的一个不是静态的(当时没有这个想法,感觉静态不静态都可以调用吧),当时就因为忽略了这个问题,一直卡在上面,一直找别的问题,昨天因为这个问题搞了好久,还没有答案,睡一觉今天早上来了之后5分钟解决了。我。。。。!!!
- 是因为 C# 中接口不能调用静态方法。
- 接口除了可以包括方法外,还可以包括事件,属性,因为他们都会映射为方法!实际上CLR(公共语言运行时)还允许接口包括静态方法,静态字段,常数,以及静态构造器,这和接口的语义并没有矛盾!但是CLS(通用语言规范)不允许接口有静态成员,因为某些语言不能定义和访问静态成员,这就给语言之间的交互带来问题!所以C#编译器不允许接口包括静态成员!
错误代码:
/// <summary>
/// 类似购物车
/// </summary>
/// <param name="cityname">城市名</param>
/// <param name="count">添加数量</param>
/// <returns>几行受影响</returns>
public static int AddCart(string cityname, string count)
{
// 用这种方法也是可以接收前端 get 过来在地址栏的参数
/* API地址:https://localhost:44361/api/StudyCore/AddCart */
int rows = ShoppingCarts.AddCart(cityname, count);
return rows;
}
正确代码:
/// <summary>
/// 类似购物车
/// </summary>
/// <param name="cityname">城市名</param>
/// <param name="count">添加数量</param>
/// <returns>几行受影响</returns>
public int AddCart(string cityname, string count)
{
// 用这种方法也是可以接收前端 get 过来在地址栏的参数
/* API地址:https://localhost:44361/api/StudyCore/AddCart */
int rows = ShoppingCarts.AddCart(cityname, count);
return rows;
}
二、vue是使用 this.$router.push("/AddSuccess");
的蠢
- 不管是度娘还是看的教程上面都是用的
push()
可以跳转页面的- 可能是我当时眼瞎,并且手、心不一,导致,表示傻傻的没有使用cv大法,因为就4个字母,然后我心里面一直想的是
push
,嘴上念的也是push
然后 手:“看我的~”
puch- 注意:这里我输入的
,不是
puchpush
提示的错误是不存在这个函数,出现这种情况先看一下是不是自己的单词写错了
正确代码:
ClickAdd(){
var thisVue02 = this;
this.$http.get("https://localhost:44361/api/StudyCore/AddCart?cityname="+this.ssCity.scity+"&count="+this.count).then((res02)=>{
if(res02.data > 0){
thisVue02.$router.push("/AddSuccess");
// alert("进来了");
}
})
}
下面正式的代码,继上篇 C# 基础之前后端分离【01】 之后
前端代码:
Demo_y01.vue内容: 添加了跳转内容
<template>
<!-- 至于为什么写在 template 里面不是很清楚,参照HelloWorld.vue 文件里面的来的 -->
<div>
Hello 小印丶
<div class="class01">
<input type="text" id="id01">
<button id="id02">搜索</button>
</div>
<hr id="id03">
<div id="id04">
<ul>
<li>
<img src="/static/demo_image/k30至尊.jpg" alt="Redmi K30 至尊纪念版">
<p class="class02">¥1999</p>
<p>Redmi K30 至尊纪念版</p>
</li>
<li>
<img src="/static/demo_image/k30至尊.jpg" alt="Redmi K30 至尊纪念版">
<p class="class02">¥1999</p>
<p>Redmi K30 至尊纪念版</p>
</li>
<li>
<img src="/static/demo_image/k30至尊.jpg" alt="Redmi K30 至尊纪念版">
<p class="class02">¥1999</p>
<p>Redmi K30 至尊纪念版</p>
</li>
<li>
<img src="/static/demo_image/k30至尊.jpg" alt="Redmi K30 至尊纪念版">
<p class="class02">¥1999</p>
<p>Redmi K30 至尊纪念版</p>
</li>
<li>
<img src="/static/demo_image/k30至尊.jpg" alt="Redmi K30 至尊纪念版">
<p class="class02">¥1999</p>
<p>Redmi K30 至尊纪念版</p>
</li>
<li>
<img src="/static/demo_image/k30至尊.jpg" alt="Redmi K30 至尊纪念版">
<p class="class02">¥1999</p>
<p>Redmi K30 至尊纪念版</p>
</li>
<li>
<img src="/static/demo_image/k30至尊.jpg" alt="Redmi K30 至尊纪念版">
<p class="class02">¥1999</p>
<p>Redmi K30 至尊纪念版</p>
</li>
<li>
<img src="/static/demo_image/k30至尊.jpg" alt="Redmi K30 至尊纪念版">
<p class="class02">¥1999</p>
<p>Redmi K30 至尊纪念版</p>
</li>
<li>
<img src="/static/demo_image/k30至尊.jpg" alt="Redmi K30 至尊纪念版">
<p class="class02">¥1999</p>
<p>Redmi K30 至尊纪念版</p>
</li>
<li>
<img src="/static/demo_image/k30至尊.jpg" alt="Redmi K30 至尊纪念版">
<p class="class02">¥1999</p>
<p>Redmi K30 至尊纪念版</p>
</li>
</ul>
</div>
<hr>
<div>
<ul>
<!-- 循环显示后端返回的值 cityForecast-->
<li v-for="forecast in cityForecast" :key="forecast.id">
<!-- 在属性前面加上 : 就可以使用 vue 的变量 -->
<router-link :to="'/ProductDetail?tCity='+forecast.scity">
<!-- router-link to="/ProductDetail" 跳转到 /ProductDetail 页面就是详情页 ? 后面的是传的参数,就写这一句后端是收不到这个参数的,地址栏有 -->
<p>
城市:{{forecast.scity}},
天气情况:{{forecast.sinfo}},
温度:{{forecast.stemperature}},
湿度:{{forecast.shumidity}},
风向:{{forecast.sdirect}},
风力:{{forecast.spower}},
空气质量指数:{{forecast.saqi}};
</p>
</router-link>
</li>
</ul>
</div>
</div>
</template>
<script>
// export default 向外导出,就是把里面的内容公开出来,让其他的地方可以引用它
export default {
data() {
return {
// 存放数据
cityForecast: String,
}
},
// 在这个里面写我们的 js 代码
mounted() {
// 页面加载完成之后加载里面的内容,一般来说逻辑代码不在这个里面写
// alert();
this.getForecastList();
},
methods: {
// 一般逻辑方法什么的在这个里面写
// 可以简写为:getForecastList(){}
getForecastList: function(){
// 下面匿名函数中的 this 表示的是匿名函数中的内容,不是表示这个 vue,这里就需要用 thisVue 这个第三方
var thisVue = this;
this.$http.get('https://localhost:44361/api/StudyCore/GetTest01').then(function(res){
// res 后端传过来的返回值
thisVue.cityForecast = res.data;
})
}
},
}
</script>
<style scoped>
/* scoped:防止样式污染,这个里面的内容支只队本页面的样式有效【一定要加哦!!!】 */
*{
padding: 0;
margin: 0;
}
#id01{
width: 600px;
height: 36px;
border: red solid 3px;
float: left;
padding: 0 10px;
/* 设置 轮廓色 */
outline-color: red;
/* 设置 轮廓样式 */
/* outline: none; */
}
#id02{
width: 80px;
height: 42px;
background-color: red;
color: white;
/* 去掉边框 */
border: 0 none;
float: left;
/* 设置 轮廓色 */
/* outline-color: red; */
/* 设置 轮廓样式 */
outline: none;
}
.class01{
width: 706px;
height: 42px;
/* 外边距自动,为了自动调整居中,前面已经有设置居中了,这里是因为前面有浮动,所以需要来改变 */
margin: auto;
}
#id03{
margin-top: 50px;
border: red 1px solid;
height: 0;
}
#id04{
width: 1595px;
height: 750px;
}
#id04 p{
text-align: left;
}
#id04 li img{
width: 260px;
}
#id04 li{
border: solid rgba(238, 238, 238, 0.397) 1px;
width: 260px;
margin: 40px 0 0 45px;
/* 去除前面的小点点 */
list-style: none;
float: left;
padding: 6px;
height: 310px;
}
#id04 li:hover{
border: #eee solid 1px;
/* 两个0分别是:X轴阴影偏移量 Y轴偏移量 */
box-shadow: 0 0 6px #ccc;
}
.class02{
font-size: 18px;
font-weight: bold;
color: red;
margin-bottom: 5px;
}
p{
height: 21px;
}
</style>
- 在 components 文件夹下新建 ProductDetail.vue 文件,点击 Demo_y01页面 最下面天气的 P 标签进行跳转的页面
ProductDetail.vue 文件:
其中包含了倒转到
AddSuccess.vue
的代码,AddSuccess.vue
相关内容在下面
<template>
<div class="class0">
<!-- 详情页 -->
<div class="class01">
<div class="class02">
<img src="/static/demo_image/mi10至尊.jpg" alt="mi10至尊">
</div>
<div class="class03" >
<p>城市:{{ssCity.scity}}</p>
<p id="id01">mi10至尊</p>
<p id="id02">¥1999</p>
<p id="id03">
<span id="span01" @click="click01()">-</span>
<!-- 这里的 value中的count 在内容改变后不会第一时间随之改变【会有延迟】,v-model=""则不会有延迟【双向绑定】,实现需要用监听 -->
<input type="text" :value="count" @change="change01()">
<span id="span02" @click="click02()">+</span>
</p>
<p id="id03_1">
<span id="span01_1" @click="click01_1()">-</span>
<input type="text" v-model="count_1">
<span id="span02_1" @click="click02_1()">+</span>
</p>
<p id="id04">
<button @click="ClickAdd()">加入购物车</button>
</p>
</div>
</div>
<hr>
</div>
</template>
<script>
export default {
data() {
return {
// 存放数据
count : 1,
count_1: 1,
ssCity: String,
}
},
mounted() {
// 在这个里面写我们的 js 代码【页面加载完成后执行调用里面的事件】
//获取 Demo_y01.vue 传过来的值
var tCity = this.$route.query.tCity;
this.getCityName(tCity);
},
methods: {
// 一般方法什么的在这个里面写
getCityName(tCity){
// 下面匿名函数中的 this 表示的是匿名函数中的内容,不是表示这个 vue,这里就需要用 thisVue 这个第三方
var thisVue = this;
this.$http.get("https://localhost:44361/api/StudyCore/GetCityName?city="+tCity).then(function(res){
thisVue.ssCity = res.data[0];
});
},
ClickAdd(){
var thisVue02 = this;
this.$http.get("https://localhost:44361/api/StudyCore/AddCart?cityname="+this.ssCity.scity+"&count="+this.count).then((res02)=>{
if(res02.data > 0){
thisVue02.$router.push("/AddSuccess");
// alert("进来了");
}
})
},
click02(){
this.count++;
},
click02_1(){
this.count_1++;
},
click01(){
if (this.count > 1) {
this.count--;
}
},
click01_1(){
if (this.count_1 > 1) {
this.count_1--;
}
},
change01(){
// 可以接收到 input 框内输入的内容
var newCount = event.target.value;
// isNaN() 判断这个变量是不是 不是数字,不是数字返回 true
// 如果 newCount 是数字 并且 newCount大于0
if (!isNaN(newCount) && newCount>0) {
this.count = newCount;
}else{
event.target.value = this.count;
}
}
},
watch: {
// 监听
count_1:function(nval, oval){
// 如果 新的变量不是数字 或者 新的变量小于1
if (isNaN(nval) || nval<1) {
this.count_1 = oval;
}
}
},
}
</script>
<style>
.class0{
width: 900px;
margin: auto;
}
.class01{
height: 550px;
}
.class02{
float: left;
width: 400px;
height: 500px;
}
.class02 img{
width: 400px;
height: 500px;
}
.class03{
float: left;
margin-left: 66px;
}
.class03 p{
margin-bottom: 50px;
text-align: left;
}
#id01{
font-size: 30px;
font-weight: bold;
}
#id02{
font-size: 20px;
font-weight: bold;
color: red;
}
#id03{
height: 30px;
}
#id03_1{
height: 30px;
}
#id04 button{
width: 210px;
height: 50px;
background-color: rgb(228, 155, 87);
border: 0 none;
border-radius: 5px;
color: white;
font-size: 15px;
font-weight: bold;
/* 鼠标放上去呈现手指状态 */
cursor: pointer;
/* 获取焦点时的边框 */
outline: none;
}
.class03 input{
height: 30px;
width: 66px;
border: 1px solid #ccc;
border-left: 0 none;
border-right: 0 none;
/* 获取焦点时的边框 */
outline: none;
text-align: center;
float: left;
}
.class03 span{
/* 可以参考:复习 CSS基础【03】有相关display的 */
/* display: inline-block; */
width: 30px;
height: 30px;
border: 1px solid #cccccc;
text-align: center;
/* 鼠标上去是个手指的状态 */
cursor: pointer;
/* 设置行号,一般设置的数字等于盒子的高度,默认的就是垂直居中了 */
line-height: 30px;
float: left;
}
#span01{
/* 设置圆角 */
border-radius: 3px 0 0 3px;
}
#span02{
/* 设置圆角【左上、右上、右下、坐下】 */
border-radius: 0 3px 3px 0;
}
</style>
- 在 components 文件夹下新建 AddSuccess.vue 文件【最后购物车的跳转页面】,里面随便来点什么内容都可以,然后就是给他添加路由。
- 在 router文件夹 下的 index.js 文件:
import Vue from 'vue'
import Router from 'vue-router'
// import HelloWorld from '@/components/HelloWorld'
// 这是参照上面一行
import Demo_y01 from '@/components/Demo_y01'
import ProductDetail from '@/components/ProductDetail'
import AddSuccess from '@/components/AddSuccess'
Vue.use(Router)
// export default new Router({
// // 路由
// routes: [{
// // 默认地址根目录
// path: '/',
// name: 'HelloWorld',
// component: HelloWorld
// }]
// })
// 参照上面的修改文件名
export default new Router({
// 路由
routes: [{
// 添加的第1个路由
// 默认地址根目录
path: '/',
name: 'Demo_y01',
component: Demo_y01
},
{
// 添加的第2个路由
path: '/ProductDetail',
name: 'ProductDetail',
component: ProductDetail
},
{
// 添加的第3个路由
path: '/AddSuccess',
name: 'AddSuccess',
component: AddSuccess
}
]
})
后端:
- 在 Models文件夹 下新建
ShoppingCarts.cs
类文件
ShoppingCarts.cs 文件:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using WebAppStudyCore01.Common;
namespace WebAppStudyCore01.Models {
public class ShoppingCarts {
// 类似购物车
public static int AddCart(string cityname, string count)
{
return SqlHelp.ExecuteNonQuery($"INSERT INTO Study01 (cityName, info) VALUES('{cityname}', '{count}')");
}
}
}
- Models 下的
StudyCoreClass01.cs
类文件
StudyCoreClass01.cs 文件: 添加部分内容
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using WebAppStudyCore01.Common;
namespace WebAppStudyCore01.Models {
public class StudyCoreClass01 {
/// <summary>
/// 城市名
/// </summary>
public String Scity { get; set; }
/// <summary>
/// 天气情况
/// </summary>
public String Sinfo { get; set; }
/// <summary>
/// 温度,可能为空
/// </summary>
public String Stemperature { get; set; }
/// <summary>
/// 湿度,可能为空
/// </summary>
public String Shumidity { get; set; }
/// <summary>
/// 风向,可能为空
/// </summary>
public String Sdirect { get; set; }
/// <summary>
/// 风力,可能为空
/// </summary>
public String Spower { get; set; }
/// <summary>
/// 空气质量指数,可能为空
/// </summary>
public String Saqi { get; set; }
public static List<StudyCoreClass01> GetTextList()
{
// 【这里不要用*,查询那些字段就把字段都写在上面的,就算是全部字段也自己写,不用*代替】
DataTable dt = SqlHelp.ExecuteTable("select * from Study01");
List<StudyCoreClass01> scc1 = new List<StudyCoreClass01>();
for (int i = 0; i < dt.Rows.Count; i++)
{
scc1.Add(ToModel(dt.Rows[i]));
}
return scc1;
}
public static List<StudyCoreClass01> GetTextList02(string name)
{
DataTable dt = SqlHelp.ExecuteTable("select * from Study01 where cityName = '"+name+"'");
List<StudyCoreClass01> scc1 = new List<StudyCoreClass01>();
for (int i = 0; i < dt.Rows.Count; i++)
{
scc1.Add(ToModel(dt.Rows[i]));
}
return scc1;
}
private static StudyCoreClass01 ToModel(DataRow dr)
{
// 下面后面的数据都是取自数据库
StudyCoreClass01 scc = new StudyCoreClass01();
scc.Scity = dr["cityName"].ToString();// 城市名
scc.Sinfo = dr["info"].ToString();// 天气情况
scc.Stemperature = dr["temperature"].ToString();// 温度,可能为空
scc.Shumidity = dr["humidity"].ToString();// 湿度,可能为空
scc.Sdirect = dr["direct"].ToString();// 风向,可能为空
scc.Spower = dr["power"].ToString();// 风力,可能为空
scc.Saqi = dr["aqi"].ToString();// 空气质量指数,可能为空
return scc;
}
}
}
Common 下的 SqlHelp.cs文件: 添加部分内容
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Threading.Tasks;
namespace WebAppStudyCore01.Common {
public class SqlHelp {
public static string ConStr { get; set; }
/// <summary>
/// 执行查询语句
/// </summary>
/// <param name="cmdText">SQL语句</param>
/// <returns>返回 SQL语句 查询数据</returns>
public static DataTable ExecuteTable(string cmdText)
{
using (SqlConnection con = new SqlConnection(ConStr))
{
con.Open();
SqlCommand cmd = new SqlCommand(cmdText, con);
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
sda.Fill(ds);
return ds.Tables[0];
// 取数据库数据
}
}
/// <summary>
/// 执行【增、删、改】语句
/// </summary>
/// <param name="cmdText">SQL语句</param>
/// <returns>返回受影响行数</returns>
public static int ExecuteNonQuery(string cmdText)
{
using (SqlConnection con = new SqlConnection(ConStr))
{
con.Open();
SqlCommand cmd = new SqlCommand(cmdText, con);
int rows = cmd.ExecuteNonQuery();
if (rows <= 0)
{
throw new Exception("数据库执行错误");
}
return rows;
}
}
}
}
Controllers 下的 StudyCoreController.cs文件: 【掉坑之地】
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using WebAppStudyCore01.Common;
using WebAppStudyCore01.Models;
namespace WebAppStudyCore01.Controllers {
[EnableCors("any")]// 添加 跨域名【在同一台电脑上面端口不一样也属于跨域】
[Route("api/[controller]/[action]")]// 后面添加 /[action] 下面是具体写到方法名
[ApiController]
public class StudyCoreController : ControllerBase {// 下面API地址只选取 StudyCoreController类 的前面部分 StudyCore
/// <summary>
/// 获取数据库yin中Study01表中所有数据
/// </summary>
/// <returns>返回所有的数据</returns>
public List<StudyCoreClass01> GetTest01()
{
/* API地址:https://localhost:44361/api/StudyCore/GetTest01 */
List<StudyCoreClass01> scc01 = StudyCoreClass01.GetTextList();
// 前端调用接口给前端返回的数据 scc01
return scc01;
// return "text小印丶";//可以先写上这句,看看接口有没有返回数据
}
/// <summary>
/// 前端的 get请求 通过地址栏传参,获取相应城市的天气信息
/// </summary>
/// <returns>返回某个城市的天气情况,数据来源于数据库已存在的</returns>
public List<StudyCoreClass01> GetCityName()
{
/* API地址:https://localhost:44361/api/StudyCore/GetCityName */
String name;
// name = Request.QueryString["city"];
// 获取前端 get请求 的地址栏的参数【上面的是网上找的没有编译通过,下面的是自己尝试的可以】
name = Request.Query["city"];
List<StudyCoreClass01> scc02 = StudyCoreClass01.GetTextList02(name);
return scc02;
}
/// <summary>
/// 类似购物车
/// </summary>
/// <param name="cityname">城市名</param>
/// <param name="count">添加数量</param>
/// <returns>几行受影响</returns>
public int AddCart(string cityname, string count)
{
// 用这种方法也是可以接收前端 get 过来在地址栏的参数
/* API地址:https://localhost:44361/api/StudyCore/AddCart */
int rows = ShoppingCarts.AddCart(cityname, count);
return rows;
}
}
}
以上文件内容添加先后顺序是乱的,需要运行起来先添加所有代码,需要参照上一篇博客
一点点笔记,以便以后翻阅。