2008年8月29日金曜日

ASP.NET MVCの記事

待望の後編が!! もう一つのASP.NET 「ASP.NET MVC」を知る(後編):CodeZine 一通りの機能説明がされててナイスです!

とりあえず前後編読んでおけば何となくアプリケーション作れるんじゃない? あと、ActionResult(ViewResultとか)?

最近、知ったんだけど"The ASP.NET MVC Information Portal"っていうのができてて、これでもかってくらい外部のサイトとかFeedで集めまくってるのでちょっと楽しいです。

最近はSSLを使えるようにいろいろ試行錯誤。 Vistaだと自己証明証明書とかで簡単にテスト環境作れるのがいいね。 SSL に使用する証明書の構成 コマンドで作成すればもっと融通のきく勝手証明書が作れるのかな~? こっちはうまくできなかったけど。 で、SSLで通信できるようになったのはいいけど、今度はどうやってリンクをSSLにしましょうか、ってところですよ。

Html.ActionLinkやRouteLink、Url.Actionとかで吐き出すURLをどうすればいいんだろかと思って調べてたら、こんなすごいのを発見。 Steve Sanderson’s blog » Blog Archive » Adding HTTPS/SSL support to ASP.NET MVC routing 書いてるとおりにSystem.Web.Routingモジュールを外して、こっちに置き換えて、Global.asaxにRoute登録すると...。すげ~!!かっこよくHTTPSとHTTPが切り替わるように出力されてる。絶対URLと相対URLをうまく切り替えてて賢く動く。

でも、VisualStudioのWebDev.WebServerじゃ、SSLで動かせないからIISに設定し直してテストしてみると~!!なんとまぁ、ちゃんと動かない...。 Problem 1のところに本人も書いてるけど、同じ症状。残念です。"Some gremlin in the routing"だってさ。 でも、これを改善したという猛者がいたりして。 Dmitriy Nagirnyak: Fixing HTTPS Support in ASP.NET MVC Routing

なぬ~!!と速攻でこの修正を加えて試してみたけど、ダメだった...。なんでだろね。ソース追っかける元気が...。いつかきっと確認しときます。 あ、そういえば、SP1 RTMにアセンブリリダイレクトしてないからうまく動かないのかも?まぁ、いっか。 このままじゃ、面倒なことになるなと思ってたところで、代替案。 Troy Goode: SquaredRoot - SSL Links/URLs in MVC

使い方は超簡単。いや、そりゃそうだってなもんで。 こっちはRoutingがどうのこうのじゃなくて拡張メソッドでガリっとURL書き換え。 なので、自分で書き換えたい部分のコードを変更する必要あり。 ちょっと面倒だけど、確実なのでとりあえずはこの方法で進めることにしてみます。 ※Html.ActionLink(...).ToSslLink()とかUrl.Action(...).ToSslUrl()って感じで使います。 このままだと、いったんHTTPになった後にHTTPに戻しにくいので、同じ要領で↓こんなのも用意しときましょう。

    public static string ToHttpUrl(this string text)
    {
      if (Utility.UseSSL)
        return ToFullyQualifiedUrl(text).Replace("https:", "http:");
      else
        return text;
    }

    public static string ToHttpLink(this string text)
    {
      if (Utility.UseSSL)
        return ToFullyQualifiedLink(text).Replace("https:", "http:");
      else
        return text;
    } 

そうそう、最初のナオキさんの記事の最後のページにこのブログが紹介で載ってるんだけど、こういうときにブログのタイトルがこんなだとちょっと恥ずかしい...。

2008年8月9日土曜日

イベントの実行順が面白くて

SQL Server 2008に合わせて.NET Framework 3.5 SP1が見えてるところですね。 ウェイトリフティングの三宅選手がスナッチあげてる時に使ってるタオルがスティッチ。ジャークのときにはサメのキャラを期待。

ASP.NET MVCのControllerではoverride出来るイベント(Onなんちゃら)が6個ありまして。

  • OnAuthorization(承認)
  • OnException(例外)
  • OnActionExecuting(Action実行前)
  • OnActionExecuted(Action実行後)
  • OnResultExecuting(Result実行前)
  • OnResultExecuted(Result実行後)
このActionとResultって何なんですか?って気になるところだったりしませんか? 以下のようなコードをHomeControllerに書くとどんな出力がでるのか試してみるとよく分かります。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
 [HandleError]
 public class HomeController : Controller
 {
    protected override void OnAuthorization(AuthorizationContext filterContext)
   {
     System.Diagnostics.Debug.WriteLine("OnAuthorization");
     base.OnAuthorization(filterContext);
   }

   protected override void OnException(ExceptionContext filterContext)
   {
     System.Diagnostics.Debug.WriteLine("OnException");
     base.OnException(filterContext);
   }

   protected override void Execute(ControllerContext controllerContext)
   {
     System.Diagnostics.Debug.WriteLine("before Execute");
     base.Execute(controllerContext);
     System.Diagnostics.Debug.WriteLine("after Execute");
   }

   protected override void OnActionExecuting(ActionExecutingContext filterContext)
   {
     System.Diagnostics.Debug.WriteLine("- OnActionExecuting");
     base.OnActionExecuting(filterContext);
   }

   protected override void OnActionExecuted(ActionExecutedContext filterContext)
   {
     System.Diagnostics.Debug.WriteLine("- OnActionExecuted");
     base.OnActionExecuted(filterContext);
   }

   protected override ViewResult View(string viewName, string masterName, object model)
   {
     System.Diagnostics.Debug.WriteLine("-- View");
     return base.View(viewName, masterName, model);
   }

   protected override void OnResultExecuting(ResultExecutingContext filterContext)
   {
     System.Diagnostics.Debug.WriteLine("- OnResultExecuting");
     base.OnResultExecuting(filterContext);
   }

   protected override void OnResultExecuted(ResultExecutedContext filterContext)
   {
     System.Diagnostics.Debug.WriteLine("- OnResultExecuted");
     base.OnResultExecuted(filterContext);
   }

   public ActionResult Index()
   {
      System.Diagnostics.Debug.WriteLine("-- Index action execute");

     ViewData["Title"] = "Home Page";
     ViewData["Message"] = "Welcome to ASP.NET MVC!";

     return View();
   }

   public ActionResult About()
   {
     ViewData["Title"] = "About Page";

     return View();
   }
 }
} 

で、これだけだとちょっと見落としちゃうタイミングがあるので、Views/Home/Index.aspxの先頭にもコード追加。

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>
<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">

<% System.Diagnostics.Debug.WriteLine("-- page rendering"); %>

   <h2><%= Html.Encode(ViewData["Message"]) %></h2>
   <p>
       To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.
   </p>
</asp:Content>

これで、準備完了。 ※太字が追加したコードです。 実行してみると、デバッグ出力が↓こうなります。

before Execute OnAuthorization - OnActionExecuting -- Index action execute ← ここでアクション実行 -- View - OnActionExecuted - OnResultExecuting -- page rendering ← ここでASPXのレンダリング - OnResultExecuted after Execute

面白いでしょ? ASPX の実行はずいぶん後なんですよね。Viewの実行時にレンダリングされるわけじゃないっていうのが、なるほどなと思わずにはいられない。ちなみに Redirect/RedirectToAction/RedirectToRouteもContent/JsonもViewと同じタイミング。ASPX のレンダリングのタイミングと同じタイミングでResult実行されるのを気をつけておく必要ありです。 ControllerのExecuteの中でこんな順序で処理されてるっていうことが分かれば、いろいろできそうじゃないですか。 で、なんでこんなこと書いてるかというと、TempDataですよ。 この中でTempDataってどういうタイミングで保存復元されるんだろかと。 ソースを追いかけるとController.cs内のprotected internal virtual void Execute(ControllerContext controllerContext)に書かれてますね。 InvokeActionを呼び出す前に、TempData.Load(TempDataProvider)。InvokeAction後にTempData.Save(TempDataProvider)。 と、いうことはControllerのExecuteをoverrideしてbase.Executeの前後でTempDataにデータを入れても意味ないってことですよ(ね?)。 TempDataの出し入れのタイミングを間違えると、入れたのに取り出す時にはnullってことになりかねないので注意が必要です。

ViewDataに比べてあんまり注目されてない気がするTempDataだけど、結構使い道があって(メッセージ出力時や、ViewDataで使うモデルデータに関連するデータを入れたり)するので、積極果敢に攻めの姿勢で使っていこうと思うところですよ。 ※ただしTempDataはシリアライズの問題もあり、LINQ to SQLのモデルをそのまま入れることはできない(StateServerとSQLのSession変数に入れられないのと同じ理由)ので、匿名クラスとかに変換して入れたりします。 それにしても、スナッチ1回目で90kg上げる中国チン選手恐るべし!最終的にミスなしで95kgて...。自重の倍て...。

2026年06月17日の記事一覧

(全 13 件) Foundry Toolkit for Visual Studio Code 自分のPCで「とりあえず動く」ではなく「一番賢く使える」ローカルLLMを教えてくれる「whichllm」、実測ベンチでランク付け(生成AIクローズアップ) | ...