ASP.NETを使って管理ページを作成しよう(実践編)
MasterForm.aspxの作成に入っていきたいと思います。MVCではなくASP.NETを使う最大のメリットはグリッドビューが使えることにあります。GridViewのコントロールを使うことにより記事データの一覧をリストにして表示してくれます。
ASP.NET MVCで作成したデータベースに接続するためのクラス(mdlCommon, mdlDatabase, mdlConst)をインポートします。ソリューションエクスプローラーのAdminWebSiteを右クリックして「追加」から「新しいフォルダー」を選び、名前を「Modules」にします。
作成したModulesフォルダを右クリックして「追加」から「既存の項目」を選択します。別のチャプターで作ったプロジェクト(WebSiteソリューション)を開きます。通常はサイドメニューに表示されている「ドキュメント」から
\Documents\Visual Studio 2015\Projects\WebSite
デフォルトでは上記のパスにプロジェクトは保存されています。 インポートできたら、GridViewを使ってみましょう。そのままGridViewのコントロールを配置するとデータの分だけページが縦長に表示されてしまいます。操作性に問題が出てきてしまうので表示するサイズを固定して、はみ出した分はスクロールバーを付けてスクロールできるようにします。
ツールボックスから「Panel」を選んでドラッグアンドドロップします。
PanelのプロパティのHeightを任意の数値にします。ここでは500pxとしました。更にプロパティのScrollBarsを「Both」に変更してスクロールバーを付けます。
ツールボックスから下にある「データ」の項目を選んで展開し、GridViewをPanelの中にドラッグアンドドロップします。
GridViewを配置できたら右上に小さくある「<」アイコンをクリックします。
メニューが開きましたら「オートフォーマット」を選択し、表示されるデザインを選んでください。いろいろなデザインがあるのでお好きなのをどうぞ。
ここでは「クラシック」を選択しました。
更に「列の編集」もしましょう。メニューを閉じてしまった方はまたGridViewの右上にある「<」アイコンをクリックしてください。「使用できるフィールド」から「ButtonField」を選択し、追加ボタンを押します。
右側に表示されている「ButtonField プロパティ」から「CommandName」の項目に「select」と入力します。そして、「ButtonType」の項目に「Button」を選び、更に一番下にある「Text」で「ボタン」と書かれた文字列を削除して、全角のスペース「 」を入力します。OKボタンを押して完了しましょう。
上記のデザインに切り替わればOK。
SQL Server Management Studioの記事を管理するテーブルの画像です。今回データをインサートしたいカラムがこの13項目です。
上記の画像に載っている項目の分、TextBoxのコントロールをMaster.aspxに配置します。labelも付けて分かりやすくしましょう。TextBoxはデフォルトでは一行しか入力するエリアがありません。
記事データなど入力エリアを大きく取りたい場合はプロパティの「TextMode」から「MultiLine」を選択しましょう。
コントロールの(ID)は下記にしました。
txtPID
txtBID
txtSID
txtKID
txtKeywords
txtTitle
txtKijiData
txtOGImage
txtDescription
txtInsDate
txtUpdate
txtPublicFlg
txtInvisibleFlg
btnPost
最終的にコントロールの配置はこのようになりました。
プログラミングに入っていきましょう。GridViewに記事のリストを表示させるようにします。MasterForm.aspx.csファイルを開いてGET_GridView()のコードを新しく追加しました。
using System; using mdlDatabase; using mdlCommon; using System.Data; using System.Text; using System.Data.SqlClient; namespace AdminWebSite { public partial class MasterForm : System.Web.UI.Page { DatabaseOpn db = new DatabaseOpn(); mdlCONST.CONSTOpn cnst = new mdlCONST.CONSTOpn(); CmnOpn mdlCmn = new CmnOpn(); DataTable tbl = new DataTable(); protected void Page_Load(object sender, EventArgs e) { if (Session["ID"] == null || Session["PASS"] == null) { //認証されていないユーザなのでログインページに飛ばす Response.Redirect("LoginForm.aspx"); } if (!GET_GridView()) { return; } } // GridViewにデータを格納 public bool GET_GridView() { SqlDataReader sqlRdr = null; StringBuilder strSql = new StringBuilder(); tbl.Clear(); tbl.Columns.Clear(); tbl.Columns.Add("pkiji_id"); tbl.Columns.Add("big_category_name"); tbl.Columns.Add("small_category_name"); tbl.Columns.Add("kiji_id"); tbl.Columns.Add("title"); tbl.Columns.Add("ins_date"); strSql.Append("SELECT k.pkiji_id, b.big_category_name, s.small_category_name, k.kiji_id, k.title, k.ins_date "); strSql.Append("FROM m_kiji k "); strSql.Append("LEFT JOIN c_big_category b "); strSql.Append("ON k.big_category_id = b.big_category_id "); strSql.Append("LEFT JOIN c_small_category s "); strSql.Append("ON k.big_category_id = s.big_category_id "); strSql.Append("AND k.small_category_id = s.small_category_id "); strSql.Append("ORDER BY k.pkiji_id ASC "); try { if (!db.DB_Connect()) { return false; } if (!db.DB_SqlReader(strSql.ToString(), ref sqlRdr)) { return false; } while (sqlRdr.Read()) { DataRow row = tbl.NewRow(); row["pkiji_id"] = sqlRdr["pkiji_id"].ToString(); row["big_category_name"] = sqlRdr["big_category_name"].ToString(); row["small_category_name"] = sqlRdr["small_category_name"].ToString(); row["kiji_id"] = sqlRdr["kiji_id"].ToString(); row["title"] = sqlRdr["title"].ToString(); row["ins_date"] = sqlRdr["ins_date"].ToString(); tbl.Rows.Add(row); } GridView1.DataSource = tbl; GridView1.DataBind(); return true; } catch (Exception ex) { return false; } finally { if (sqlRdr != null) { if (!sqlRdr.IsClosed) { sqlRdr.Close(); } } db.DB_Close(); } } } }一番初めに読み込まれるPage_Load()にGET_GridView()メソッドを呼び出す記述をしました。デバッグしてみましょう。
表示されましたね! でも文字が大きいような気がします。
GridViewのプロパティを開いて「Font」の左に出ている「+」のアイコンをクリックして展開します。「Size」で「Small」に変更しました。
デバッグしてみるときれいに表示されました。
今度はGridViewの左端に表示しているボタンをクリックすることにより、その行に表示されている記事データをそれぞれのコントロールに転写するようにします。GridViewのコントローラをダブルクリックしてGridView1_SelectedIndexChanged()を生成します。Modules/mdlCommon.csを開いて中にある前回のチャプターで使ったメソッドはいらないので全て削除し、新しいメソッドGET_kiji()を下記のように追加しました。
using System; using System.IO; using System.Text; using System.Data.SqlClient; using mdlDatabase; namespace mdlCommon { public class CmnOpn { DatabaseOpn db = new DatabaseOpn(); mdlCONST.CONSTOpn cnst = new mdlCONST.CONSTOpn(); public bool GET_kiji(string strPkiji_id,ref int intB_id, ref int intS_id, ref int intK_id, ref string strKeywords, ref string strTitle, ref string strKiji_data, ref string strOgimage, ref string strDescription, ref string strInsDate, ref string strUpdate, ref bool PublicFlg, ref bool InvisibleFlg) { SqlDataReader sqlRdr = null; StringBuilder strSql = new StringBuilder(); try { strSql.Append("SELECT * "); strSql.Append("FROM m_kiji "); strSql.Append("WHERE pkiji_id = '"); strSql.Append(strPkiji_id); strSql.Append("'"); if (!db.DB_Connect()) { return false; } if (!db.DB_SqlReader(strSql.ToString(), ref sqlRdr)) { return false; } while (sqlRdr.Read()) { intB_id = int.Parse(sqlRdr["big_category_id"].ToString()); intS_id = int.Parse(sqlRdr["small_category_id"].ToString()); intK_id = int.Parse(sqlRdr["kiji_id"].ToString()); strKeywords = sqlRdr["keywords"].ToString(); strTitle = sqlRdr["title"].ToString(); strKiji_data = sqlRdr["kiji_data"].ToString(); strOgimage = sqlRdr["ogimage"].ToString(); strDescription = sqlRdr["description"].ToString(); strInsDate = sqlRdr["ins_date"].ToString(); strUpdate = sqlRdr["up_date"].ToString(); PublicFlg = bool.Parse(sqlRdr["public_flg"].ToString()); InvisibleFlg = bool.Parse(sqlRdr["invisible_flg"].ToString()); } return true; } catch (Exception ex) { return false; } finally { if (sqlRdr != null) { if (!sqlRdr.IsClosed) { sqlRdr.Close(); } } db.DB_Close(); } } } }
GridView1_SelectedIndexChanged()からGET_kiji()を呼び出します。このようにコードを書きました。
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e) { string strPkiji_id = ""; int intBig_category_id = 0; int intSmall_category_id = 0; int intKiji_id = 0; string strKeywords = ""; string strTitle = ""; string strKijiData = ""; string strOgimage = ""; string strDescription = ""; string strInsDate = ""; string strUpDate = ""; bool PublicFlg = false; bool InvisibleFlg = false; int intSeletedIndex = 0; intSeletedIndex = GridView1.SelectedIndex; strPkiji_id = GridView1.Rows[intSeletedIndex].Cells[1].Text; if (!mdlCmn.GET_kiji(strPkiji_id, ref intBig_category_id, ref intSmall_category_id, ref intKiji_id, ref strKeywords, ref strTitle, ref strKijiData, ref strOgimage, ref strDescription, ref strInsDate, ref strUpDate, ref PublicFlg, ref InvisibleFlg)) { return; } txtPID.Text = strPkiji_id; txtBID.Text = intBig_category_id.ToString(); txtSID.Text = intSmall_category_id.ToString(); txtKID.Text = intKiji_id.ToString(); txtKeywords.Text = strKeywords; txtTitle.Text = strTitle; txtKijiData.Text = strKijiData; txtOGImage.Text = strOgimage; txtDescription.Text = strDescription; txtInsDate.Text = strInsDate; txtUpdate.Text = strUpDate; txtPublicFlg.Text = PublicFlg.ToString(); txtInvisibleFlg.Text = InvisibleFlg.ToString(); }ボタンをクリックした時、その行のデータがそれぞれのコントロールに転写されましたね。今度はいよいよ登録ボタンを押してデータをインサートまたはアップデートできるようにします。仕様としましては入力されているpKiji_idがデータベースに存在している場合はデータの更新(アップデート)をし、pKiji_idが存在していないなら新規のデータとみなしインサートするようにします。
まずはModules.mdlCommon.csに下記のpKiji_idをチェックするメソッドを追加しました。
// Pkiji_idチェック public bool Check_pkijiID(string pkiji_id) { SqlDataReader sqlRdr = null; StringBuilder strSql = new StringBuilder(); string strCheck = ""; strSql.Append("SELECT pkiji_id "); strSql.Append("FROM m_kiji "); strSql.Append("WHERE pkiji_id = "); strSql.Append(pkiji_id); try { if (!db.DB_Connect()) { return false; } if (!db.DB_SqlExeScalar(strSql.ToString(), ref strCheck)) { return false; } if (strCheck != "") { // Pkiji_idが存在している return true; } else { // Pkiji_idが存在していない return false; } } catch (Exception ex) { return false; } finally { if (sqlRdr != null) { if (!sqlRdr.IsClosed) { sqlRdr.Close(); } } db.DB_Close(); } }
MasterForm.aspxに戻って登録ボタンのコントロールをダブルクリックします。btnPost_Clickのメソッドに下記のコードを追加しました。
protected void btnPost_Click(object sender, EventArgs e) { SqlDataReader sqlRdr = null; StringBuilder strSql = new StringBuilder(); int intPublicFlg = 0; int intInvisibleFlg = 0; string strToday = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); if (txtPublicFlg.Text == "True") { intPublicFlg = 1; } else { intPublicFlg = 0; } if (txtInvisibleFlg.Text == "True") { intInvisibleFlg = 1; } else { intInvisibleFlg = 0; } if (mdlCmn.Check_pkijiID(txtPID.Text.Trim())) { // 既存の記事の更新 strSql.Append("UPDATE m_kiji "); strSql.Append(" SET pkiji_id = '" + txtPID.Text.Trim() + "'"); strSql.Append(" , big_category_id = " + txtBID.Text); strSql.Append(" , small_category_id = " + txtSID.Text); strSql.Append(" , kiji_id = " + txtKID.Text); strSql.Append(" , keywords = '" + txtKeywords.Text + "'"); strSql.Append(" , title = '" + txtTitle.Text + "'"); strSql.Append(" , kiji_data = '" + txtKijiData.Text + "'"); strSql.Append(" , ogimage = '" + txtOGImage.Text + "'"); strSql.Append(" , description = '" + txtDescription.Text + "'"); strSql.Append(" , ins_date = '" + txtInsDate.Text + "'"); strSql.Append(" , up_date = '" + strToday + "'"); strSql.Append(" , public_flg = " + intPublicFlg); strSql.Append(" ,invisible_flg = " + intInvisibleFlg); strSql.Append(" WHERE pkiji_id = '" + txtPID.Text.Trim() + "'"); } else { // 新しい記事の登録 strSql.Append("INSERT INTO m_kiji "); strSql.Append("(pkiji_id "); strSql.Append(", big_category_id "); strSql.Append(", small_category_id "); strSql.Append(", kiji_id "); strSql.Append(", keywords "); strSql.Append(", title "); strSql.Append(", kiji_data "); strSql.Append(", ogimage "); strSql.Append(", description "); strSql.Append(", ins_date "); strSql.Append(", up_date "); strSql.Append(", public_flg "); strSql.Append(", invisible_flg) "); strSql.Append("VALUES "); strSql.Append("( "); strSql.Append(txtPID.Text); strSql.Append(" ," + txtBID.Text); strSql.Append(" ," + txtSID.Text); strSql.Append(" ," + txtKID.Text); strSql.Append(" ,'" + txtKeywords.Text + "'"); strSql.Append(" ,'" + txtTitle.Text + "'"); strSql.Append(" ,'" + txtKijiData.Text + "'"); strSql.Append(" ,'" + txtOGImage.Text + "'"); strSql.Append(" ,'" + txtDescription.Text + "'"); strSql.Append(" ,'" + txtInsDate.Text + "'"); strSql.Append(" ,NULL"); strSql.Append(" ," + intPublicFlg); strSql.Append(" ," + intInvisibleFlg); strSql.Append(")"); } try { if (!db.DB_Connect()) { return; } if (!db.DB_SqlExeNonQuery(strSql.ToString())) { return; } if (!db.DB_Close()) { return; } GET_GridView(); return; } catch (Exception ex) { return; } finally { if (sqlRdr != null) { if (!sqlRdr.IsClosed) { sqlRdr.Close(); } } } }pKiji_idが存在すればデータを更新し、存在していなければ新規データの登録という形にできました。ここで紹介したコードはあくまでデータの更新と登録をすることに趣を置いています。実際は入力チェックを行ったり、pubic_flgやinvisible_flgなどはドロップボックスのコントロールを使って簡単にフラグのON OFFを切り替えできるようにしたりすると操作性が上がります。
このMasterForm.aspxに画像ファイルをアップロードするコントロールを追加したいと思いますが、長くなっているので整理をするという意味で別のフォームを作成してレクチャーしたいと思います。
このコード記事データをデータベースに格納する時にサニタイズしていないわね。
サニタイズとは何ですか?
サニタイズとはダブルクオーテーション(")などの特殊記号を別の文字に置き換えることだよ。データベースのSQL文は特殊記号を使うから格納するデータに特殊記号が混じっていると上手く登録できなかったり、不具合が起こったりする可能性があるんだ。だから取り出しと挿入にReplaceをかけて対応してください。