iT邦幫忙

2021 iThome 鐵人賽

DAY 8
0
自我挑戰組

菜鳥工程師的奇幻旅程系列 第 8

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,明天則是會延伸討論資料庫的指令以及網站上線的處理細節。


上一篇
Day 7 - 拯救落後的專案能撐一天是一天(前端篇)
下一篇
Day 9 - 拯救落後的專案能撐一天是一天(資料庫與網站上線篇)
系列文
菜鳥工程師的奇幻旅程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言