みなさんこんにちは
ひろぽんです!
ASP.NETでWEB開発をしていて、ViewからControllerにModel以外の引数を渡したい!って思うことありませんか?
私は割とあります。
例えば、記事一覧ページからコメントを投稿する場合等、リレーションの設定をしたい場合に!
上記のように記事一覧ページからコメントを投稿する場合、Controllerはあくまでもコメントになり、メソッドはCreateになります。
ですが普通にModelだけ投げてしまうと、コメントと記事が紐づきません。
そんな時に、Modelと記事のIdを投げてあげると、コメントのController内でコメントと記事の紐づけができますよね!
今回はそんな場合等に使える、ASP.NETでViewからControllerにActionLinkを使ってModel以外の値を投げる方法について書いていきます!
前提となるMODEL
💡 Controller の役割や Form_Load 的な理解については別記事 Controller は WinForms の Form_Load 拡張版 で WinForms 経験者向けに書いてます。
public class Article
{
public int id { get; set; }
public string title { get; set; }
public string body { get; set; }
public DateTime created { get; set; }
public DateTime updated { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
}</code></pre></div>
記事のModelはこんな感じですね!
public class Comment
{
public int id { get; set; }
public string title { get; set; }
public string body { get; set; }
public DateTime created { get; set; }
public DateTime updated { get; set; }
public virtual Article Article { get; set; }
}</code></pre></div>
コメントのModelも記事と同じです。
基本的にタイトルがあって本文がある。といった形です。
記事1対コメント多になっているのが特徴ですかね!
では続いてスキャフォールドですが今回必要なのは、CommentのControllerのCreateとArticlesのDetailsのViewなので、その部分のみ書いていきます!
まずはCommentのCreateメソッドから!
// POST: Comments/Create
// 過多ポスティング攻撃を防止するには、バインド先とする特定のプロパティを有効にしてください。
// 詳細については、https://go.microsoft.com/fwlink/?LinkId=317598 を参照してください。
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "id,title,body,created,updated")] Comment comment)
{
if (ModelState.IsValid)
{
db.Comments.Add(comment);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(comment);
}</code></pre></div>
このCreateメソッドにArticleIdを引数に受け取るようにして、Create実行時に記事と紐づくようにすると以下のようになります。
// POST: Comments/Create
// 過多ポスティング攻撃を防止するには、バインド先とする特定のプロパティを有効にしてください。
// 詳細については、https://go.microsoft.com/fwlink/?LinkId=317598 を参照してください。
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "id,title,body,created,updated")] Comment comment,int articleId)
{
var article = db.Articles.FirstOrDefault(a => a.id == articleId);
if (ModelState.IsValid)
{
comment.Article = article;
db.Comments.Add(comment);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(comment);
}</code></pre></div>
引数にarticleIdを設定して、Create実行時にデータベースから引数のarticleIdの記事を取得し、CommentのArticleにセットする。
これだけで、リレーションが登録されるってめちゃくちゃ便利ですね。
SQLならなかなかややこしいことを書かないといけないのに、Asp.Netではその辺はあまり意識することないので、便利ですね!!!
では続いて、ArticleのDetailsのViewからCommentのCreateを呼び出し引数articleIdを渡す作業!
@model WebApplication1.Models.Article
@{
ViewBag.Title = "Details";
}
<h2>Details</h2>
<div>
<h4>Article</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.title)
</dt>
<dd>
@Html.DisplayFor(model => model.title)
</dd>
<dt>
@Html.DisplayNameFor(model => model.body)
</dt>
<dd>
@Html.DisplayFor(model => model.body)
</dd>
<dt>
@Html.DisplayNameFor(model => model.created)
</dt>
<dd>
@Html.DisplayFor(model => model.created)
</dd>
<dt>
@Html.DisplayNameFor(model => model.updated)
</dt>
<dd>
@Html.DisplayFor(model => model.updated)
</dd>
</dl>
</div>
<p>
@Html.ActionLink("Edit", "Edit", new { id = Model.id }) |
@Html.ActionLink("Back to List", "Index")
</p>
なんの変哲もないArticleのDetailsのViewにコメント追加リンクを追加します!
@model WebApplication1.Models.Article
@{
ViewBag.Title = "Details";
}
<h2>Details</h2>
<div>
<h4>Article</h4>
<hr />
<dl class="dl-horizontal">
<dt>
@Html.DisplayNameFor(model => model.title)
</dt>
<dd>
@Html.DisplayFor(model => model.title)
</dd>
<dt>
@Html.DisplayNameFor(model => model.body)
</dt>
<dd>
@Html.DisplayFor(model => model.body)
</dd>
<dt>
@Html.DisplayNameFor(model => model.created)
</dt>
<dd>
@Html.DisplayFor(model => model.created)
</dd>
<dt>
@Html.DisplayNameFor(model => model.updated)
</dt>
<dd>
@Html.DisplayFor(model => model.updated)
</dd>
</dl>
</div>
@Html.ActionLink("コメントを追加","Create",new { Controller = "Comments",articleId = Model.id})
<p>
@Html.ActionLink("Edit", "Edit", new { id = Model.id }) |
@Html.ActionLink("Back to List", "Index")
</p>
実際に触ってみるとこんな感じになります!

トップ画面には、ArticleのIndexを設定しました!
ArticleのDetailsを見てみると

コメント追加リンクが設定されています!
ここから実際にコメントを追加してみます!


コメントが登録されました!
これでArticleIdが実際に紐づいていたらOKですね!

紐づいている!
OKです!
以上
💡 補足: 業務系の現場でよくハマるパターン
俺もこの ActionLink のリンク生成、過去案件でハマったところを3つ並べておきます。
① ルーティング順序のミスでリンクが効かない
RouteConfig.cs に書いた MapRoute の順序で URL が解決される。デフォルトの {controller}/{action}/{id} より下にカスタムルートを書くと、デフォルトに先に拾われて404。順序めっちゃ大事。
② パラメータ名と Action 引数名の不一致で null
@Html.ActionLink("詳細", "Detail", new { userId = 1 }) で Controller 側が public ActionResult Detail(int id) だと、 userId じゃなくて id を期待してるので null になる。名前を完全一致させる。
③ HTML 属性指定で htmlAttributes に null を渡す罠
ActionLink のオーバーロードは引数順序が紛らわしい。 @Html.ActionLink("text", "action", new { id = 1 }, null) の null 部分が htmlAttributes 指定。 ここを省略すると routeValues として認識されない場合があるので、明示的に null か new {} を渡す。
❓ よくある質問
Q1. ActionLink と Url.Action の違いは?
A. ActionLink は <a> タグまで生成、 Url.Action は URL 文字列だけ返す。 jQuery で動的にリンク作る時は Url.Action。 ビューに直接書くなら ActionLink。
Q2. RouteValueDictionary を使うべきタイミングは?
A. パラメータ名が動的に決まる場合(変数のキー名で渡す)。 静的な場合は匿名型 new { id = 1 } で十分。
Q3. Area ある時の ActionLink の書き方は?
A. routeValues に area = "AreaName" を入れる。 @Html.ActionLink("text","action","controller",new { area = "Admin", id = 1 }, null) という感じ。
Q4. POST 用のリンクを作るには?
A. ActionLink は GET のみ。 POST したいなら Html.BeginForm() + submit ボタン、または jQuery で form 動的生成。 業務系では POST リンク禁止(CSRF 対策上)。
Q5. ASP.NET Core での書き方は?
A. asp-controller / asp-action / asp-route-id 等の TagHelper で書く。 <a asp-controller="Home" asp-action="Index">Home</a> という感じ。 ActionLink より読みやすい。
📚 関連記事
- Controller は WinForms の Form_Load 拡張版 — WinForms 経験者向け Controller 入門
- FormとFormの間で値の共有・受け渡し — WinForms 版の画面遷移
- DataGridViewにDataTable反映 — WinForms での一覧表示
- Formの中にFormを表示して切り替え — Master/Detail 構造
- VB.netで右からの文字列を取得 — VB.net 文字列処理
目次







コメント