2009年9月20日日曜日

戸塚ホッケー事情

MHLのシーズンも始まって、この土曜で既に2試合消化したけど、どっちも負けたから特に書く事もない...。切ない。とりあえず、あれだ。初戦はゴーリーいなかったからいいとして、2戦目はひどい。あれじゃ、100戦しても100回負ける。もう少し賢く守りましょう。新規加入のゴーリー、スガマタさんはとてもすばらしいゴールテンディングを見せてくれてたよね?後はディフェンスの問題だけなんだから。

で、試合の話はいいとして、今日戸塚でみんなでおしゃべりしてる時に、戸塚に誰がいるのか誰か来るのかを簡単にみんなで共有できるようにするのに、ミチアキさんが「Twitterどう?」って話になったよね。その場にいた数人には説明したけど、なかなか言葉だけだと分かりにくいと思うので、みんなでガンガン使ってみよう!

http://twitter.jp

ネット関連に疎い人も多いと思うけど、スズキ君にはサヨちゃんが上手いこと説明して登録するようにしといてね!S40組にはオレが説明するとして、クラッシャーズ組にはヤマケン選手よろしく!後は、ちょっとづつ広めていきましょう。クローバー組はタカオ?

Twitterって何?って言う人も多いと思うけど、検索すればヤマのように説明出てくるから何とかなるよ。ケータイからのアクセスは...ケータイ持ってないからよく分かんないよ!モバツイッターとか?

そのままTwitterにつぶやいても、メッセージが流れてよく分かんなくなると困るので、戸塚スケートファクトリー用のハッシュタグとして Totuka Skate Factory Hockey の頭文字を取って#tsfhとしてみる感じでどうっすか。つぶやきの最後に#tsfhって書いてつぶやくだけ。そしたらTwitter / Search - #tsfhここにアクセスすればいい、戸塚の状況がすべて見られるようになるっていう寸法。

twitter

戸塚に行く前・着いてから・誰かを誘う時、いろいろつぶやいてみたら便利なんじゃないかね~。

追記

大事なことを書き忘れてた。Twitterでたけはらをフォローするときのアカウント名はtakeparaデス。

2009年9月15日火曜日

こういうのはいいのかどうか

ASP.NET MVC Transaction Attribute (using NHibernate) - Scott's Blog

NHibernateじゃなくても、以下のようなTransactionAttributeで。

using System;
using System.Transactions;
using System.Web.Mvc;

namespace MainSite.Controllers
{
  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
  public class TransactionAttribute : ActionFilterAttribute
  {
    private TransactionScope _transactionScope;

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
      _transactionScope = new TransactionScope();

      base.OnActionExecuting(filterContext);
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
      base.OnActionExecuted(filterContext);

      if (filterContext.Exception == null)
        _transactionScope.Complete();

      _transactionScope.Dispose();
    }
  }
}

適当なDataContextを用意してこれまた適当なAction(適当すぎてすいません)で。

    public ActionResult Index()
    {
      ViewData["Message"] = "Welcome to ASP.NET MVC!";

      return View();
    }

    [HttpPost,ActionName("Index")]
    [Transaction]
    public ActionResult IndexPost(string name)
    {
      var db = new DataClasses1DataContext();
      db.Table1s.InsertOnSubmit(new Table1 {name = name});
      db.SubmitChanges();

      //throw new HttpException(500,"Error!");
      return RedirectToAction("Index");
    }

Unit of Workって言うんですかね~。Exception起こせばロールバックするんだけど...。トランザクションってこのレイヤで意識するものなのかな~。う~ん。好みや規模に合わせて好きなやり方でどうぞ、ってことで。

2009年9月12日土曜日

runAllManagedModulesForAllRequests

VS2008での開発中のWebサーバーはWebDev.WebServerで、これってsystem.webServerセクションを処理しないで、IIS6と同じ動きになるじゃないっすか。

ドはまった。いきなり全然動かない状況が発生してテンヤワンヤ。そもそもIIS6にデプロイするものを作ってて、でもちょっとテストしたくなってIIS7にデプロイしたらイエロースクリーン。サッパリ原因が分からず泣きそうになった。出てきたエラーは↓これ。

セッション状態は、構成ファイルまたは Page ディレクティブで enableSessionState が true に設定されているときのみ使用できます。System.Web.SessionStateModule またはカスタムセッション状態モジュールがアプリケーション構成の <configuration>\<system.web>\<httpModules> セクションに含まれていることも確認してください。
説明: 現在の Web 要求を実行中に、ハンドルされていない例外が発生しました。エラーに関する詳細および例外の発生場所については、スタック トレースを参照してください。

例外の詳細: System.Web.HttpException: セッション状態は、構成ファイルまたは Page ディレクティブで enableSessionState が true に設定されているときのみ使用できます。System.Web.SessionStateModule またはカスタムセッション状態モジュールがアプリケーション構成の <configuration>\<system.web>\<httpModules> セクションに含まれていることも確認してください。

全然、解決出来そうなtipsが見つからなくて、将来の自分のためにここにコピペしとく。なんでセッションがいきなり動作しないんじゃ!と、お悩みなら、とにかくrunAllManagedModulesForAllRequests属性を確認。IIS7って統合パイプラインだったりするのが魅力なんだけど、こんなことに時間をつぶされるとは...。

    <system.webServer>
      <validation validateIntegratedModeConfiguration="false"/>
      <modules runAllManagedModulesForAllRequests="true">
        <remove name="ScriptModule" />
        <remove name="UrlRoutingModule" />

SessionStateModuleがマネージモジュールなおかげでこの属性を外すと、EnableSessionStateを設定しろと全然違うメッセージになって泣ける。

今後主流になるIIS7.5(Windows 7だけど)の場合は、英語っぽいメッセージになったけど、これまた検索で見つかるようにコピペしとこう。

The SessionStateTempDataProvider requires SessionState to be enabled.
説明: 現在の Web 要求を実行中に、ハンドルされていない例外が発生しました。エラーに関する詳細および例外の発生場所については、スタック トレースを参照してください。

例外の詳細: System.InvalidOperationException: The SessionStateTempDataProvider requires SessionState to be enabled.

そもそも、この属性をいついじってしまったのかさえ覚えてない...。普通にプロジェクト作成したときには指定されてるから自分で消したのは間違いないんだけど、IIS7にデプロイするまで問題が発覚しないから、要注意。

全然関係無いけどBubbleShareにアップしてるアルバムをダウンロードしようとしても0バイトのZIPファイルになってて全然ダウンロード出来ない。早くダウンロードしないとそろそろ閉鎖しちゃう。あわあわ。

2009年9月6日日曜日

HandleErrorの使い方リベンジ

前回の投稿の時には全然気にしてなかった問題を最近突っ込まれたので、改めて試して見ました。

そもそもASP.NET MVCで例外発生時のハンドリングをどうするのか、というのは前回の投稿に書いてるので読んでもらえれば分かると思います。と、言うと読んでもらえない気もするので簡単に説明すると、web.configでsystem.web/customErrorsをOnにしておき、ControllerやActionにHandleError属性を指定する。そうするとException毎に出力する内容を自分で制御出来るのさ!、というものです。

ここでポイントになるのはsystem.web/customErrorsでエラーハンドリングをする部分です。と、いうのも発生したエラーを捕捉し、表示したい内容を切り替える際に、この方法だとエラーページから302 Redirectで表示ページに遷移します。でも、人ではない何か(クローラやらAjaxなんかでのRESTクライアント)に正しくエラーを伝えるにはHTTP StatusCodeに正しい値をセットしたレスポンスを返さないとダメじゃないですか。ダメだとしましょう。

前回の実装では、302 Redirectの後に返されるレスポンスで正しいHTTP StatusCodeを返してる。けど、ちょっと待てと。そもそもRedirectいらないだろと。おっしゃる通りです。まったくその通りで、リクエストに対してRedirectなんかせず、スパッとステータスを返すのが正しい実装ですよね。

どうすればそういう実装が簡単にできましょうか、が今回の主題です。で、この主題を実装して正しく動くのはIIS7以降に限定なのでそうじゃない環境の人は「ふ~ん、そっすか」くらいにしか得るものがないかも。ガンバです!

まずsystem.web/customErrorsだけだとリダイレクトされてしまうので、これを何とかしたい。IHttpModuleとかで実装するのも手としてはありかもしれないですが、そんなことしなくてもweb.configにsystem.webServer/httpErrorsというのがありまして。このセクションにエラー発生時の挙動を書きます。それだけだとcutomErrorsと何が違うんだと思われても致し方なし。決定的に違うものがありまして、それがresponseMode="ExecuteURL"という属性。これを指定するとただのHTMLレスポンスでもなく、リダイレクトでもなく、指定したURLの実行結果を返してくれるんです。まばゆいくらい素敵です。

httpErrors Element [IIS 7 Settings Schema]

詳しくはリファレンスをチェケラッなんだけど、残念なことに日本語になって無くてですね...。ここは一つ「早く日本語にしてください!」とこのエントリを読んだ人はチャックに言いましょう!IISというかインフラは担当が違うと弱音を吐くようなら「担当に伝えてください!」とチャックに言いましょう!だって担当知らないし。

MSDNのドキュメントの苦情もすべてチャックに!そんなチャックはTHE TRUTH IS OUT THEREこちら(ゴメンねチャック)。

話を進める前に前回の状況のスクリーンショットを確認しておきます。

error1 error2

左が立ち上げた時の状態。右がBad Requestのリンクをクリックした状態。クリックすると拡大するのでステータスを確認してみてください。302 Redirectの後に400 Bad Requestになってますね。ちなみに開発環境のwebDev.webServerはwebServerセクションを見てくれないので、ローカルのIISにデプロイして確認する必要があります。今回はWindows 7上のIIS7.5にデプロイしてます。

まずはsystem.webServer.httpErrorsを設定します。

    <httpErrors errorMode="Custom">
      <clear />
      <error statusCode="400" path="/ErrorHandle/Errors/400" responseMode="ExecuteURL" />
      <error statusCode="403" path="/ErrorHandle/Errors/403" responseMode="ExecuteURL" />
      <error statusCode="404" path="/ErrorHandle/Errors/404" responseMode="ExecuteURL" />
    </httpErrors>

適当な感じで申し訳ないっす。 で、web.server/customErrorsを変更します。

    <customErrors mode="On" defaultRedirect="Errors" />

前回の設定内容をガッツリ消して、上記のみにしてしまいましょう。これすら消すとHandleError属性が効かなくなってエラーが捕捉出来なくなるので残しておきます。

続いて、HandleErrorAttributeクラスを派生させたHttpHandleErrorAttributeクラスを作成します。この派生クラスでOnExceptionをoverrideして処理してしまいましょう!

using System.IO;
using System.Web;
using System.Web.Mvc;

namespace ErrorHandling.Controllers
{
  public class HttpHandleErrorAttribute : HandleErrorAttribute
  {
    public override void OnException(ExceptionContext filterContext)
    {
      var exception = filterContext.Exception as HttpException;
      if (exception == null)
      {
        base.OnException(filterContext);
        return;
      }

      var statusCode = exception.GetHttpCode();
      var errorViewName = string.Format("~/Views/Errors/Error{0}.aspx", statusCode);
      if (!File.Exists( filterContext.HttpContext.Server.MapPath(errorViewName)))
        errorViewName = "~/Views/Shared/Error.aspx";

      filterContext.Result = new StatusViewResult(new ViewResult { ViewName = errorViewName }) { StatusCode = statusCode };
      filterContext.ExceptionHandled = true;
    }
  }
}

普通のExceptionは無視して、HttpExceptionだけ捕捉します。後は、ControllerにHttpHanderErrorを追加するだけ。

using System;
using System.Web;
using System.Web.Mvc;

namespace ErrorHandling.Controllers
{
  [HandleError(Order = 1)]
  [HttpHandleError]
  public class HomeController : Controller
  {
    public ActionResult Index()
    {
      ViewData["Message"] = "Welcome to ASP.NET MVC!";

      return View();
    }
// 以下省略

太字のところです。 ちなみに前回のサンプルソースに付け足してます。

実行すると↓こうなります。

error3

ちゃんと1度目のレスポンスで400がが返ってますね!

error4 error5

上の2つは左がThrow Exceptionリンクをクリックしたもので、これはcustomErrorsが効いてる結果です。右がMethod not arrowedをクリックした結果で、HttpHandleErrorでViewの定義が無かった(405を用意してないです)時のものです。

エラー処理もこれでスッキリ!

2009年9月4日金曜日

あ、メタルキングじゃないことがばれた

先日のBoFの様子が早くもCodeZineで記事になってます!

「ASP.NET Web Form」か「ASP.NET MVC」か? .NETによるWebアプリ開発の今を徹底討論(1/4):CodeZine

最初のページのトップにある写真でプロジェクターの映像を見上げてるのが自分です。これだけ小さい写真だと顔も分からないから恥ずかしくないね!同じ写真内で真ん中あたりにノートパソコンのモニターがちらっと写り混んでるね~。ボスなんだよね~。このノートパソコンの画面気になるでしょ~?メモとか取ってるとか思ってるでしょ~?違うんですよ!パワポ(?)で「ここでボケて」とか「もっと詳しく」とか「なんでスーツ着てないの?」とかが用意されてて、しゃべってる途中でチョイチョイ画面をこちらに向けて楽しんでたんだよ!上手いこと写真には写ってないけど一番後ろの席で肉好きの熊さんも同じくカンペを用意してたんだよ!怖え~。BoF怖え~。罠ばっかりだ。

写真小さいとか思ったそこのあなた。2ページ目ではちょっとデカイ写真が。メタルキングじゃないことがばれた。東京生まれヒップホップ育ちのメタルキングで通してたのに普通の人なのがばれた。ちなみにカメラ目線ではありません。たまたまです。写真撮ってることなんて気がついてませんから。ド緊張してたんで。

記事ではスゴイまじめに技術の話をしてる風ですが、そこは記事を書いてくれたナオキさんの腕っす。自分へたれっす。

これからもご贔屓に~。

2009年8月28日金曜日

ボフったー

本日BoFに参加してくださったみなさま!ありがとうございました!

超、緊張しました。結構あれこれとしゃべること用意してたんですが、全然しゃべれませんでした。自己紹介を途中棄権ってなんだよ!みたいな。

内容的にはちゃんと「適材適所で使い分け」というのを入れたかったんですが、なにもかもが後の祭り。だって、管理画面なんか小野さんのサンプルみたいにゼロコーディングで出来たら最高ですよね。ViewState/PostBackなPage Controllerスタイルで、コントロールに処理を完全に委譲してしまうWebFormは最強です。それらの機能を少し横取りして、Pageからすべての機能を切り離し(この時点でもうアーキテクチャスタイルが違うので比較することじたいに無理があるんですけど)Front ControllerスタイルにしたASP.NET MVCによるスクラッチ開発は面白さ爆発です!

とにかくまず最初に驚いたのがASP.NET MVCで何か作ったことのある開発者の方が思ってた以上に多かったこと。ビックリしました。可能性たっぷりですね!フレームワークと名乗るにはまだまだ万人向けなものにはなってないMVCですが、何となくこの路線を突っ走って欲しいという個人的には思ってます。だってチャップリンも言ってるじゃないですか。

人生は恐れなければ、とても素晴らしいものなんだよ。
人生に必要なもの。それは勇気と想像力、そして少しのお金だ。

うん、全然関係無い言葉だね!

えと、ちなみにデスね、今日話したかったメモを以下に残しておきます。

  • 共通のnamespaceはImportでaspx/ascx毎にしていするんじゃなくて、web.configで指定しておこう。
  • HTML入力を受け付ける時にはValidateInput属性で指定しよう。Pageディレクティブやweb.configでのValidateRequestはController関係無いよ!
  • csprojのMvcBuildViewsをtrueにしてViewのコンパイルを強制するのが便利なときもある。
  • JavaScript無しで機能を実装したあとに、JavaScriptでのUX向上を目指すのが王道。でも、こだわらなくてもいいかもね。
  • URLはリソース指向に考えてルーティングに定義しよう。
  • RepositoryとServiceを作成しといて、アクションでは単なる呼び出しがいい。
  • DB Modelと View Modelを分ける(相互にマッピングする)。
  • テストしやすくするために、HttpContextへの依存をControllerからなくす(UserNameとIsXhr)。依存性が無いならテストは結構楽ちん!
  • 全体共通なBaseControllerを定義しておくと何かと楽ちん(abstractでね!)。
  • Viewでの作業を楽にするためにヘルパーを定義。
  • Controller名やAction名のマジックストリングをなくすために、T4MVCを活用。
  • 入力検証を楽にするためにDataAnnotationsModelBinderを活用。
  • もっと複雑になるならDIでRepository/Serviceの依存性注入。
  • マッピングも大変ならAutoMapperやら(自分で書いてもいいけど)。
  • テストが複雑になりそうなら(依存性を持ったもののテストをしたいとか)Mockを使おう。MoqやらRhino.Mocksやら。
  • カッコ良くRESTfulな実装にしたいならREST for ASP.NET MVC!

参考にするといいかもなURL

お勧め書籍

サンプルに実装してる項目もあれば、無い項目もあります(DIやMockや)が、こういうのを取り入れると楽しく開発出来るっていうのを話したかったデス。

サンプル一式は↓こちらからどうぞ。

動かすにはSQLServer2008Express以上が必要になります。Databasesフォルダ内の2つのMDFをそれぞれAspNetDBとMyTimeDataという名前でアタッチ(MS SQL Server 2008 Attach Database .MDF File)するとそのままで動くんじゃないかと思います。

※App_Dataに入れてAttachDbFilenameをConnectionStringに指定する方が簡単なんですが、それだとウェブのプロジェクトとテストのプロジェクトで同じインスタンス名でDB作成しようとして動かないんで気をつけてください。

機能的な物はBoFで紹介したとおり、Membershipによるユーザー管理とログイン、作業時間の追加・更新・削除と合計表示のみです。これにチャートコントロールでの表示やら、月内デイリー合計なんかの機能をつければ、それなりに使える物になるんじゃないかと思いますがどうでしょうかね。プロジェクトの名前を「ボフったー」にしなかったのが「エドったー」に完全に負けてるところデス!

細かいサンプルの説明は...、必要ならしますが、どうなんでしょう。週末だし書くかもしれないですが、ホッケーもしたいので微妙です。たけはらが書かなくてもチャックが説明してくれると思います!無茶ぶり返し!

最後に。

こういう機会を与えてくれた、小野さんとナオキさんには感謝しきれません。ボスにはいろんな人を紹介してもらってマジ感謝です。一人だと誰とも知り合えずに過ごす事になったこと間違い無しです。MSの方達も、こんなどこの馬の骨なのか分からないチンピラ開発者の話に耳を傾けてくれてホント嬉しかったです。

BoFでたけはらの話に耳を傾けてくれた人たちの暖かさには、感謝しても仕切れません。マジ泣ける。本当にありがとうございました。

コンカレント

Tech ED2日目。今日はボスと別行動もあって、ちょっぴり大人の仲間入り?

まぁ、最初のセッションは同じのだったけど、別々にセッションルームに入ったので別行動ってことでいいですかね?今日も熊澤さんの話を聞きに行ったんですが、ちょいちょい熊澤さんが明後日の方向を向いて話をするわけですよ。ナゼ正面向いて話をしないんだろうかと思って目線の先を見るとボスが立って見てた...。そこ、マンツーなんですか。何でですか。見に来てる人100人くらいいる感じなんですが、マンツーで説明なんですか。そーですか。NUMAの話で盛り上がり、アンドキュメンテッドな動的管理ビューを紹介してくれたりと、初日に続いて濃厚な内容でした。

とりあえずBoFって何?みたいな状態を打破するために他の方のBoFを見てみることにしました。ボスとべーさんの言うとおりみんなスーツでした。な、わけねーよ。誰もスーツじゃないじゃないか!でも、不安だったからMSの人に「スーツじゃないとダメなんですか?」って聞いたら「そんなことないです」って教えてくれました。隣で渋木さんが「おまえ、ばらしてんじゃねーよ」という目でMSの人のこと見てた...。その目はまるで熊。ハンマー持った熊。

なんやかんやで、セッション全終了の後、休憩ルームでおしゃべりしてたら、ナオキさんが「ガンダムの人がいます!」と呼んできてくれて、少しお話しすることが出来ました。もうね、とにかくね、ガンダムは分からないから違う例えにしてください、と。攻殻機動隊か電脳コイルなら分かるので、そっちでお願いしますと。Azureの話をもっとしたかったけど途中で渋木さんと赤間さんも参加して、猫バス事件の話になって...。面白かったからいっか。でも、あれだ、みんな日常会話で使う単語が変。誰もなんの突っ込みもなく普通にそういう単語なんだもんよ。技術の話をしてるわけじゃなく、風呂とトイレがコンカレントだとか、会話がかみ合うのをプロトコルが一致するとか、食事に合流するのをジョインするとか、日常会話でそれはおかしいと思うんだ。オレおかしいと思うんだ。オレがおかしいのか??

夕食の時に、今度は荒井さんが同席。The Root of .NET Frameworkでハートを鷲づかみにされた荒井さん。なんかね、今までどんな人が本を書いてるとか、ブログを書いてるとか全然意識したこと無かったんですよ。自分とは関係無い世界の人たちっていうか。実際会って話をするなんて考えたこと無かったし。でも、なんかみんな素敵な人ばっかりでさ~。食事の後、途中まで電車が一緒でマンツーマンで荒井さんとおしゃべり出来て得した気分。名もない開発者な自分の話をずっと聞いてくれて、答えを返してくれて。あ、そうそう、自分もだけど、荒井さんも気がついてないだろう接点を発見した。荒井省三のBlog : The Root of .NET Framework の書評で荒井さんがたけはらタンブラのThe root ofの感想へリンクしてくれてた。う~ん、今日一緒に話をするまえに知ってたら、もっと楽しかったかも!でも、明日もあるし、会ったらその話をふってみようかな。

んでもって明日は、とうとうBoFに登壇(最後の枠のBoF-14 ASP.NET Web Form vs. ASP.NET MVC in Japanデス)。小野さんは「なんとかなるよ」と言ってくれてるけど、全く打ち合わせもなく、かなりドキドキなんですけど...。チャックが初日のセッションで無茶ぶりするもんだから胃が痛くてしょうがねーす。たぶん小野さんとナオキさんの陰に隠れて小さくなってると思います。

dotnetConf2015 Japan

https://github.com/takepara/MvcVpl ↑こちらにいろいろ置いときました。 参加してくださった方々の温かい対応に感謝感謝です。