iT邦幫忙

2021 iThome 鐵人賽

DAY 9
1
Modern Web

ASP.NET Web Forms 入門 - 30天建立遊艇網頁專案後端及後台功能 C#系列 第 9

Day 9 - 依 DEALERS 前台頁面分析拆解後,逐步建立後台功能 (下) - 圖檔同名處理 - ASP.NET Web Forms C#

  • 分享至 

  • xImage
  •  

🌵 建立 Dealer Manager - Content Page 後台頁面 - 代理商功能。


Dealer Manager 後台頁面 - 代理商功能介紹 :

📌 後台代理商功能需要的功能如下 :

1. 單個國家會有多個區域代理商,因此需要對應單個國家能新增跟刪除不同"區域"。

https://ithelp.ithome.com.tw/upload/images/20210923/20139487KtlUp9n7mH.jpg


2. 區域代理商的資料都是固定格式。

https://ithelp.ithome.com.tw/upload/images/20210923/20139487TBx2X1IzRw.jpg

  • 🌵 灰色欄位設定為 ReadOnly,無法修改。

  • 🌵 這個區域資料較多,Visible 先設成 false 不顯示,選完國家及代理商後才顯示。

  • 👺 代理商的 Thumbnail 縮圖建議用 asp:Literal 控制項送 HTML 的作法製作,如果使用 asp:Image 控制項,在圖檔名稱有中文時,後端使用 .ImageUrl 設定控制項路徑,會在渲染後因為中文轉碼而讀不到圖片。



Dealer Manager 後台頁面實作 :

1. 建立區域代理商資料表

https://ithelp.ithome.com.tw/upload/images/20210923/20139487g6mIdZ1dRp.jpg


2. 將國家資料表的 id 與區域代理商資料表 country_ID 建立關聯

https://ithelp.ithome.com.tw/upload/images/20210923/20139487lFOKNC8iVI.jpg

  • 🧠 可以在資料庫圖表的關聯性中設定屬性,將關聯性 " INSERT 及 UPDATE 規格" 裡面的刪除規則,設定為串聯刪除 (**重疊顯示 - Cascade **),這樣如果刪除國家時,會一併刪除該國的區域代理商,可以避免手殘亂刪時出現錯誤,當然也會寫在後台的規則裡。

  • 👀 串聯刪除-設定參考 : 如何在 SQL Server 資料庫設計「一對一」表格關聯

3. 在國家下拉列表 DropDownList 控制項直接使用輔助精靈連接資料庫並設定值為對應 id

https://ithelp.ithome.com.tw/upload/images/20210923/20139487TVDMg5CyEL.jpg

  • 🌵 先在原始檔頁選擇點選控制項該行程式碼,再轉到設計頁可以避免選錯,點擊側開選項設定資料來源時,要勾 countrySort 跟 id 這樣設定完成後,再點擊側開選項選擇資料來源時,資料欄位值才能選到 id。

  • 👺 這裡很重要,有設定的話 SQL 語法會變很簡單,後面有遇到下拉選單最好都設定。

4. 在 Page_Load 事件中加入 showDealerList(); 方法讀取 RadioButtonList 控制項資料如下

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack) {
        DropDownList1.DataBind(); //先綁定取得選取預設值
        showDealerList();
    }
}


5. 建立 showDealerList(); 方法的邏輯程式碼如下

private void showDealerList()
{
    //依下拉選單選取國家的值 (id) 取得地區分類
    string selCountry_id = DropDownList1.SelectedValue;
    SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
    string sql = "SELECT area FROM Dealers WHERE country_ID = @selCountry_id";
    SqlCommand command = new SqlCommand(sql, connection);
    command.Parameters.AddWithValue("@selCountry_id", selCountry_id);
    //取得地區分類
    connection.Open();
    SqlDataReader readerCountry = command.ExecuteReader();
    while (readerCountry.Read()) {
        string typeStr = readerCountry["area"].ToString();
        // RadioButtonList 增加方式
        ListItem listItem = new ListItem();
        listItem.Text = typeStr;
        listItem.Value = typeStr;
        RadioButtonList1.Items.Add(listItem);
    }
    connection.Close();
}


6. 在增加區域的 Add 按鈕 OnClick 事件加入以下後置程式碼

protected void BtnAddArea_Click(object sender, EventArgs e)
{
    //取得下拉選單國家的值 (id)
    string selCountry_id = DropDownList1.SelectedValue;
    //取得輸入欄內的文字
    string areaStr = TBoxAddArea.Text;
    //判斷是否重複用
    bool isRepeat = false;

    //取得地區分類
    SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
    string sql = $"SELECT area FROM Dealers WHERE country_ID = @selCountry_id";
    SqlCommand command = new SqlCommand(sql, connection);
        command.Parameters.AddWithValue("@selCountry_id", selCountry_id);
    connection.Open();
    SqlDataReader readerCountry = command.ExecuteReader();
    while (readerCountry.Read()) {
        string typeStr = readerCountry["area"].ToString();
        //判斷有無重複名稱
        if (areaStr.Equals(typeStr)) {
            isRepeat = true;
            //重複警告
            TBoxAddArea.ForeColor = Color.Red;
            TBoxAddArea.Text = "The area name is repeated!";
        }
    }
    connection.Close();

    //輸入的區域名稱不重複才執行
    if (!isRepeat) {
        TBoxAddArea.ForeColor = Color.Black;
        //新增區域
        string sql2 = "INSERT INTO Dealers (country_ID, area) VALUES(@selCountry_id, @areaStr)";
        SqlCommand command2 = new SqlCommand(sql2, connection);
        command2.Parameters.AddWithValue("@selCountry_id", selCountry_id);
        command2.Parameters.AddWithValue("@areaStr", areaStr);
        connection.Open();
        command2.ExecuteNonQuery();
        connection.Close();

        //畫面渲染
        RadioButtonList1.Items.Clear(); //清掉舊的
        BtnDelArea.Visible = false;
        DealerList.Visible = false;
        LabUploadImg.Visible = false;
        UpdateDealerListLab.Visible = false;
        showDealerList(); //讀取新的

        //清空輸入欄位
        TBoxAddArea.Text = "";
    }
}


7. 在刪除區域的 Delete Area 按鈕 OnClick 事件加入以下後置程式碼

protected void BtnDelArea_Click(object sender, EventArgs e)
{
    //取得選取資料的值
    string selAreaStr = RadioButtonList1.SelectedValue;

    //刪除實際圖檔檔案
    SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
    string sql = "SELECT dealerImgPath FROM Dealers WHERE area = @selAreaStr";
    SqlCommand command = new SqlCommand(sql, connection);
    command.Parameters.AddWithValue("@selAreaStr", selAreaStr);
    connection.Open();
    SqlDataReader reader = command.ExecuteReader();
    if (reader.Read()) {
        string imgPath = reader["dealerImgPath"].ToString();
        if (!imgPath.Equals("")) {
            string savePath = Server.MapPath($"~/Tayanahtml/upload/Images/{imgPath}");
            File.Delete(savePath);
        }
    }
    connection.Close();

    //刪除資料庫該筆資料
    string sqlDel = "DELETE FROM Dealers WHERE area = @selAreaStr";
    SqlCommand commandDel = new SqlCommand(sqlDel, connection);
    commandDel.Parameters.AddWithValue("@selAreaStr", selAreaStr);
    connection.Open();
    commandDel.ExecuteNonQuery();
    connection.Close();

    //畫面渲染
    RadioButtonList1.Items.Clear(); //清掉舊的
    BtnDelArea.Visible = false;
    DealerList.Visible = false;
    LabUploadImg.Visible = false;
    UpdateDealerListLab.Visible = false;
    showDealerList(); //讀取新的
    TBoxAddArea.ForeColor = Color.Black;
    TBoxAddArea.Text = "";
}


8. 在國家下拉列表的 DropDownList 控制項 OnSelectedIndexChanged 事件加入以下後置程式碼控制畫面渲染

protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
    //當選擇國家改變時刷新畫面資料
    RadioButtonList1.Items.Clear();
    BtnDelArea.Visible = false;
    DealerList.Visible = false;
    LabUploadImg.Visible = false;
    UpdateDealerListLab.Visible = false;
    showDealerList();
}
  • 👺 記得在 .aspx 頁面加上AutoPostBack="True",這樣選取改變時才會刷新頁面。

9. 建立顯示區域代理商資料表 showDealerListTable(); 讀取資料方法

private void showDealerListTable()
{
    //當區域選取時才顯示代理商資料表
    DealerList.Visible = true;
    //放入國家顯示文字
    TBoxCountry.Text = DropDownList1.SelectedItem.Text;
    //放入區域
    TBoxArea.Text = RadioButtonList1.SelectedValue;

    //依選取區域的值連接資料庫取得資料
    string selAreaStr = RadioButtonList1.SelectedValue;
    SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
    string sql = $"SELECT * FROM Dealers WHERE area = @selAreaStr";
    SqlCommand command = new SqlCommand(sql, connection);
    command.Parameters.AddWithValue("@selAreaStr", selAreaStr);
    connection.Open();
    SqlDataReader reader = command.ExecuteReader();
    //放入個別資料
    while (reader.Read()) {
        string savePath = reader["dealerImgPath"].ToString();
        LiteralImg.Text = $"<img alt='Thumbnail Image' src='/Tayanahtml/upload/Images/{savePath}' Width='209px'/>";
        TBoxImage.Text = reader["dealerImgPath"].ToString();
        TBoxName.Text = reader["name"].ToString();
        TBoxContact.Text = reader["contact"].ToString();
        TBoxAddress.Text = reader["address"].ToString();
        TBoxTel.Text = reader["tel"].ToString();
        TBoxFax.Text = reader["fax"].ToString();
        TBoxEmail.Text = reader["email"].ToString();
        TBoxLink.Text = reader["link"].ToString();
        TBoxDate.Text = reader["initDate"].ToString();
    }
    connection.Close();
}
  • 🌵 用 .SelectedItem.Text 來取得下拉選單選取的顯示文字 !

  • 🌵 圖片路徑 savePath 是用來送到前台的 HTML 內容,所以前面不是波浪符號喔 !

10. 在區域列表的 RadioButtonList 控制項 OnSelectedIndexChanged 事件加入以下後置程式碼控制畫面渲染

protected void RadioButtonList1_SelectedIndexChanged(object sender, EventArgs e)
{
    //區域預設不選取,但當選取切換時顯示刪除按鈕
    BtnDelArea.Visible = true;
    LabUploadImg.Visible = false;
    UpdateDealerListLab.Visible = false;
    //顯示區域代理商資料表
    showDealerListTable();
    TBoxAddArea.ForeColor = Color.Black;
    TBoxAddArea.Text = "";
}
  • 👺 記得在 .aspx 頁面加上AutoPostBack="True",這樣選取改變時才會刷新頁面。

11. 在 FileUpload 控制項後加上一個 Upload 按鈕,並在 Upload 按鈕的 OnClick 事件加入以下後置程式碼,並進行圖檔同名處理後,完成上傳功能

protected void BtnUploadImg_Click(object sender, EventArgs e)
{
    //設定存檔路徑,需填完整路徑,結尾反斜線如果沒加要用 Path.Combine() 可自動添加
    string savePath = Server.MapPath("~/Tayanahtml/upload/Images/");

    //判斷有選檔案才可上傳
    if (FileUpload1.HasFile) {
        //取得選擇區域名稱
        string selAreaStr = RadioButtonList1.SelectedValue;

        //先執行刪除舊圖檔
        SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
        string sqlDel = "SELECT dealerImgPath FROM Dealers WHERE area = @selAreaStr";
        SqlCommand commandDel = new SqlCommand(sqlDel, connection);
        commandDel.Parameters.AddWithValue("@selAreaStr", selAreaStr);
        connection.Open();
        SqlDataReader reader = commandDel.ExecuteReader();
        if (reader.Read()) {
            string delFileName = reader["dealerImgPath"].ToString();
            //有舊圖才執行刪除
            if (!String.IsNullOrEmpty(delFileName)) {
                File.Delete(savePath + delFileName);
            }
        }
        connection.Close();

        //儲存圖片檔案及圖片名稱
        //檢查專案資料夾內有無同名檔案,有同名就加流水號
        DirectoryInfo directoryInfo = new DirectoryInfo(savePath);
        //取得選取檔案名稱
        string fileName = FileUpload1.FileName;
        string[] fileNameArr = fileName.Split('.');
        int count = 0;
        foreach (var fileItem in directoryInfo.GetFiles()) {
            if (fileItem.Name.Contains(fileNameArr[0])) {
                count++;
            }
        }
        fileName = fileNameArr[0] + $"({count + 1})." + fileNameArr[1];
        FileUpload1.SaveAs(savePath + fileName);

        //渲染畫面
        DateTime nowtime = DateTime.Now;
        LabUploadImg.Visible = true;
        LabUploadImg.ForeColor = Color.Green;
        LabUploadImg.Text = "*Upload Success! - " + nowtime.ToString("G");

        //更新資料庫資料
        string sql = "UPDATE Dealers SET dealerImgPath = @fileName WHERE area = @selAreaStr";
        SqlCommand command = new SqlCommand(sql, connection);
        command.Parameters.AddWithValue("@fileName", fileName);
        command.Parameters.AddWithValue("@selAreaStr", selAreaStr);
        connection.Open();
        command.ExecuteNonQuery();
        connection.Close();

        //渲染畫面
        showDealerListTable();
    }
    else {
        //警告沒有選取檔案
        LabUploadImg.Visible = true;
        LabUploadImg.ForeColor = Color.Red;
        LabUploadImg.Text = "*Need Choose File!";
    }
}
  • 👀 DirectoryInfo 類別參考官網 : DirectoryInfo 類別

  • 👀 GetFiles() 方法參考官網 : DirectoryInfo.GetFiles 方法

  • 🌵 用 .Contains 才能把已經加過流水號的檔案算進計算的數量裡。

  • 🌵 FileUpload 控制項需配合一個按鈕控制項來執行上傳功能。

  • 👺 儲存圖檔前記得先檢查有無同名檔案,而且檢查圖檔要針對存放的資料夾,因為可能會出現同名但內容不同的圖片,避免其它頁面有使用同名檔案被取代。

12. 在上傳代理商資料的 Update Dealer List Value 按鈕 OnClick 事件加入以下後置程式碼

protected void BtnUpdateDealerList_Click(object sender, EventArgs e)
{
    //依國家及選取區域的值連接資料庫取得資料
    string selAreaStr = RadioButtonList1.SelectedValue;
    string selCountry_id = DropDownList1.SelectedValue;
    SqlConnection connection = new SqlConnection(WebConfigurationManager.ConnectionStrings["TayanaYachtConnectionString"].ConnectionString);
    string sql = $"UPDATE Dealers SET name=@name, contact=@contact, address=@address, tel=@tel, fax=@fax, email=@email, link=@link WHERE country_ID=@selCountry_id AND area = @selAreaStr";
    SqlCommand command = new SqlCommand(sql, connection);
    command.Parameters.AddWithValue("@name", TBoxName.Text);
    command.Parameters.AddWithValue("@contact", TBoxContact.Text);
    command.Parameters.AddWithValue("@address", TBoxAddress.Text);
    command.Parameters.AddWithValue("@tel", TBoxTel.Text);
    command.Parameters.AddWithValue("@fax", TBoxFax.Text);
    command.Parameters.AddWithValue("@email", TBoxEmail.Text);
    command.Parameters.AddWithValue("@link", TBoxLink.Text);
    command.Parameters.AddWithValue("@selCountry_id", selCountry_id);
    command.Parameters.AddWithValue("@selAreaStr", selAreaStr);
    connection.Open();
    command.ExecuteNonQuery();
    connection.Close();

    //渲染上傳成功提示
    DateTime nowtime = DateTime.Now;
    UpdateDealerListLab.Visible = true;
    UpdateDealerListLab.Text = "*Upload Success! - " + nowtime.ToString("G");
    Page.SetFocus(UpdateDealerListLab);
}



13. 渲染畫面後,進行功能測試,確認無誤,完成此頁後台功能~



本日總結 :

📢 這個頁面因為放入兩組會互相影響的功能,所以關鍵會在互動時的項目開關,如上篇提到的增刪國家時,國家下拉選單要同步更新,而在下拉選取不同國家時預設不選取任何區域,是避免反覆讀取還不確定使用者要看的資料是哪個,而在選取區域後會秀出刪除區域的按鈕,刪除區域後又會回到預設不選取任何區域,另外選取區域後才會秀出這個國家這個區域的代理商細項資料,這些切換的細節,在第一次設計畫面交互時可能不太好想到,可以試著先畫草稿模擬想像。

  • 明日將介紹製作 DEALERS 前台頁面的後端細節。

上一篇
Day 8 - 依 DEALERS 前台頁面分析拆解後,逐步建立後台功能 (上) - GridView 應用 - ASP.NET Web Forms C#
下一篇
Day 10 - 將 DEALERS 後台儲存資料提取後,送至前台渲染畫面 - Literal 控制項應用 - ASP.NET Web Forms C#
系列文
ASP.NET Web Forms 入門 - 30天建立遊艇網頁專案後端及後台功能 C#30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言