ASP.NET MVC5(C#)でURLのパラメータを受け取ってViewを制御する方法
前回やったプログラミングの要領で今度は記事ページの作成もしてみましょう! 先に仕様の方を説明します。データベースの大カテゴリーの分だけコントローラーを追加します。 データベース大カテゴリーにbig_urlrootがありますね。これを使って
プログラミングのページはhttp://yigao.jp/programming/
CG素材のページはhttp://yigao.jp/cg/
といった具合にしたいです。この第二階層にあるprogrammingやcgなどはコントローラーを作成することで対応できます。重要なのはコントローラー名です。では例としてプログラミングのページ作成をレクチャーします。
big_urlrootが「programming」なのでコントローラー名は頭文字を大文字にして「ProgrammingContoller.cs」というファイルを作成します。
手順はソリューションエクスプローラーのControllersのフォルダを右クリックして「追加」の「コントローラー」を選択します。
MVC 5 controller - Emptyを選択して追加ボタンを押します。
コントローラー名に「ProgrammingController」と打ってAddボタンを押します。
Viewsに「Programming」というフォルダが作成されていると思います。無ければフォルダを作成してください。「Programming」フォルダにIndex.cshtmlファイルを作成します。
「追加」の「ビュー」を選択してください。
View_name:に「Index」と入力し
Template:に「Empty (without model)」を選択し
Options:は全てチェックボックスを外します。
上記の設定でAddボタンを押します。
同じ要領でSharedフォルダにDefault.cshtmlを作成します。
このファイルにHTMLをごりごりと書いていきます。トップページとデザインはほとんど変わらないのが普通なので、Top.cshtmlのコードを流用しましょう!
HTMLのコードの最下部に@RenderBody()を忘れずに記述します。
Views/Programming/Index.cshtmlに作成したDefault.cshtmlを関連付けます。
Views/Programming/Index.cshtmlを開いていったん記述されているコードを全て削除して、下記コードを新しく記述します。
@{ Layout = "~/Views/Shared/Default.cshtml"; }これでデバッグしてみます。
URLに/programming/をくっつけてアクセスしてみるとページが表示されました!
今度はデータベースよりデータを取得するコードを書いていきましょう。
/Modules/mdlCommon.csを開いてメソッドを追加します。
追加したメソッドはこちら
public bool GET_kiji(string strBigUrlroot, string strSmallUrlroot, string strKijiID, ref string strTitle, ref string strKijiData, ref string strInsDate, ref string strUpDate) { SqlDataReader sqlRdr = null; StringBuilder strSql = new StringBuilder(); string strBig_ID = ""; string strSmall_ID = ""; try { if (strKijiID == "" || strKijiID == null) { strKijiID = "0"; } if (!GET_Category_ID(strBigUrlroot, strSmallUrlroot, ref strBig_ID, ref strSmall_ID)) { return false; } strSql.Append("SELECT k.title, k.kiji_data, k.ins_date, k.up_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("WHERE k.big_category_id = "); strSql.Append(strBig_ID); strSql.Append(" "); strSql.Append("AND k.small_category_id = "); strSql.Append(strSmall_ID); strSql.Append(" "); strSql.Append("AND k.kiji_id = "); strSql.Append(strKijiID); if (!db.DB_Connect()) { return false; } if (!db.DB_SqlReader(strSql.ToString(), ref sqlRdr)) { return false; } while (sqlRdr.Read()) { strTitle = sqlRdr["title"].ToString(); strKijiData = sqlRdr["kiji_data"].ToString(); strInsDate = sqlRdr["ins_date"].ToString(); strUpDate = sqlRdr["up_date"].ToString(); } return true; } catch (Exception ex) { return false; } finally { if (sqlRdr != null) { if (!sqlRdr.IsClosed) { sqlRdr.Close(); } } db.DB_Close(); } } public bool GET_Category_ID(string strBigName, string strSmallName, ref string strBig_ID, ref string strSmall_ID) { SqlDataReader sqlRdr = null; StringBuilder strSql = new StringBuilder(); bool blnSmallFlg = false; strSql.Append("SELECT k.big_category_id, k.small_category_id "); strSql.Append("FROM m_kiji k "); strSql.Append("INNER JOIN c_big_category b "); strSql.Append("ON k.big_category_id = b.big_category_id "); strSql.Append("INNER 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("WHERE big_urlroot = '"); strSql.Append(strBigName); strSql.Append("' "); if (strSmallName != null && strSmallName != "" && strSmallName != "0") { blnSmallFlg = true; strSql.Append("AND small_urlroot = '"); strSql.Append(strSmallName); strSql.Append("'"); } try { if (!db.DB_Connect()) { return false; } if (!db.DB_SqlReader(strSql.ToString(), ref sqlRdr)) { return false; } while (sqlRdr.Read()) { strBig_ID = sqlRdr["big_category_id"].ToString(); if (blnSmallFlg) { strSmall_ID = sqlRdr["small_category_id"].ToString(); } else { strSmall_ID = "0"; } break; } return true; } catch (Exception ex) { return false; } finally { if (sqlRdr != null) { if (!sqlRdr.IsClosed) { sqlRdr.Close(); } } db.DB_Close(); } }下にあるGET_Category_ID()メソッドがURL(big_urlrootとsmall_urlroot)でもらった文字列からbig_category_idとsmall_category_idを検索して取得します(これがないと記事データを検索できません)。 カテゴリーID(big_category_idとsmall_category_id)を使ってGET_kiji()が記事データを取得しています。
ProgrammingController.csを開いて作成したメソッドを呼び出す処理を書きましょう。
下記のように書きました。
using System.Web.Mvc; using mdlCommon; namespace WebSite.Controllers { public class ProgrammingController : Controller { CmnOpn mdlCmn = new CmnOpn(); const string strBigcategory = "programming"; // GET: Programming public ActionResult Index() { string strTitle = ""; string strKijiData = ""; string strInsDate = ""; string strUpDate = ""; if (!mdlCmn.GET_kiji(strBigcategory, "", "", ref strTitle, ref strKijiData, ref strInsDate, ref strUpDate)) { // エラーページのViewを表示 } ViewBag.Title = strTitle; ViewBag.Kiji = strKijiData; ViewBag.InsDate = strInsDate; ViewBag.UpDate = strUpDate; return View(); } } }Views/Programming/Index.cshtmlも修正しましょう。
下記のように記述しました。
@{ Layout = "~/Views/Shared/Default.cshtml"; } @section Title{@Html.Raw(@ViewBag.Title)} @section Kiji{@Html.Raw(@ViewBag.Kiji)} @section InsDate{@Html.Raw(@ViewBag.InsDate)} @section UpDate{@Html.Raw(@ViewBag.UpDate)}この要領でViews/Shared/default.cshtmlも修正します。
< !DOCTYPE html > < html lang="ja" > < head > < meta charset="utf-8"> < meta name="viewport" content="width=device-width, initial-scale=1" > < title>IT技術部(素材屋) < link rel="stylesheet" type="text/css" href="/Content/css/style.css" > < /head > < body >デバッグをしてみると表示されました。表示されていない方はデータベースに記事がない可能性があります。@RenderPage("_Title.cshtml") @RenderPage("_Topmenu.cshtml")body > html >@RenderSection("Title")
作成日時:@RenderSection("InsDate")
更新日時:@RenderSection("UpDate")
@RenderSection("Kiji")
big_category_id = 1
small_category_id = 0
kiji_id = 0
上記の記述でデータを入れてください。
第二階層
http://yigao.jp/programming/
の記事データは取得することができました。
今度は第三階層
http://yigao.jp/programming/csharp/
の記事を表示できるようにしましょう。
第三階層によるアクセスを取得するにはアクションメソッドを作成する必要があります。例えば大カテゴリー「プログラミング」の中の小カテゴリー「C#」「PHP」「Java」などがある場合、小カテゴリーの分だけProgrammingControllerにアクションメソッドというメソッドを記述しなければなりません。
実際に記述してみましょう。
今回は例としてC#のページを表示する過程を記したいと思います。
まず、ProgrammingControllerに下記を追加します。
public ActionResult csharp() { return View("~/Views/Programming/index.cshtml"); }画像も載せておきます。
これでデバッグして表示してみましょう。
http://localhost:62326/Programming/csharp/
ルーティングが上手くいき、ページが表示されたと思います。コードを追加して記事データを取得できるようにしましょう。
csharpのアクションメソッドを下記のように修正しました。
public ActionResult csharp() { // アクションメソッドの文字列(csharp)を取得 string strSmallcategory = System.Reflection.MethodBase.GetCurrentMethod().Name.ToString(); string strTitle = ""; string strKijiData = ""; string strInsDate = ""; string strUpDate = ""; if (!mdlCmn.GET_kiji(strBigcategory, strSmallcategory, "", ref strTitle, ref strKijiData, ref strInsDate, ref strUpDate)) { // エラーページのViewを表示 } ViewBag.Title = strTitle; ViewBag.Kiji = strKijiData; ViewBag.InsDate = strInsDate; ViewBag.UpDate = strUpDate; return View("~/Views/Programming/index.cshtml"); }データベースに
big_category_id = 1
small_category_id = 1
kiji_id = 0
のデータを入れてデバッグしてみましょう。localhost/programming/csharp/にアクセス。 ちゃんと表示されましたね!
最後に第四階層の
http://yigao.jp/programming/csharp/1/
のページを取得できるようにしましょう。
アクションメソッドを下記のように2箇所修正します。
public ActionResult csharp(string id) { // アクションメソッドの文字列(csharp)を取得 string strSmallcategory = System.Reflection.MethodBase.GetCurrentMethod().Name.ToString(); string strTitle = ""; string strKijiData = ""; string strInsDate = ""; string strUpDate = ""; if (!mdlCmn.GET_kiji(strBigcategory, strSmallcategory, id, ref strTitle, ref strKijiData, ref strInsDate, ref strUpDate)) { // エラーページのViewを表示 } ViewBag.Title = strTitle; ViewBag.Kiji = strKijiData; ViewBag.InsDate = strInsDate; ViewBag.UpDate = strUpDate; return View("~/Views/Programming/index.cshtml"); }1行目の(string id)のidの方に記事番号(localhost/programming/csharp/1/)の数字が入ってきます。 データベースに
big_category_id = 1
small_category_id = 1
kiji_id = 1
のデータを入れてデバッグしてみましょう。
http://localhost:62326/Programming/csharp/1/
ちゃんと表示できました。
番外編
第五階層以上のURLを生成するためにはどうしたらよいのでしょうか。
案としては、大カテゴリーと小カテゴリーの間に中カテゴリーのテーブルをデータベースに作成して、ASP.NET MVC側ではソリューションエクスプローラーのトップにあるApp_Start/RouteConfig.csに
routes.MapRoute( "Default", // ルート名. "{controller}/{action}/{small_id}/{kiji_id}", // パラメーター付きの URL new { controller = "Top", action = "Index", small_id = UrlParameter.Optional, kiji_id = UrlParameter.Optional } // パラメーターの既定値 );とするとよさそう。簡単に説明すると{controller}が大カテゴリー、{action}が中カテゴリー、{small_id}が小カテゴリー、{kiji_id}が記事番号を表しています。小カテゴリーと記事番号はアクションメソッドの引数で受け取ります。
コントローラーのアクションメソッドを
public ActionResult csharp(string small_id, string kiji_id)としてください。
気付いたのですがURLが http://localhost:62326/Programming/csharp/1/ Programmingの頭文字が大文字になっています。非常に気になるので修正しましょう。こちらの記事に対応方法が書いてありました!
http://blog.shibayan.jp/entry/20131030/1383142007
App_Start/RouteConfig.csに
routes.LowercaseUrls = true;
上記コードを付け加えます。
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Routing; namespace WebSite { public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); // URL は小文字にする routes.LowercaseUrls = true; routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Top", action = "Index", id = UrlParameter.Optional } ); } } }最終的にできたコードがこちら。これでも反映されていない現象にあいました。外国の掲示板ではバグではないかと言われています。ブラウザのキャッシュをクリアしたりして対応してください。
だいぶ駆け足ね。
すみません。もっと初心者の方にも分かりやすいようにいつか電子書籍にでもして公開したいと考えています。