C# ActionResultとは?IActionResultとの違い・戻り値・使い方を初心者向けに徹底解説
はじめに
C#でASP.NET MVCやASP.NET Core MVCを学び始めると、Controllerの戻り値としてActionResultという型がよく登場します。
たとえば、次のようなコードを見たことがあるかもしれません。
C#public ActionResult Index()
{
return View();
}
また、ASP.NET Coreでは次のようにIActionResultやActionResult<T>が使われることもあります。
C#public IActionResult Index()
{
return View();
}
C#public ActionResult<Product> GetProduct(int id)
{
return product;
}
C#初心者にとっては、ActionResult、IActionResult、ActionResult<T>の違いが分かりにくく、「結局どれを使えばいいのか」「return View()との関係は何なのか」と迷いやすいポイントです。
この記事では、C#におけるActionResultの基本から、主な戻り値の種類、IActionResultやActionResult<T>との違い、実務での使い分けまで、初心者にも分かりやすく解説します。
1. C#のActionResultとは?まず押さえるべき基本
ActionResultとは、ASP.NET MVCやASP.NET Core MVCにおいて、ControllerのアクションメソッドがHTTPレスポンスを返すために使う戻り値の型です。
Webアプリケーションでは、ユーザーがURLにアクセスしたり、ボタンをクリックしたりすると、サーバー側のControllerに処理が渡されます。その処理結果として、画面を表示したり、JSONデータを返したり、別ページへリダイレクトしたりします。
この「処理結果」を表すために使われるのがActionResultです。
1-1. ActionResultはASP.NET MVC / ASP.NET Core MVCで使う戻り値の型
ActionResultは、Controllerのアクションメソッドの戻り値として使われます。
C#public ActionResult Index()
{
return View();
}
この例では、Indexアクションが実行されると、View()によって画面表示用の結果が返されます。
ActionResultは、単にデータを返すだけの型ではありません。HTTPレスポンスとして「何を返すか」を表す型です。
たとえば、以下のような結果を返せます。
C#return View();
return Json(data);
return RedirectToAction("Index");
return NotFound();
return BadRequest();
return Ok();
このように、ActionResultを使うことで、Controllerからさまざまな種類のレスポンスを返せます。
1-2. ControllerのアクションメソッドがHTTPレスポンスを返すための仕組み
ASP.NET MVCやASP.NET Core MVCでは、URLへのリクエストに対してControllerのアクションメソッドが実行されます。
たとえば、次のようなURLにアクセスしたとします。
/Products/Details/1
この場合、一般的にはProductsControllerのDetailsアクションが呼び出されます。
C#public ActionResult Details(int id)
{
var product = GetProduct(id);
if (product == null)
{
return NotFound();
}
return View(product);
}
このアクションでは、商品データが見つからない場合はNotFound()を返し、見つかった場合はView(product)を返しています。
つまり、ActionResultは「リクエストに対してどのようなレスポンスを返すか」を表す役割を持っています。
1-3. ActionResultを使うとView・JSON・リダイレクト・ステータスコードを返せる
ActionResultの大きな特徴は、複数の種類のレスポンスを1つの戻り値の型で扱えることです。
たとえば、画面を表示する場合はView()を返します。
C#public ActionResult Index()
{
return View();
}
JSONデータを返す場合はJson()を使います。
C#public ActionResult GetData()
{
var data = new { Id = 1, Name = "Sample" };
return Json(data);
}
別のアクションへ移動させたい場合はRedirectToAction()を使います。
C#public ActionResult Create()
{
return RedirectToAction("Index");
}
エラーやステータスコードを返す場合は、NotFound()やBadRequest()などを使います。
C#public ActionResult Details(int id)
{
if (id <= 0)
{
return BadRequest();
}
return Ok();
}
このように、ActionResultはWebアプリケーションのさまざまなレスポンスを表現できます。
1-4. C#初心者が混同しやすい「戻り値」と「画面表示」の違い
初心者が混同しやすいのが、「戻り値」と「画面表示」の違いです。
C#の通常のメソッドでは、戻り値といえば数値や文字列、オブジェクトなどをイメージするかもしれません。
C#public int Add(int a, int b)
{
return a + b;
}
しかし、Controllerのアクションメソッドでは、戻り値は単なる値ではなく、HTTPレスポンスを表します。
C#public ActionResult Index()
{
return View();
}
この場合、View()は「画面を直接表示している」のではなく、「Viewを使ってHTMLレスポンスを生成する結果」を返しています。
つまり、return View();は画面そのものを返しているのではなく、最終的にブラウザへ返すレスポンスを作るための結果を返していると考えると理解しやすくなります。
2. ActionResultが使われる場面と全体像
ActionResultは、ASP.NET MVCやASP.NET Core MVCでControllerが処理結果を返す場面で使われます。
主な場面は次のとおりです。
C#return View();
return Json(data);
return RedirectToAction("Index");
return NotFound();
return BadRequest();
return File(bytes, "application/pdf");
Webページを表示する場合にも、APIとしてJSONを返す場合にも、エラー処理にも使われます。
2-1. MVCパターンにおけるControllerとActionResultの役割
MVCとは、アプリケーションを以下の3つに分けて設計する考え方です。
| 要素 | 役割 |
|---|---|
| Model | データやビジネスロジックを扱う |
| View | 画面表示を担当する |
| Controller | リクエストを受け取り、処理結果を返す |
Controllerは、ユーザーからのリクエストを受け取り、必要に応じてModelからデータを取得し、最終的にActionResultを返します。
C#public class ProductsController : Controller
{
public ActionResult Index()
{
var products = GetProducts();
return View(products);
}
}
この例では、Controllerが商品一覧データを取得し、View(products)を返しています。
Controllerの役割は、処理の流れを制御し、最終的なレスポンスの種類を決めることです。その結果を表すのがActionResultです。
2-2. Webページを表示する場合のActionResult
Webページを表示する場合は、View()を返すのが一般的です。
C#public ActionResult Index()
{
return View();
}
Viewにデータを渡したい場合は、モデルを引数として渡します。
C#public ActionResult Details(int id)
{
var product = new Product
{
Id = id,
Name = "ノートパソコン",
Price = 120000
};
return View(product);
}
この場合、Details.cshtmlなどのViewファイルに商品データを渡し、HTMLを生成してブラウザへ返します。
MVCで画面を表示するControllerでは、ActionResultやIActionResultが頻繁に使われます。
2-3. APIでJSONデータを返す場合のActionResult
Web APIでは、HTML画面ではなくJSONデータを返すことが多くなります。
C#public ActionResult GetProduct()
{
var product = new
{
Id = 1,
Name = "キーボード",
Price = 5000
};
return Json(product);
}
ASP.NET Core Web APIでは、Ok()を使ってJSONとして返すこともよくあります。
C#public IActionResult GetProduct()
{
var product = new
{
Id = 1,
Name = "キーボード",
Price = 5000
};
return Ok(product);
}
この場合、HTTPステータスコード200 OKとともに、商品データがJSON形式で返されます。
2-4. エラー・認証・リダイレクト処理で使うActionResult
ActionResultは、正常な画面表示やデータ返却だけでなく、エラーや認証、リダイレクト処理でも使われます。
たとえば、対象データが存在しない場合はNotFound()を返します。
C#public IActionResult Details(int id)
{
var product = FindProduct(id);
if (product == null)
{
return NotFound();
}
return View(product);
}
入力値が不正な場合はBadRequest()を返します。
C#public IActionResult Update(int id)
{
if (id <= 0)
{
return BadRequest();
}
return Ok();
}
処理完了後に一覧画面へ戻したい場合は、RedirectToAction()を使います。
C#public IActionResult Create()
{
return RedirectToAction("Index");
}
このように、ActionResultはWebアプリケーションの制御に欠かせない戻り値の型です。
3. ActionResultの主な戻り値の種類
ActionResultには、さまざまな具体的な戻り値があります。
代表的なものは次のとおりです。
| 種類 | 用途 |
|---|---|
| ViewResult | Viewを表示する |
| JsonResult | JSONを返す |
| RedirectResult | 指定URLへリダイレクトする |
| RedirectToActionResult | 指定アクションへリダイレクトする |
| ContentResult | 文字列やHTMLを返す |
| FileResult | ファイルを返す |
| StatusCodeResult | HTTPステータスコードを返す |
| NotFoundResult | 404 Not Foundを返す |
| BadRequestResult | 400 Bad Requestを返す |
| OkResult | 200 OKを返す |
それぞれの違いを理解すると、Controllerの戻り値を適切に選べるようになります。
3-1. ViewResult:Viewを返して画面を表示する
ViewResultは、Razor ViewなどのViewを使ってHTML画面を表示するための結果です。
通常は、Controller内でView()メソッドを呼び出して返します。
C#public ActionResult Index()
{
return View();
}
Viewにモデルを渡す場合は、次のように書きます。
C#public ActionResult Details()
{
var product = new Product
{
Id = 1,
Name = "マウス",
Price = 3000
};
return View(product);
}
戻り値の型を明確にViewResultと書くこともできます。
C#public ViewResult Index()
{
return View();
}
ただし、実務では将来的にNotFound()やRedirectToAction()を返す可能性もあるため、ActionResultやIActionResultを使うことが多いです。
3-2. JsonResult:JSON形式のデータを返す
JsonResultは、オブジェクトをJSON形式で返すための結果です。
C#public JsonResult GetData()
{
var user = new
{
Id = 1,
Name = "Yamada"
};
return Json(user);
}
戻り値をActionResultにしても問題ありません。
C#public ActionResult GetData()
{
var user = new
{
Id = 1,
Name = "Yamada"
};
return Json(user);
}
APIでは、Json()よりもOk()やActionResult<T>を使うことも多いです。
C#public IActionResult GetUser()
{
var user = new
{
Id = 1,
Name = "Yamada"
};
return Ok(user);
}
3-3. RedirectResult / RedirectToActionResult:別ページへ遷移させる
RedirectResultは、指定したURLへリダイレクトするための結果です。
C#public ActionResult GoToGoogle()
{
return Redirect("https://www.google.com");
}
一方、RedirectToActionResultは、Controller内の別アクションへリダイレクトするときに使います。
C#public ActionResult Create()
{
// 登録処理
return RedirectToAction("Index");
}
別のControllerのアクションへリダイレクトする場合は、Controller名も指定できます。
C#public ActionResult Create()
{
return RedirectToAction("Details", "Products", new { id = 1 });
}
MVCアプリケーションでは、フォーム送信後に再読み込みによる二重登録を防ぐため、登録完了後にRedirectToAction()を使うことがよくあります。
3-4. ContentResult:文字列やHTMLなどのコンテンツを返す
ContentResultは、文字列をそのままレスポンスとして返すための結果です。
C#public ContentResult Hello()
{
return Content("Hello, ASP.NET Core!");
}
戻り値をActionResultにしても使えます。
C#public ActionResult Hello()
{
return Content("Hello, ASP.NET Core!");
}
HTML文字列を返すこともできます。
C#public ActionResult Html()
{
return Content("<h1>Hello</h1>", "text/html");
}
ただし、HTMLを直接文字列で返すよりも、通常はViewを使って画面を作成する方が保守しやすくなります。
3-5. FileResult:ファイルを返す
FileResultは、PDF、画像、CSVなどのファイルを返すための結果です。
C#public IActionResult Download()
{
byte[] fileBytes = System.IO.File.ReadAllBytes("sample.pdf");
return File(fileBytes, "application/pdf", "sample.pdf");
}
CSVファイルを返す例は次のとおりです。
C#public IActionResult DownloadCsv()
{
var csv = "Id,Name\n1,Yamada\n2,Suzuki";
var bytes = System.Text.Encoding.UTF8.GetBytes(csv);
return File(bytes, "text/csv", "users.csv");
}
ファイルダウンロード機能を作る場合、File()メソッドを使うと便利です。
3-6. StatusCodeResult:HTTPステータスコードを返す
StatusCodeResultは、HTTPステータスコードのみを返したい場合に使います。
C#public IActionResult Error()
{
return StatusCode(500);
}
ステータスコードとメッセージを一緒に返すこともできます。
C#public IActionResult Error()
{
return StatusCode(500, "サーバーエラーが発生しました。");
}
APIでは、処理結果に応じて適切なHTTPステータスコードを返すことが重要です。
3-7. NotFoundResult・BadRequestResult・OkResultなどの代表的な結果
ASP.NET Coreでは、よく使うステータスコードを簡単に返せるメソッドが用意されています。
C#return Ok();
return Ok(data);
return BadRequest();
return BadRequest("入力値が不正です。");
return NotFound();
return NotFound("データが見つかりません。");
return Unauthorized();
return Forbid();
代表的な結果は次のとおりです。
| メソッド | 結果 | 意味 |
|---|---|---|
| Ok() | 200 OK | 正常に処理できた |
| BadRequest() | 400 Bad Request | リクエスト内容が不正 |
| Unauthorized() | 401 Unauthorized | 認証が必要 |
| Forbid() | 403 Forbidden | 権限がない |
| NotFound() | 404 Not Found | 対象が見つからない |
| StatusCode(500) | 500 Internal Server Error | サーバー側エラー |
これらを適切に使うことで、クライアント側が処理結果を判断しやすくなります。
4. ActionResultの基本的な使い方
ここからは、ActionResultの基本的な使い方をコードで確認していきます。
Controllerのアクションメソッドでは、戻り値の型にActionResultやIActionResultを指定し、処理結果に応じてView()、Json()、RedirectToAction()、NotFound()などを返します。
4-1. ControllerでActionResultを戻り値に指定する基本構文
基本構文は次のとおりです。
C#public ActionResult アクション名()
{
return 戻り値;
}
具体例は次のようになります。
C#public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}
ASP.NET Coreでは、IActionResultを使うことも多いです。
C#public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
どちらも、アクションメソッドがレスポンス結果を返すために使います。
4-2. View()を返すサンプルコード
Viewを返す基本例です。
C#public class ProductsController : Controller
{
public ActionResult Index()
{
return View();
}
}
Viewにデータを渡す場合は、モデルを作成してView()の引数に渡します。
C#public class ProductsController : Controller
{
public ActionResult Details(int id)
{
var product = new Product
{
Id = id,
Name = "モニター",
Price = 25000
};
return View(product);
}
}
この場合、Details.cshtml側では渡されたモデルを使って画面を表示できます。
C#@model Product
<h1>@Model.Name</h1>
<p>@Model.Price 円</p>
4-3. Json()を返すサンプルコード
JSONを返す場合は、Json()を使います。
C#public class ProductsController : Controller
{
public ActionResult GetJson()
{
var product = new
{
Id = 1,
Name = "USBケーブル",
Price = 1200
};
return Json(product);
}
}
このアクションにアクセスすると、次のようなJSONが返されます。
JSON{
"id": 1,
"name": "USBケーブル",
"price": 1200
}
ASP.NET Core Web APIでは、次のようにOk()を使うことも一般的です。
C#[HttpGet]
public IActionResult Get()
{
var product = new
{
Id = 1,
Name = "USBケーブル",
Price = 1200
};
return Ok(product);
}
4-4. RedirectToAction()を返すサンプルコード
登録や更新が完了したあと、一覧画面へ戻したい場合はRedirectToAction()を使います。
C#public class ProductsController : Controller
{
[HttpPost]
public ActionResult Create(Product product)
{
// 登録処理
return RedirectToAction("Index");
}
}
別のControllerへリダイレクトする場合は、Controller名も指定します。
C#return RedirectToAction("Details", "Products", new { id = product.Id });
RedirectToAction()は、指定したアクションへのURLを生成してリダイレクトするため、MVCのルーティングと相性が良い方法です。
4-5. NotFound()・BadRequest()・Ok()を返すサンプルコード
APIや詳細画面では、条件に応じてNotFound()、BadRequest()、Ok()などを返します。
C#[HttpGet]
public IActionResult GetProduct(int id)
{
if (id <= 0)
{
return BadRequest("idは1以上を指定してください。");
}
var product = FindProduct(id);
if (product == null)
{
return NotFound("商品が見つかりません。");
}
return Ok(product);
}
このコードでは、状況に応じて異なるレスポンスを返しています。
| 条件 | 戻り値 |
|---|---|
| idが不正 | BadRequest |
| 商品が存在しない | NotFound |
| 商品が存在する | Ok |
このように、ActionResultやIActionResultを使うと、1つのアクション内で複数の結果を返せます。
4-6. 条件分岐によって異なるActionResultを返す方法
ActionResultの便利な点は、条件によって異なる種類の戻り値を返せることです。
C#public IActionResult Details(int id)
{
if (id <= 0)
{
return BadRequest();
}
var product = FindProduct(id);
if (product == null)
{
return NotFound();
}
if (!User.Identity.IsAuthenticated)
{
return Unauthorized();
}
return View(product);
}
この例では、次のような結果を返しています。
| 条件 | 返す結果 |
|---|---|
| idが0以下 | 400 Bad Request |
| 商品が存在しない | 404 Not Found |
| ログインしていない | 401 Unauthorized |
| 正常 | View |
実務では、入力チェック、データ存在確認、認証・認可チェックを行い、それぞれに適したActionResultを返すことが重要です。
5. ActionResultとIActionResultの違い
C#でASP.NET Coreを学ぶと、ActionResultだけでなくIActionResultもよく登場します。
どちらもControllerのアクションメソッドの戻り値として使えますが、意味には違いがあります。
簡単にいうと、IActionResultはインターフェースで、ActionResultはその実装クラスの一種です。
5-1. IActionResultはインターフェース、ActionResultは実装クラス
IActionResultは、アクションの実行結果を表すインターフェースです。
C#public IActionResult Index()
{
return View();
}
一方、ActionResultはIActionResultを実装するクラスです。
C#public ActionResult Index()
{
return View();
}
ASP.NET Core MVCでは、多くの結果クラスがIActionResultとして扱えます。
C#return View();
return Ok();
return NotFound();
return RedirectToAction("Index");
これらはすべて、アクション結果として返せるオブジェクトです。
初心者向けにまとめると、次のように考えると分かりやすいです。
| 型 | 意味 |
|---|---|
| IActionResult | アクション結果を表す共通のルール |
| ActionResult | アクション結果を表す具体的なクラス |
5-2. IActionResultを使うメリット
IActionResultを使うメリットは、戻り値の自由度が高いことです。
C#public IActionResult Details(int id)
{
if (id <= 0)
{
return BadRequest();
}
var product = FindProduct(id);
if (product == null)
{
return NotFound();
}
return View(product);
}
このように、BadRequest()、NotFound()、View()など、異なる種類の結果を同じメソッドから返せます。
また、IActionResultはインターフェースなので、抽象度が高く、実装の詳細に依存しにくいという特徴があります。
特にASP.NET Core MVCでは、Controllerの戻り値としてIActionResultを使うコードがよく見られます。
5-3. ActionResultを使うメリット
ActionResultを使うメリットは、MVCのアクション結果であることが明確に伝わる点です。
C#public ActionResult Index()
{
return View();
}
また、ASP.NET MVC時代から使われてきた型なので、既存のMVCプロジェクトではActionResultが多く使われている場合があります。
ASP.NET Coreでも、ActionResultは使えます。
C#public ActionResult Details(int id)
{
var product = FindProduct(id);
if (product == null)
{
return NotFound();
}
return View(product);
}
ActionResultは、画面表示を中心としたMVCアプリケーションでも使いやすい戻り値の型です。
5-4. 実務ではどちらを使うべきか
実務では、ASP.NET Core MVCならIActionResultを使うケースが多いです。
C#public IActionResult Index()
{
return View();
}
Web APIで戻り値のデータ型を明確にしたい場合は、ActionResult<T>がよく使われます。
C#public ActionResult<Product> GetProduct(int id)
{
var product = FindProduct(id);
if (product == null)
{
return NotFound();
}
return product;
}
既存のASP.NET MVCプロジェクトでは、ActionResultが使われていることも多いため、プロジェクトの方針に合わせることが大切です。
5-5. 初心者が覚えるべき使い分けの目安
初心者は、まず次の目安で覚えるとよいでしょう。
| 場面 | おすすめの戻り値 |
|---|---|
| MVCで画面を返す | IActionResult または ActionResult |
| ASP.NET Core MVCの一般的なController | IActionResult |
| Web APIでデータを返す | ActionResult<T> |
| 古いASP.NET MVCプロジェクト | ActionResult |
| 戻り値を具体的に限定したい | ViewResult、JsonResultなど |
最初は、IActionResultを基本として覚え、APIではActionResult<T>を検討すると理解しやすいです。
6. ActionResultとActionResult<T>の違い
ActionResult<T>は、ASP.NET Core Web APIでよく使われる戻り値の型です。
ActionResultが「アクション結果」を表すのに対し、ActionResult<T>は「指定したデータ型、またはHTTPレスポンス結果」を返せる型です。
たとえば、商品情報を返すAPIでは次のように書けます。
C#public ActionResult<Product> GetProduct(int id)
{
var product = FindProduct(id);
if (product == null)
{
return NotFound();
}
return product;
}
このコードでは、商品が存在すればProductを返し、存在しなければNotFound()を返しています。
6-1. ActionResult<T>はASP.NET Core Web APIでよく使われる戻り値
Web APIでは、レスポンスとして返すデータ型が重要です。
たとえば、商品詳細APIならProductを返すことが明確な方が、コードを読む人にとって分かりやすくなります。
C#[HttpGet("{id}")]
public ActionResult<Product> Get(int id)
{
var product = FindProduct(id);
if (product == null)
{
return NotFound();
}
return product;
}
ActionResult<Product>と書くことで、このAPIは基本的にProductを返すことが分かります。
一方で、エラー時にはNotFound()やBadRequest()も返せます。
6-2. データ型を明示しながらHTTPレスポンスも返せる
ActionResult<T>のメリットは、データ型を明示しつつ、HTTPレスポンスも柔軟に返せることです。
C#public ActionResult<UserDto> GetUser(int id)
{
if (id <= 0)
{
return BadRequest("idが不正です。");
}
var user = FindUser(id);
if (user == null)
{
return NotFound();
}
return user;
}
この例では、正常時はUserDtoを返し、異常時はBadRequest()やNotFound()を返しています。
もし戻り値を単純にUserDtoにしてしまうと、NotFound()のようなHTTPレスポンス結果を返せません。
C#public UserDto GetUser(int id)
{
// NotFound()を返せない
}
APIでは、正常時のデータだけでなく、異常時のレスポンスも重要です。そのため、ActionResult<T>が便利です。
6-3. ActionResult<T>を使うサンプルコード
以下は、商品情報を取得するAPIのサンプルです。
C#[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
[HttpGet("{id}")]
public ActionResult<ProductDto> GetProduct(int id)
{
if (id <= 0)
{
return BadRequest("idは1以上を指定してください。");
}
var product = FindProduct(id);
if (product == null)
{
return NotFound("商品が見つかりません。");
}
return product;
}
private ProductDto? FindProduct(int id)
{
if (id == 1)
{
return new ProductDto
{
Id = 1,
Name = "ノートパソコン",
Price = 120000
};
}
return null;
}
}
public class ProductDto
{
public int Id { get; set; }
public string Name { get; set; } = "";
public int Price { get; set; }
}
このコードでは、正常時はProductDtoを返し、入力エラー時はBadRequest()、データがない場合はNotFound()を返しています。
6-4. IActionResult・ActionResult・ActionResult<T>の比較表
IActionResult、ActionResult、ActionResult<T>の違いをまとめると次のようになります。
| 戻り値の型 | 特徴 | 主な用途 |
|---|---|---|
| IActionResult | アクション結果を表すインターフェース | ASP.NET Core MVC全般 |
| ActionResult | アクション結果を表すクラス | MVC画面、既存プロジェクト |
| ActionResult<T> | データ型とHTTPレスポンスを両方表せる | ASP.NET Core Web API |
より具体的には、次のように使い分けます。
| 例 | 適した型 |
|---|---|
| Viewを返す画面アクション | IActionResult / ActionResult |
| リダイレクトやエラーも返す画面アクション | IActionResult / ActionResult |
| JSON APIで特定のDTOを返す | ActionResult<T> |
| ステータスコードだけを返す | IActionResult |
| 戻り値をViewに限定する | ViewResult |
初心者は、MVC画面ではIActionResult、APIではActionResult<T>を基本にすると整理しやすくなります。
6-5. API開発ではActionResult<T>が選ばれやすい理由
API開発でActionResult<T>が選ばれやすい理由は、戻り値のデータ型が明確になるからです。
C#public ActionResult<ProductDto> GetProduct(int id)
この宣言を見るだけで、「このAPIは正常時にProductDtoを返す」と分かります。
また、エラー時には次のようなレスポンスも返せます。
C#return BadRequest();
return NotFound();
return StatusCode(500);
つまり、ActionResult<T>は、型安全性とHTTPレスポンスの柔軟性を両立できる型です。
APIの仕様を分かりやすくしたい場合や、Swaggerなどでレスポンス型を分かりやすく見せたい場合にも役立ちます。
7. ActionResultでよく使うHTTPステータスコード
WebアプリケーションやAPIでは、処理結果に応じて適切なHTTPステータスコードを返すことが重要です。
ステータスコードは、クライアントに対して「処理が成功したのか」「リクエストに問題があるのか」「サーバーでエラーが起きたのか」を伝えるためのものです。
7-1. 200 OK:正常に処理できた場合
200 OKは、リクエストが正常に処理されたことを表します。
ASP.NET Coreでは、Ok()を使って返せます。
C#public IActionResult Get()
{
var data = new { Message = "成功しました。" };
return Ok(data);
}
画面表示でView()を返す場合も、通常は正常なレスポンスとして扱われます。
C#public IActionResult Index()
{
return View();
}
APIでは、データ取得や更新成功時に200 OKを返すことがよくあります。
7-2. 400 Bad Request:リクエスト内容に問題がある場合
400 Bad Requestは、クライアントから送られたリクエスト内容に問題がある場合に返します。
C#public IActionResult Get(int id)
{
if (id <= 0)
{
return BadRequest("idは1以上を指定してください。");
}
return Ok();
}
たとえば、必須項目が不足している、形式が不正、指定された値が範囲外といった場合に使います。
7-3. 401 Unauthorized / 403 Forbidden:認証・認可に問題がある場合
401 Unauthorizedは、認証が必要な場合や、ログインしていない場合に使います。
C#public IActionResult MyPage()
{
if (!User.Identity.IsAuthenticated)
{
return Unauthorized();
}
return View();
}
403 Forbiddenは、ログインはしているものの、アクセス権限がない場合に使います。
C#public IActionResult AdminPage()
{
if (!User.IsInRole("Admin"))
{
return Forbid();
}
return View();
}
簡単にいうと、未ログインなら401、権限不足なら403と考えると分かりやすいです。
7-4. 404 Not Found:対象データが見つからない場合
404 Not Foundは、指定されたデータやページが見つからない場合に返します。
C#public IActionResult Details(int id)
{
var product = FindProduct(id);
if (product == null)
{
return NotFound();
}
return View(product);
}
APIでもよく使われます。
C#public ActionResult<ProductDto> GetProduct(int id)
{
var product = FindProduct(id);
if (product == null)
{
return NotFound("商品が見つかりません。");
}
return product;
}
対象データが存在しない場合にnullをそのまま返すよりも、NotFound()を返した方がクライアントに意図が伝わりやすくなります。
7-5. 500 Internal Server Error:サーバー側でエラーが発生した場合
500 Internal Server Errorは、サーバー側で予期しないエラーが発生した場合に返します。
C#public IActionResult Error()
{
return StatusCode(500, "サーバーエラーが発生しました。");
}
ただし、実務では例外をController内で毎回try-catchするよりも、例外処理ミドルウェアやフィルターで共通処理にすることが多いです。
Controllerでは、想定できるエラーに対してBadRequest()やNotFound()を返し、想定外のエラーは共通のエラーハンドリングに任せる設計がよく使われます。
7-6. ステータスコードを適切に返すサンプルコード
以下は、入力チェック、データ存在確認、正常返却を行うAPIの例です。
C#[HttpGet("{id}")]
public ActionResult<ProductDto> GetProduct(int id)
{
if (id <= 0)
{
return BadRequest("idは1以上を指定してください。");
}
var product = FindProduct(id);
if (product == null)
{
return NotFound("商品が見つかりません。");
}
return Ok(product);
}
このように、条件に応じて適切なステータスコードを返すことで、APIを利用する側がエラーの原因を判断しやすくなります。
8. ActionResultを使うときのよくある疑問
ここでは、C#初心者がActionResultを学ぶときによく疑問に感じるポイントを解説します。
8-1. ActionResultとViewResultは何が違う?
ViewResultは、Viewを返すための具体的な結果です。
C#public ViewResult Index()
{
return View();
}
一方、ActionResultは、View以外の結果も返せるより広い型です。
C#public ActionResult Index()
{
if (DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
{
return RedirectToAction("Holiday");
}
return View();
}
ViewResultにすると、基本的にはViewを返すことを前提にしたメソッドになります。
ActionResultにすると、View、Redirect、NotFoundなど複数の結果を返せます。
8-2. ActionResultとreturn View()の関係は?
ActionResultは戻り値の型で、return View()は実際に返している結果です。
C#public ActionResult Index()
{
return View();
}
このコードでは、メソッドの戻り値の型がActionResultで、返している中身がView()です。
たとえるなら、ActionResultは「返せる結果の種類を受け取れる箱」で、View()は「その箱に入れる具体的な結果」です。
同じActionResultでも、次のように別の結果を返せます。
C#public ActionResult Index()
{
return RedirectToAction("Login");
}
つまり、ActionResultとView()は同じものではなく、ActionResultという戻り値の型に対して、View()という具体的な結果を返している関係です。
8-3. APIでもActionResultを使える?
APIでもActionResultは使えます。
C#[HttpGet]
public ActionResult Get()
{
var data = new { Id = 1, Name = "Sample" };
return Ok(data);
}
ただし、ASP.NET Core Web APIでは、戻り値のデータ型を明確にできるActionResult<T>がよく使われます。
C#[HttpGet("{id}")]
public ActionResult<ProductDto> Get(int id)
{
var product = FindProduct(id);
if (product == null)
{
return NotFound();
}
return product;
}
APIでは、正常時に何のデータを返すのかが重要なため、ActionResult<T>を使うとコードの意図が明確になります。
8-4. voidやstringを返すのではだめなのか?
C#のメソッドとしては、voidやstringを返すこともできます。
C#public string Hello()
{
return "Hello";
}
しかし、MVCやWeb APIのControllerでは、HTTPレスポンスとしての意味を明確にするために、ActionResultやIActionResultを使う方が一般的です。
たとえば、stringだけでは、エラー時に404 Not Foundや400 Bad Requestを自然に返しにくくなります。
C#public IActionResult Hello(int id)
{
if (id <= 0)
{
return BadRequest();
}
return Ok("Hello");
}
ActionResultを使うことで、正常時と異常時のレスポンスを分かりやすく表現できます。
8-5. 非同期処理ではTask<ActionResult>を使うべき?
データベースアクセスや外部API呼び出しなど、非同期処理を行う場合は、Task<IActionResult>やTask<ActionResult<T>>を使うことが多いです。
C#public async Task<IActionResult> Index()
{
var products = await _productService.GetProductsAsync();
return View(products);
}
Web APIでは、次のように書けます。
C#[HttpGet("{id}")]
public async Task<ActionResult<ProductDto>> GetProduct(int id)
{
var product = await _productService.GetProductAsync(id);
if (product == null)
{
return NotFound();
}
return product;
}
非同期処理を使う場合は、戻り値をTask<IActionResult>やTask<ActionResult<T>>にし、メソッドにasyncを付けるのが基本です。
9. ActionResultの実務的なベストプラクティス
ActionResultは便利な型ですが、何でも自由に返せるからこそ、実務ではルールを決めて使うことが大切です。
ここでは、実務で意識したいベストプラクティスを紹介します。
9-1. MVC画面ではIActionResultまたはActionResultを使う
MVCで画面を返すControllerでは、IActionResultまたはActionResultを使うのが一般的です。
C#public IActionResult Index()
{
return View();
}
Viewだけでなく、リダイレクトやエラー画面も返す可能性があるため、具体的なViewResultに限定しすぎない方が扱いやすい場面があります。
C#public IActionResult Details(int id)
{
var product = FindProduct(id);
if (product == null)
{
return NotFound();
}
return View(product);
}
画面系のControllerでは、プロジェクト内でIActionResultかActionResultのどちらを使うかを統一すると、コードの見通しがよくなります。
9-2. Web APIではActionResult<T>を検討する
Web APIでは、正常時に返すデータ型を明確にするためにActionResult<T>を検討しましょう。
C#[HttpGet("{id}")]
public ActionResult<ProductDto> GetProduct(int id)
{
var product = FindProduct(id);
if (product == null)
{
return NotFound();
}
return product;
}
ActionResult<T>を使うと、APIの戻り値が読み取りやすくなります。
C#public ActionResult<List<ProductDto>> GetProducts()
この宣言を見るだけで、商品DTOのリストを返すAPIだと分かります。
9-3. 戻り値の型を統一してコードの見通しをよくする
プロジェクト内で戻り値の型がバラバラだと、コードを読むときに迷いやすくなります。
C#public ViewResult Index()
public ActionResult Details(int id)
public IActionResult Create()
public object Get()
もちろん、必要に応じて使い分けることはありますが、基本方針を決めておくと保守しやすくなります。
たとえば、次のようなルールです。
| 場面 | 戻り値 |
|---|---|
| MVC画面 | IActionResult |
| Web API | ActionResult<T> |
| ファイルダウンロード | IActionResult |
| 明確にViewだけ返す | ViewResult |
チーム開発では、戻り値の型のルールを揃えることで、Controllerの可読性が向上します。
9-4. エラー時のレスポンスを明確にする
エラー時に何を返すかを明確にすることも重要です。
悪い例として、データが見つからない場合にnullを返すだけでは、クライアント側がどう扱えばよいか分かりにくくなります。
C#public ProductDto GetProduct(int id)
{
return null;
}
よりよい例は、NotFound()を返すことです。
C#public ActionResult<ProductDto> GetProduct(int id)
{
var product = FindProduct(id);
if (product == null)
{
return NotFound();
}
return product;
}
入力エラーの場合はBadRequest()、認証が必要な場合はUnauthorized()、権限がない場合はForbid()など、状況に応じたレスポンスを返しましょう。
9-5. 可読性の高いControllerを書くポイント
可読性の高いControllerを書くには、次の点を意識します。
| ポイント | 内容 |
|---|---|
| 条件分岐を分かりやすくする | 先にエラー条件を返す |
| 戻り値の型を統一する | IActionResultやActionResult<T>を使い分ける |
| ビジネスロジックを詰め込みすぎない | Serviceクラスに分ける |
| ステータスコードを適切に返す | Ok、BadRequest、NotFoundなどを使う |
| メソッド名を分かりやすくする | Index、Details、Createなど目的を明確にする |
たとえば、次のように早めにエラーを返すと読みやすくなります。
C#public ActionResult<ProductDto> GetProduct(int id)
{
if (id <= 0)
{
return BadRequest("idが不正です。");
}
var product = FindProduct(id);
if (product == null)
{
return NotFound();
}
return product;
}
正常処理を最後に書くことで、処理の流れが追いやすくなります。
10. 初心者向け:ActionResultの理解を深めるサンプル
最後に、初心者向けにActionResult、IActionResult、ActionResult<T>を使ったサンプルをまとめて確認しましょう。
ここでは、商品管理を例にして、一覧画面、詳細API、入力エラー、データなし、登録後のリダイレクトを扱います。
10-1. 一覧画面を表示するActionResultの例
商品一覧画面を表示する例です。
C#public class ProductsController : Controller
{
public IActionResult Index()
{
var products = new List<ProductDto>
{
new ProductDto { Id = 1, Name = "ノートパソコン", Price = 120000 },
new ProductDto { Id = 2, Name = "マウス", Price = 3000 },
new ProductDto { Id = 3, Name = "キーボード", Price = 8000 }
};
return View(products);
}
}
このアクションは、商品一覧データをViewに渡して画面を表示します。
MVCの画面表示では、return View(model);の形をよく使います。
10-2. 詳細データを取得するActionResult<T>の例
商品詳細をAPIで返す例です。
C#[ApiController]
[Route("api/[controller]")]
public class ProductsApiController : ControllerBase
{
[HttpGet("{id}")]
public ActionResult<ProductDto> GetProduct(int id)
{
var product = FindProduct(id);
if (product == null)
{
return NotFound();
}
return product;
}
private ProductDto? FindProduct(int id)
{
if (id == 1)
{
return new ProductDto
{
Id = 1,
Name = "ノートパソコン",
Price = 120000
};
}
return null;
}
}
ActionResult<ProductDto>にすることで、正常時はProductDtoを返し、データがない場合はNotFound()を返せます。
10-3. 入力エラー時にBadRequestを返す例
入力値に問題がある場合は、BadRequest()を返します。
C#[HttpGet("{id}")]
public ActionResult<ProductDto> GetProduct(int id)
{
if (id <= 0)
{
return BadRequest("idは1以上を指定してください。");
}
var product = FindProduct(id);
if (product == null)
{
return NotFound();
}
return product;
}
この例では、idが0以下の場合に400 Bad Requestを返します。
入力チェックを行い、問題があれば早めにBadRequest()を返すことで、処理が分かりやすくなります。
10-4. データが存在しない場合にNotFoundを返す例
指定されたデータが存在しない場合は、NotFound()を返します。
C#public IActionResult Details(int id)
{
var product = FindProduct(id);
if (product == null)
{
return NotFound("商品が見つかりません。");
}
return View(product);
}
画面の場合は、独自のエラー画面を表示することもあります。
C#public IActionResult Details(int id)
{
var product = FindProduct(id);
if (product == null)
{
return View("NotFound");
}
return View(product);
}
APIではNotFound()、画面では専用のエラーViewを返すなど、用途に応じて使い分けるとよいでしょう。
10-5. 登録成功後にRedirectToActionで遷移する例
フォームから商品を登録したあと、一覧画面へ遷移する例です。
C#public class ProductsController : Controller
{
[HttpGet]
public IActionResult Create()
{
return View();
}
[HttpPost]
public IActionResult Create(ProductDto product)
{
if (!ModelState.IsValid)
{
return View(product);
}
// 登録処理
SaveProduct(product);
return RedirectToAction("Index");
}
private void SaveProduct(ProductDto product)
{
// データベースへの保存処理など
}
}
登録成功後にRedirectToAction("Index")を返すことで、商品一覧画面へリダイレクトできます。
フォーム送信後にViewを直接返すのではなく、リダイレクトを使うことで、ブラウザの再読み込みによる二重送信を防ぎやすくなります。
まとめ
ActionResultは、C#のASP.NET MVCやASP.NET Core MVCで、ControllerのアクションメソッドがHTTPレスポンスを返すために使う重要な型です。
ActionResultを使うと、次のようなさまざまな結果を返せます。
C#return View();
return Json(data);
return RedirectToAction("Index");
return Ok(data);
return BadRequest();
return NotFound();
return File(bytes, "application/pdf");
ActionResult、IActionResult、ActionResult<T>の違いを整理すると、次のようになります。
| 型 | 特徴 | よく使う場面 |
|---|---|---|
| ActionResult | アクション結果を表すクラス | MVC画面、既存MVCプロジェクト |
| IActionResult | アクション結果を表すインターフェース | ASP.NET Core MVC全般 |
| ActionResult<T> | データ型とHTTPレスポンスを両方返せる | ASP.NET Core Web API |
初心者は、まず次のように覚えると分かりやすいです。
MVCで画面を返す場合は、IActionResultまたはActionResultを使います。
C#public IActionResult Index()
{
return View();
}
Web APIでデータを返す場合は、ActionResult<T>を使うと便利です。
C#public ActionResult<ProductDto> GetProduct(int id)
{
var product = FindProduct(id);
if (product == null)
{
return NotFound();
}
return product;
}
ActionResultを理解すると、Controllerがどのように画面、JSON、リダイレクト、エラー、ステータスコードを返しているのかが分かるようになります。
ASP.NET CoreでMVCアプリケーションやWeb APIを開発するうえで、ActionResultは避けて通れない基本知識です。まずはView()、Ok()、BadRequest()、NotFound()、RedirectToAction()の使い方から覚えていきましょう。

