Day 8 - 拯救落後的专案能撑一天是一天(後端篇)

走过了前端的一些坑之後接着来处理後端的功能,相较於前端开发完後在浏览器可以看到即时的结果(例如场景有没有正常载入),传到server的部分就常常要将处理的行为在编辑器(Visual Studio)下断点看输出的数值(下log也可以,但自己的习惯是断点逐步执行的过程中确定功能input到output跟自己想的一样)。

第二天分享的内容主要会环绕在前端怎麽传资料到後端、Web Service的使用方式以及资料库端的简单概念,并且接下来分享的技术和工具都是主要使用到的。

等等,资料怎麽传到後端?

Ajax

AJAX即「Asynchronous JavaScript and XML」(非同步的JavaScript与XML技术),指的是一套综合了多项技术的浏览器端网页开发技术。

开发情境 : 今天使用者输入一些资讯後接着做查询或者是登入的动作,接着按下确认键後的处里过程,而首先会有一个键的表单并且按键加入onclick的行为去呼叫执行ajax的动作。

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="/action_page.php">
      <input type="text" id="account" name="account" value="John"><br>
      <input type="text" id="password" name="password" value="Doe"><br><br>
      <input type="submit" value="Submit">
    </form>   
</body>
</html>

<button type="button" value="确认" onclick="LoginCheck()">

Ajax呼叫的范例如下(以Jquery为例)可以看到里面有几个重要的参数,首先是url为呼叫的指定位置指定要做甚麽事情,接着资料要传什麽则是放在data这里面(如果要传的内容较多建议存成json的型态)。

function LoginCheck(){
  $.ajax({
    type: 'GET', // 用POST or GET的方式
    dataType: 'json',  // 资料的格式
    url: url, // 呼叫後端的URL
    data: data, // 传送给後端的资料
    timeout: 5000,
    async: false, // 是否开启同步非同步请求
    success: function(data, textStatus ){ // 成功回传结果
       alert('request successful');
    },
    fail: function(xhr, textStatus, errorThrown){ // 失败回传结果
       alert('request failed');
    }
  });
}

ASP.NET Web 服务 (ASMX)

後端的处理上依照先前长期合作单位使用Web Service的sample code进行修改(整个专案是使用ASP.NET Web Forms),那时候还很好笑的询问提供程序码的联络窗口哪里可以看到後端的处理行为xD

.ASMX 提供的功能可让您建立 web 服务,使用简单的物件存取通讯协定 (SOAP) 传送讯息。SOAP 是一种与平台无关且与语言无关的通讯协定,可用於建立及存取 web 服务。.ASMX 服务的取用者不需要知道用来执行此服务的平台、物件模型或程序设计语言的任何相关资讯。


//首页登入按钮(点击後登入成功刷新页面)
//登入按钮
function LoginCheck(){
    $.ajax({
        type: "POST",
        contentType: "application/json; charset=utf-8",
        url: "WebService.asmx/ValidateLogin",
        data: "{'username':'" + $('#account').val() + "','userpwd':'" + $('#password').val() + "'}",
        dataType: "json",
        async: false,
        success: function (result) {
            if (result.d == false) {
                bootbox.alert({
                    size: "small", title: "讯息提示", message: "帐号密码错误!",
                    callback: function () {

                    }
                });
            } else {
                $('#divlogout1').removeClass('hidden');
                $('#divlogin1').addClass('hidden');

                // 成功登入後刷新订单
                $('#order-list').load(' #order-list > *');

                //$('#btnSubmit').load(' #btnSubmit');     
                $('#btnSubmit').css('display', 'block');

                // 20200615--test
                //$('#goto3dreality').load(' #goto3dreality > *');

            }
        },
        fail: function(xhr, textStatus, errorThrown){ // 失败回传结果
           alert('request failed');
        }
    });
});

以下为登入的判断行为

using DBAction;
using Ini;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Threading;
using System.Web;
using System.Web.Services;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// 若要允许使用 ASP.NET AJAX 从指令码呼叫此 Web 服务,请取消注解下列一行。
[System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService
{
    #region 会员登入
    [WebMethod(EnableSession = true)]
    public bool ValidateLogin(string username, string userpwd)
    {

        // 授权:设定角色到 userData 
        //userData = "gold_member,board_admin";
        using (SqlCommand Cmd = new SqlCommand())
        {
            bool _tf = false;

            Cmd.CommandText = "SELECT UserName,EMail,UserId FROM [MemberInfo] WHERE [Email]=@Email AND [LoginPwd]=@LoginPwd AND IsDel=0 ";
            Cmd.Parameters.AddWithValue("@Email", username);
            Cmd.Parameters.AddWithValue("@LoginPwd", userpwd);

            DataTable dt = dbCommand.GetTable(Cmd);
            if (dt.Rows.Count > 0)
            {
                _tf = true;
                HttpContext.Current.Session.Add("userid", dt.Rows[0][2].ToString());
                HttpContext.Current.Session.Add("username", dt.Rows[0][0].ToString());
            }
            return _tf; // JsonConvert.SerializeObject(_tf);
        }
    }
    #endregion
}


例外补充当执行资料表指令前需要连线到资料库(当时是分开做处理)。

DataTable dt = dbCommand.**GetTable**(Cmd);
public static DataTable GetTable(SqlCommand command)
{
    DataTable data = new DataTable();
    using (SqlConnection sqlconnection = new SqlConnection(WebConfigurationManager.ConnectionStrings["ptri219"].ConnectionString))
    {
        command.Connection = sqlconnection;
        using (SqlDataAdapter Sqla = new SqlDataAdapter(command))
        {
            Sqla.Fill(data);
        }
    }
    return data;
}

综合上述基本上大概流程会这样

  1. html设计表单加入触发Javascript function的行为
  2. 将AJAX放在此function被触发後时就可以执行上述的操作(路径记得对应ASMX的位置以及呼叫的Function name)
  3. ASMX定义的Function接受到资料後与资料库连线并且执行script将结果回传到前端
  4. Ajax的success接收到结果完成一次前端与後端沟通的流程

前後端开发时的贴心提醒

与昨天的前端篇一起检视开发上可以留意的几点

  • 当要透过AJAX或者是其他方式呼叫时,请特别注意要传送的资料是否有在里面(有时候会因为想说使用者在画面上确实有输入但是迟迟没有正常执行,因此第一步建议可以确认这一部分)
  • 确认URL呼叫的位置是否正确(尤其是呼叫ASMX需要确认档案位置) => 确认方式可以开浏览器的Network标签查看触发的行为如果是404那路径基本上错了
  • 呼叫到asmx的function请确认前端传递的数值是否有接收到(关键点在於前端data的object名称若asmx funciton内没有相对应的宣告名称会导致资料没有接收到)
  • 後端的资料库连线(SqlConnection)确认是否有正常连线,若没有检查这个地方後面的处理会卡死在这一个地方
  • 如同上点当确认有正常连线後资料库的指令确认是否正确

原本想要把资料库这块写在今天,但这两天超级浓缩将前後端处理的过程写完後直接打消这个念头xD,明天则是会延伸讨论资料库的指令以及网站上线的处理细节。


<<:  # Day3 Virtual Memory Layout on RISC-V Linux

>>:  标签图片的方法与实作 - Day 12

DAY 21 制作 Nav Bar - FontAwesome

FontAwesome FontAwesome 让我们可以快速方便的使用 Icon 的设计,不过他有...

[Day28]初探Firebase Cloud Messaging for Flutter

大家好,今天要来尝试使用firebase_messaging,今天使用的是Android手机 首先到...

Deep Link / Deferred Deep Link 深度连结

Deep Link 可以开启 app 的特定页面,而不仅仅是打开 app 首页而已。 In the ...

Day18:终於要进去新手村了-Javascript-回圈-for

今天也看了彭彭的影片,要来记录的是for回圈的部分,基本上判断概念跟while回圈一样,需要注意初始...

#远距办公开放员工外网连线, 如何确保内外部资料传输安全?

疫情後,公司调整部份员工仍维持远距工作,但开放员工外网连线容易让内网出现资安漏洞 如何确保员工在公...