C# 基础之前后端分离【02】

本文代码仓库地址: 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
  • 注意:这里我输入的 puch ,不是 push
    提示的错误是不存在这个函数,出现这种情况先看一下是不是自己的单词写错了

正确代码:

        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">&yen;1999</p>
                    <p>Redmi K30 至尊纪念版</p>
                </li>
                <li>
                    <img src="/static/demo_image/k30至尊.jpg" alt="Redmi K30 至尊纪念版">
                    <p class="class02">&yen;1999</p>
                    <p>Redmi K30 至尊纪念版</p>
                </li>
                <li>
                    <img src="/static/demo_image/k30至尊.jpg" alt="Redmi K30 至尊纪念版">
                    <p class="class02">&yen;1999</p>
                    <p>Redmi K30 至尊纪念版</p>
                </li>
                <li>
                    <img src="/static/demo_image/k30至尊.jpg" alt="Redmi K30 至尊纪念版">
                    <p class="class02">&yen;1999</p>
                    <p>Redmi K30 至尊纪念版</p>
                </li>
                <li>
                    <img src="/static/demo_image/k30至尊.jpg" alt="Redmi K30 至尊纪念版">
                    <p class="class02">&yen;1999</p>
                    <p>Redmi K30 至尊纪念版</p>
                </li>

                <li>
                    <img src="/static/demo_image/k30至尊.jpg" alt="Redmi K30 至尊纪念版">
                    <p class="class02">&yen;1999</p>
                    <p>Redmi K30 至尊纪念版</p>
                </li>
                <li>
                    <img src="/static/demo_image/k30至尊.jpg" alt="Redmi K30 至尊纪念版">
                    <p class="class02">&yen;1999</p>
                    <p>Redmi K30 至尊纪念版</p>
                </li>
                <li>
                    <img src="/static/demo_image/k30至尊.jpg" alt="Redmi K30 至尊纪念版">
                    <p class="class02">&yen;1999</p>
                    <p>Redmi K30 至尊纪念版</p>
                </li>
                <li>
                    <img src="/static/demo_image/k30至尊.jpg" alt="Redmi K30 至尊纪念版">
                    <p class="class02">&yen;1999</p>
                    <p>Redmi K30 至尊纪念版</p>
                </li>
                <li>
                    <img src="/static/demo_image/k30至尊.jpg" alt="Redmi K30 至尊纪念版">
                    <p class="class02">&yen;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">&yen;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;
    }

  }
}

以上文件内容添加先后顺序是乱的,需要运行起来先添加所有代码,需要参照上一篇博客


笔记源码


一点点笔记,以便以后翻阅。

猜你喜欢

转载自blog.csdn.net/qq_44111597/article/details/108864434