必要な余談:少し前まで、私は印刷出版を目的とした記事を投稿しました 。 以下の記事にも同じ運命があります。ジャーナルのp状のために印刷されませんでした。 前回と同様、私はHabréについての記事を公開することにしました。これは、対象が形式の下で得られる利益です。 記事がデザインされており、雑誌のテキストが含まれていることに注意してください。Habr向けに準備されている場合は、一部を変更できます。 記事をお楽しみください。
最近、Microsoftが開発ツール、新しいツール、および.netプラットフォームでプログラムを開発するためのメカニズムの開発に特別な注意を払っていることが注目されています。 C#言語は急速に開発されており、その4番目のバージョンはそれほど遠くありません。 新しいF#言語を導入し、積極的に推進しています。 Entity Frameworkはデータベース開発者向けに開発されたもので、.Net Framework 3.5およびVisual Studio 2008の最初のサービスパックの最終バージョンとして既に利用可能です。Microsoftは、Webプロジェクト開発のクライアント部分にも積極的に関与しています。 私たちの注意のために、Ajax.Net 4.0の開発パスが提案されています。 Internet Explorer 8はますます標準に準拠しており、Webプログラマーにとって魅力的なツールになりつつあります。たとえば、[開発ツール]タブにはJavaScriptプロファイラーが含まれています。 最近の非常に良いニュースは、次のVisual Studio更新でのjQuery JavaScriptライブラリの完全なサポートと組み込みの発表です。 この観点から、ASP.NET開発者に何が提案されているのかという疑問が生じます。 答えはMVCフレームワークです。 この記事の目的は、WebプロジェクトとそのソリューションにMVCフレームワークを使用することを決定したプログラマーが遭遇する可能性のあるいくつかの一般的な問題を検討することです。
O MVC
Model-view-controllerまたは英語のModel-view-controllerパターンは、非常に長い間使用されてきました。 1979年に、彼はTrigwe Reenskaugの「Smalltalk-80でのアプリケーション開発:Model-View-Controllerの使用方法」で説明されました。 それ以来、このパターンは非常に成功したソフトウェアアーキテクチャとして確立されました。
インターフェイスで作業するユーザーは、ユーザーアクションをインターセプトするコントローラーを制御します。 次に、コントローラーはモデルにユーザーアクションを通知し、それによってモデルの状態を変更します。 コントローラーはビューにも通知します。 ビューは、モデルの現在の状態を使用して、ユーザーインターフェイスを構築します。
このパターンの基本は、アプリケーションデータモデル、そのロジック、およびデータの相互の分離です。 したがって、「分割統治」規則に従って、モデルがプレゼンテーションとロジックに依存せず、ユーザーインターフェイスが制御ロジックから確実に分離される、適切に構成されたソフトウェアを構築できます。
現在、MVCパターンは、Webアプリケーションの開発に使用されるほとんどのプログラミング言語に対して、何らかの形で実装されています。 PHPには最大数の実装がありますが、Java、Perl、Python、およびRubyには独自のオプションがあります。 MicrosoftのMVCバージョンより前には、.NETプラットフォーム用のオプションであるMaverick.NETとMonoRailもありました。
ASP.NET MVCフレームワーク
2007年12月10日に、MicrosoftはASP.NETのMVC実装を導入しました。 依然として.aspx、.ascx、および.masterファイルに基づいており、フォーム、ロール、データキャッシュ、セッション状態管理、ヘルスモニタリング、構成、プロバイダーアーキテクチャなどに基づく認証を完全にサポートしています。
一方、MVCフレームワークは、古典的なWebフォームとWebコントロールの使用を意味するものではなく、ポストバックやビューステートなどのメカニズムがありません。 MVCフレームワークは、クエリモデルとしてURLマッピングとRESTアーキテクチャの使用も提供します。これは、Webプロジェクトの検索エンジン最適化にプラスの影響を与えます。
--- | クラシックASP.NET | MVC |
クエリモデル | ポストバック | REST |
データモデル | ページのcsファイルコード(コードビハインド)経由 | MVCパターンにより定義 |
インターフェース設計 | Webコントロール | 純粋なhtml、MVC UIヘルパー |
ID自動生成 | はい | いや |
ViewState | そこにある | いや |
URLマッピング | いや | そこにある |
一般に、私の意見を表明すると、MVCフレームワークはクライアントコードの品質に焦点を当てたASP.NET開発者向けの新しいスタイルを提案したと言えます。 MVCで生成されたページコードには、自動生成されたものは何も含まれていません。肥大化した識別子、巨大なビューステートはありません。 Web 2.0の概念が私たちの生活にしっかりと入った時代では、クライアント側のページを完全に制御することが、Webプロジェクトの成功の鍵です。
MVCフレームワークのバージョン
MVCフレームワークはバージョンごとに改善されており、9月から10月の間に2つのバージョンがリリースされ、多くの新しいことがもたらされたため、プレビュー5では次の変更が行われました。
- 部分ビューのレンダリングのサポートが追加されました;実際、ビューにカスタム要素を挿入できます。
- 特定のタイプのリクエスト(POSTまたはGET)のアクションを設定できるAcceptVerbs属性が追加されました。
- ActionName属性を追加しました。これにより、メソッドに名前アクションを与えることができます。 デフォルトでは、アクション名とメソッド名は同じですが、今では異なる名前にできます。
- HandleError属性の操作を変更しました。 開発者向けに、エラー情報を含む標準の「死のイエローページ」を表示できるようになりました。
- ModelBinderを介した複合型のサポートが登場しました。
10月中旬にリリースされたMVCフレームワークベータには、次のようなアドオンも含まれています。
- Visual Studioの新しい[ビューの追加]メニュー
- \ ScriptsフォルダーとjQueryのサポート
- 複合型のネイティブモデルバインダーのサポート
- 再構築されたモデルバインダーインフラストラクチャ
- UpdateModelおよびTryUpdateModelメソッドの改善
- UpdateModelおよびTryUpdateModelスクリプトのテストの改善
- AcceptVerbs属性が入力されます。 HttpVerbs列挙を追加しました。
- 検証中のデフォルトエラーメッセージの改善
- いくつかのヘルパーメソッドを変更しました。 フォームの作成を変更しました。 メソッドは、HtmlHelperクラスの拡張メソッドになりました。
- Silverlight 2によるプロジェクトサポート
- このベータ版のASP.NET MVC Futuresビルドは別であり、含まれていません
- GACアセンブリサポート
ヒント
ページでselect html要素を設定する方法
要素を作成するには、HtmlクラスヘルパーのDropDownListメソッドを使用します。
<%= Html.DropDownList( ""、 "sampleSelect")%>
最初のパラメーターは、アイテムのリストに追加されるストリングをデフォルトのストリングとして指定し、2番目のパラメーターはselectの名前です。
最も興味深いのは、selectにデータを追加する方法です。 次のデータモデルがあるとします。
public class Product
{
public string Name
{
get ;
set ;
}
public int Id
{
get ;
set ;
}
}
* This source code was highlighted with Source Code Highlighter .
製品タイプのデータセットを選択に配置するには、次の手順を実行します。
var products = GetProducts();
ViewData ["sampleSelect"] =新しいSelectList(製品、「Id」、「名前」);
どこで
GetProductsは特定のメソッドであり、IEnumerableの形式のデータソースです。このようなデータソースはデータモデルに配置する必要があります。ここでは、例として簡略化しています。
SelectListは、System.Web.MVCで定義されているヘルパークラスです。
ここでは、ViewDataを介して、SelectListクラスを使用して作成されたデータセットが渡され、そのコンストラクターは、最初のパラメーターを介して製品の形式でデータを受け取ります。 値のProductクラスで定義されたプロパティの名前とselectの表示テキストは、2番目と3番目のパラメーターで渡されます。
ユーザーコントロールを表示する方法
コントロールを表示するには、プレビュー5にあるHtml.RenderPartial(...)メソッドを使用します。 プロジェクトでユーザーコントロールを使用するには、通常のWebユーザーコントロールとしてではなく、MVCビューユーザーコントロールとして作成する必要があります。 違いは、作成された要素がどのクラスから継承されるかです。 MVCの場合、アイテムはSystem.Web.Mvc.ViewUserControlを継承します。
ユーザー要素の出力は難しくありません:
<%Html.RenderPartial( "SampleUserCtrl"); %>
SampleUserCtrlは、ユーザーコントロールを表すクラスの名前です。
Htmlクラスを介して作成された要素をクラス属性に割り当てる方法
HTMLヘルパークラスは非常に便利なMVCフレームワークツールで、ページ上にコントロールを均一に作成できます。 そしてもちろん、このクラスのメソッドを使用すると、html要素の属性を設定できます。 例として、テキストSampleLinkでハイパーリンクを設定し、パラメーターproduct.Id tag rel = "nofollow"でアクションActionNameを設定します。
Html.ActionLink( "SampleLink"、ActionName、new {product.Id}、new {rel = "nofollow"})
問題は、属性名がC#の予約語(もちろん「クラス」)に一致したときに始まります。 解決策は簡単です。
Html.ActionLink( "SampleLink"、ActionName、new {product.Id}、new {@class = "sample-css-class"})
リトルビューデータ
場合によっては、あるアクションから別のアクションにデータを転送する必要があります。 たとえば、入力フィールドのあるページで、入力されたデータの処理中に例外が発生しました。例外はページに戻るときに報告する必要があります。 1つのアクションが入力されたデータの処理に関与し、別のアクションがページの処理を担当しているため、他の場合に使用されるViewDataは役に立ちません。
そのような場合、MVCにはTempDataがあります。これは、要求時にのみ存在し、その後削除されるデータ構造です。
<%if(TempData ["Message"]!= null){%>
<%= HttpUtility.HtmlEncode(TempData ["Message"]。ToString())%>
<%}%>
このコードは、メッセージが存在する場合に表示します。 メッセージ自体は基本に設定されます:
if ( String .IsNullOrEmpty(UserText))
{
TempData[ "Message" ] = " " ;
return RedirectToAction( "Index" );
}
* This source code was highlighted with Source Code Highlighter .
GETリクエストとPOSTリクエストのロジックを分離する
MVCフレームワークプレビュー5には、特に、POST要求とGET要求のロジックを分離できるすばらしいメカニズムがあります。 この分離は、AcceptVerbs属性を通じて行われます。 たとえば、メインページにユーザー名とパスワードを入力するためのフォームがあるとします。 また、入力されたユーザー名とパスワードの確認、認証、ユーザーの承認を行うログインアクションもあります。 セキュリティのために、ページ上のフォームからのPOSTリクエストのみを処理するように強制することにより、このアクションのアクションを制限できます。 また、他のすべてのリクエストは別のアクションに送信する必要があります。これにより、同じページが返されます。
[AcceptVerbs( "GET" )]
public ActionResult Login()
{
return View( "Index" );
}
[AcceptVerbs( "POST" )]
public ActionResult Login( string userLogin, string userPass)
{
[… …]
return RedirectToAction( "Index" , "Home" );
}
* This source code was highlighted with Source Code Highlighter .
さらに、HttpVerbs列挙がMVCフレームワークベータに登場しました。これを使用して、厳密に型指定された値でAcceptVerbs属性パラメーターを設定できます。
[AcceptVerbs(HttpVerbs.Post)]
キャッシュ管理
MVCフレームワークを使用すると、各アクションの結果のキャッシュを制御できます。 つまり、このリクエストまたはそのリクエストをサーバーまたはクライアントにキャッシュする方法と量を指定できます。 これを行うには、従来のasp.netディレクティブの<%@ OutputCache%>属性[OutputCache]に類似したものがあります。 そのパラメーターは次のとおりです。
パラメータ | 説明 |
VaryByHeader | 条件付きキャッシュが実行されるhttpヘッダーのセミコロン区切り値を含む文字列 |
Varybyparam | GETを使用したクエリ文字列の値またはPOSTを使用したパラメーターに基づいて条件付きキャッシュを設定します |
VaryByContentEncoding | Accept-Encoding http-headerディレクティブの内容に応じたキャッシュ条件を示します |
期間 | Durationは、ページまたはユーザー要素がキャッシュされる時間を秒単位で設定します |
NoStore | ブール値を取ります。 trueの場合、no-storeパラメーターをCache-Control http-headerディレクティブに追加します |
Cacheprofile | web.configおよびキャッシングセクションで指定されたキャッシングプロファイルを指定するために使用されます |
OutputCacheLocation | このパラメーターはキャッシュストレージの場所のルールを記述し、OutputCacheLocation列挙の値の1つを取ります |
VaryByCustom | キャッシングを制御するテキスト。 このテキストが「ブラウザ」の場合、キャッシュはブラウザの名前とそのバージョン(メジャーバージョン)によって条件付きで実行されます。 VaryByCustomに文字列が指定されている場合、Global.asaxファイルのGetVaryByCustomStringメソッドをオーバーライドして条件付きでキャッシュする必要があります。 |
OutputCacheの使用は非常に基本的です。 次の例は、アクションインデックスの結果を10秒間キャッシュする方法を示しています。
[OutputCache(Duration = 10)]
public ActionResult Index()
{
…
}
* This source code was highlighted with Source Code Highlighter .
複雑なページとカスタムモデル
多くの場合、最も異種のデータの多くがページの作成に関係しています。 ポータルのユーザーの個人ページには、選択したニュースのデータ、プロファイルデータ、他の参加者から送信されたメッセージのデータ、天気データ、日付と正確な時間、さらにはさまざまなデータがあります。
データベースに保存される場合、そのようなデータは1つのテーブルに保存されるのではなく、いくつかのテーブルに保存されます。 この場合、ORM-データベースオブジェクトモデルを使用する場合、MVCフレームワークの1ページを作成するには、多数のリストまたは他の変数を初期化し、データを入力する必要があります。
この場合、単語MVCの文字Mを実装して、複雑なデータモデルを作成することをお勧めします。 以下に、このようなモデルを実装するためのオプションの1つの例を示します。
public class BankInfoModel
{
public Bank Bank;
public IEnumerable <BankBranch> BankBranches;
}
* This source code was highlighted with Source Code Highlighter .
値Bankとこの銀行のすべての支店のリストを含むモデルが作成されます(たとえば、いくつかの理由により、単に銀行から支店のリストを取得することはできません)。
モデルを透過的に使用するには、次を実行する必要があります。ビューの基本クラスを次のように再実行します。
部分クラスのパブリックインデックス:ViewPage
に
public partial class Index : ViewPage<BankInfoModel>
* This source code was highlighted with Source Code Highlighter .
これで、ビューコードで、ViewData.Modelを介してBankInfoModel型のモデルのインスタンス化されたインスタンスにアクセスできます。 もちろん、コントローラーはそれを初期化する必要がありますが、これは基本です:
public ActionResult Info( int ? id)
{
var info = new BankInfoModel {Bank = db.Banks.Single(x => x.id == id)};
info.BankBranches = info.Bank.LocationBranches
.Where(x => x.Address.Street.cityId == 1).SelectMany(x => x.BankBranches);
return View(info);
}
* This source code was highlighted with Source Code Highlighter .
intはどこですか? idは、銀行IDを示すパラメーターです
ビューでモデルのインスタンスを使用するのも簡単です。
< div class ="vcard" >
< h1 >< span class ="fn org" > <% =ViewData.Model.Bank.shortName %> </ span ></ h1 >
< p > : < span class ="fn phone" > <% =ViewData.Model.Bank.phone %> </ span ></ p >
</ div >
* This source code was highlighted with Source Code Highlighter .
複合型、ModelBinder
MVCフレームワークは、フォームの値の転送がアクションパラメーターを通じて行われるように設計されています。 たとえば、以下はログインとパスワードのデータを入力するための2つのフィールドがあるフォームです。
< form method ="post" action ="<%= Html.AttributeEncode(Url.Action(" Login ", " Home ")) %>" >
< ul >< li >
< label for ="txtLogin" > </ label > <% = Html.TextBox( "userLogin" , “”, new {id = "txtLogin" }) %> </ li >< li >
< label for ="txtPass" > </ label > <% = Html.Password( "userPass" , “”, new {id = "txtPass" }) %> </ li >< li >
< input type ="submit" value ="" />
</ li ></ ul >
</ form >
* This source code was highlighted with Source Code Highlighter .
ユーザーがこのフォームに入力したデータは、以下に示すように、適切なパラメーターを介してアクションに転送されます。
[AcceptVerbs( "POST")]
パブリックActionResultログイン(文字列userLogin、文字列userPass)
しかし、フォームに多数の入力フィールドが含まれている場合はどうすればよいでしょうか? アクションのために何十ものパラメーターを作成することは可能ですか? いいえ、MVCフレームワークには、多数のメソッドパラメーターのようないステップを回避するメカニズムが含まれています。 このようなメカニズムはModelBinderと呼ばれます。 最初に、フォームを記述するクラスを宣言します。
public class LoginModel
{
public string userLogin { get ; set ; }
public string userPass { get ; set ; }
public LoginModel()
{
}
}
* This source code was highlighted with Source Code Highlighter .
次に、IModelBinderインターフェイスを実装するクラスを定義する必要があります。
public class LoginModelBinder : IModelBinder
{
public object GetValue(ControllerContext controllerContext, string modelName,
Type modelType, ModelStateDictionary modelState)
{
LoginModel modelData = new LoginModel ();
modelData.userLogin = controllerContext. HttpContext .Request[ "userLogin" ];
modelData.userPass = controllerContext. HttpContext .Request[ "userPass" ];
return modelData;
}
}
* This source code was highlighted with Source Code Highlighter .
GetValueメソッドを定義し、リクエストコンテキストを通じてその中にモデルデータを入力することに注意してください。
最終ステップの前に、LoginModelモデルクラスのModelBinder属性を指定する必要があります。
[ModelBinder( typeof (LoginModelBinder))]
public class LoginModel
{
public string userLogin { get ; set ; }
public string userPass { get ; set ; }
public LoginModel()
{
}
}
* This source code was highlighted with Source Code Highlighter .
結論として、フォームから送信されたパラメーターを自動的に初期化するために構造を使用します。
[AcceptVerbs( "POST")]
Public ActionResult Login([ModelBinder(typeof(LoginModelBinder))] LoginModel loginModelData)
このオプションは、MVC Frameworkプレビュー5に登場しました。
MVCフレームワークベータ版は、この点で大幅な改善をもたらしました。 現在、標準の.NETタイプの転送を自動的に処理する組み込みバインダーがあります。 つまり、前の例でModelBinderを作成する代わりに、単純化されたコードを作成できます。
[AcceptVerbs(HttpVerbs.Post)]
パブリックActionResultログイン(LoginModel loginModelData)
さらに、開発者はBind属性を使用できます。これにより、フォームパラメータ名のプレフィックスを制御できるため、値を変更したり、プレフィックスがないことを示すことができます。 同じ属性を使用すると、複合型のパラメーター値に関連付けられるフォームプロパティの「ホワイト」または「ブラック」リストを指定できます。
[AcceptVerbs(HttpVerbs.Post)]
Public ActionResult Login([バインド(プレフィックス=””、インクルード=” userLogin、userPass”)] LoginModel loginModelData)
また、ModelBinderの独自のバリアントを作成する義務はありませんが、このツールは引き続き有用であり、フォームから送信された複合型の値の処理を微調整するのに役立ちます。
生のエラー、無効なURLの傍受
突然発生する不可解なエラーほどユーザーを混乱させるものはないことが知られています。 そのようなエラーがプロジェクトでときどき発生する場合でも、ユーザーができるだけわかりやすい通知を受け取るようにする必要があります。 このような目的のために、エラーページ、未処理の例外のキャッチ、および404 http "Page not found"エラーの処理が使用されます。
未処理の例外をキャッチするには、たとえば次のコードを含むエラー情報を使用して、Views / SharedフォルダーにError.aspxページを作成します。
< span >
! , . < br />
: <% = ViewData.Model.Exception.Message %>
</ span >
* This source code was highlighted with Source Code Highlighter .
すべての未処理の例外をページにリダイレクトするには、各コントローラーでHandleError属性を指定する必要があります。
[HandleError]
パブリッククラスHomeController:コントローラー
さらに、global.asaxで指定されたルートに適合しないすべての無効なURLを処理するには、すべての無効なリクエストを特別なページにリダイレクトする別のルートを作成する必要があります。
routes.MapRoute( "Error"、 "{* url}"、new
{
コントローラー=「エラー」、
action = "Http404"
});
ご覧のとおり、すべての無効なURLはエラーコントローラーのHttp404アクションにつながります。 そのようなコントローラーを作成し、アクションを追加する必要があります。
public class ErrorController : Controller
{
public ActionResult Index()
{
return RedirectToAction( "Http404" );
}
public ActionResult Http404()
{
Response.StatusCode = 404;
return View();
}
}
* This source code was highlighted with Source Code Highlighter .
Http404.aspxビューのコンテンツは基本的なものです。
< h1 > 404 </ h1 >
< p > </ p >
* This source code was highlighted with Source Code Highlighter .
したがって、間違ったルートをナビゲートしようとする試みをキャッチしますが、ルートがテンプレートの下にあるがまだ正しくない場合はどうでしょうか? 解決策は、例外が発生したフィールドチェックです。
public ActionResult Info( int ? id)
{
if (!id.HasValue)
throw new HttpException( "404" );
[ … … ]
}
* This source code was highlighted with Source Code Highlighter .
このようなカスタム例外をキャッチするには、web.configのcustomErrorsセクションを作成または変更する必要があります。
< customErrors mode ="RemoteOnly" >
< error statusCode ="404" redirect ="~/Error/Http404" />
</ customErrors >
* This source code was highlighted with Source Code Highlighter .
したがって、タイプ404のすべてのカスタム例外もHttp404.aspxページにリダイレクトされます。これにより、一般的なアプローチを維持し、「ページが見つかりません」という概念の下で無効なURLとエラーまたはその他の理由で入力されたURLの両方を組み合わせることができますアクセス権の違反などにより、処理が受け入れられない理由。
IIS7でエラーキャプチャを正常に機能させるには、サイトの設定の[エラーページ]セクションで次のパラメーターを設定する必要があります。
おわりに
この記事では、MVCフレームワークでの作業のいくつかの側面を説明しようとしました。 多くのポイントは初歩的であり、一部は見た目ほど単純ではなく、一部はインターネット上で十分に説明されており、一部はまったく説明されていません。 いずれの場合でも、上記の資料は、MVCフレームワークに精通している初心者と、それを使用してWebアプリケーションを作成した経験のある初心者の両方に適したサービスとして役立ちます。
今日のMVCフレームワークは、最終的に製品のベータ版にすぎません。 ただし、このツールを使用すると、MVCパターンのすべての機能を使用してWebアプリケーションを作成できます。 おそらく、この記事を読むと、MVC Frameworkの最終リリースがリリースされますが、これは2008年末までにリリースされる予定ですが、ほとんどの機能は変更されないと想定できます。