URL生成方式の進化について述べる
13210 ワード
Webアプリケーションを開発する際には、ページに大量のリンクが配置されますが、リンクの生成方法は簡単に見えますが、さまざまな変化があり、それぞれメリットとデメリットがあります.ASP.で見てみましょうNET MVCアプリケーションのビューで、リンクアドレスを生成するにはどのような方法があるのか、それらの間でどのように変化しているのか.
ターゲット
例として、ターゲットURLが必要です.ここでの目標は、次のアクションのURL、つまり記事の詳細ページです.
私達の目標URLは文章のIDとタイトルの連合で、その中のタイトルの中のスペースはとても短い横線に置き換えます——文章のタイトルをURLに入れるのは自然にSEOのためです.そこで私たちはこのようなRouteルールを使用します.
URL Routingがarticleにキャプチャされた後、その形式は次のようになります.
私たちはこのIDだけを考えていますが、後ろの文字列はURLの中にありますが、完全に無視されています.実際のプロジェクトでは、このような文字列からIDを抽出し、対応するArticleオブジェクトを取得するModel Binderを作成できます.しかし、私たちの今はこれに注目していません.
私たちの目標はただ一つです.URLを生成する方法です.
方法1:直接接続文字列
これは最も直接的で、最も考えやすい方法です.
このやり方はASP.NETの誕生は私たちと一緒に歩いてきて、もう7、8年になりました.ほとんどの友达はそれに慣れていないと信じています.その利点は自然に最も簡単で、最も直接的で、ほとんど敷居がなく、準備も必要なく直接使用することができ、理論的には性能も最適です.しかし、その欠点も明らかです.それは、ページごとにこのような文字列を繰り返す必要があります.私たちのURLの生成ルールが急に変わったらどうなるか考えてみましょう.私たちはすべてのリンクを生成する場所を見つけて、一つ一つ変えなければなりません.これは往々にして大きな工事であり、非常に間違いやすい.静的検査に頼ることができないからだ.従って,実際には,急速に開発された超小型でない限り,投げ放題の実験的プロジェクトを行うにつれて,このようなやり方は一般的に推奨されない.
方法2:補助方法の使用
方法1の欠点を回避するために、補助方法を使用してURLを生成することができます.
URLを生成する補助方法をUrlHelperの拡張方法と書き、ページ上でURLを生成することができます(余分なマークは省略します):
このアプローチの利点は、URLを生成するロジックを1つに集約することであり、変更が必要な場合はこの場所を修正するだけでよく、副作用がほとんどなく、使用も簡単です.その欠点は、このURLの変更がRoute構成の変化に関連している場合(例えば、http://www.domain.com/article/5になるhttp://articles.domain.com/5)を選択すると、ToArticleメソッドも変更する必要があります.すなわち,この方法はDRY(Don’t Repeat Yourself)の原則を貫徹するのにまだ不十分である.しかし、一般的なプロジェクトにとって、このやり方には大きな問題はありません.これもURL方式を構築するベースラインです.
方法3:Route構成からURLを生成する
URL Routingの双方向の役割については数回も言及しましたが、Routeルールを構成すると、URLを生成するために使用できます.
Route構成では、Route Valueコレクションの値に基づいてURLを生成する方法がわかりますので、この役割を任せてください.一般的には、Routeルールの名前を指定します.これにより、各ルールを試行するコストが節約され、競合問題に悩まされることもありません.この場合,URLに変化が必要であっても,Routeルールを調整すればよい--ルールの「値」に対する需要が変わらなければよい.例えば、前に述べたURLの変更は、Route構成を次のように調整するだけです.
このアプローチの利点は、「自動」がRoute構成と同期し、追加の論理がほとんど必要ないことです.その欠点は、パフォーマンスの観点から「細かい」差がある可能性があることです(実際の応用で重要かどうかは別ですが).
方法4:Lambda式を使用してURLを生成する
Lambda式を使用してURLを生成するメリットもよく強調します.
ASP.NET MVCでは,1つのURLの最終目標はあくまでアクションであるため,コードにこれをより直感的に表現できれば,コードの可読性をさらに向上させることができる.この点はASP.NET MVC 1.0が持参したMvcFuturesプロジェクトにはすでに体現されているが、残念ながら十分ではなく、実用的な価値はほとんどない.しかし、MvcPatchプロジェクトを使用して開発することもできます.Lambda式を使用してURLを生成する完全な能力を提供し、MvcFuturesの補助方法に対して様々な補足を行います. ActionNameAttribute をサポートパフォーマンス向上 パラメータの一部を無視することができる Routeルールの名前 を指定できます.は、アクションの複雑なパラメータの双方向変換 をサポートする.
この方法では、Actionメソッドを簡単に変更する必要があります.
アクションメソッドにはRouteNameAttributeとマークされており、Routeルールの名前(4点目)を指定しています.また、ArticleBinderは、ArticleオブジェクトからRoute Valueに変換する新しいインタフェースIrouteBinderを実現します.
このアプローチの利点は,「URLを生成する」という作業を基本的に回避し,アクションメソッドという根本的な目標に注目することである.また、さまざまなロジックも集約されており、Actionメソッドの周囲に囲まれており、問題が発生しても四散クエリを必要とせず、ArticleオブジェクトをRoute Valueに変換する役割も対応する操作とともに、独立したユニットテストが容易になります.また、Lambda式を使用してURLを生成すると、コンパイラの静的チェックも得られ、コンパイル中にできるだけ多くの問題を解決できることが保証されます.
その欠点は主に複雑で、MvcPatchプロジェクトを使用しない場合は、そんなに簡単ではない多くの補助方法を自分で補充する必要があるかもしれません.また、ビューのコードページが少し多くなりました.また、式ツリー解析に基づいたアプローチでは、パフォーマンスが多少損なわれる可能性がありますが、次回はこの問題に注目します.
方法5:Lambda式の使用を簡略化する
5つ目の方法は実は前者の補充です.例えば、このような補助方法を準備することができます.
これにより、ページ上でArticleControllerクラスを指定する必要がなくなります.このクラスの名前は確かに長いです.
あるいは、方法2または3を組み合わせて、追加の補助方法を提供することができます.
最終的にどの補助方法を使うかについては、問題は大きくないと思います.前者の「準備作業」は簡単で、コントローラごとに補助方法を用意するだけで十分ですが、後者はアクションごとに補助方法を提供する必要がありますが、使いやすいです.
このアプローチの利点は,Lambda式によるURL構築の利点を継承することに加え,その使用を簡略化することである.欠点についてはLambda式と似ているかもしれませんが、例えば準備作業が多く、性能は理論的にやや劣っています.
5つ目の方法は、私もASPにいます.NET MVCプロジェクトで使用される「標準的なやり方」.
まとめ
今回は「URL生成」という簡単な目標を様々な方法で「進化」し、選択して使用することができます.この進化の過程は、実は一歩一歩欠点を発見し、的確な改善を行う過程でもある.私たちはASPを使っていますが.NET MVCのビューはプレゼンテーションの担体として用いられるが、その方式や考え方はこれに限らずASP.NET MVCの他の態様(ControllerでURLを生成するなど)、またはWeb開発に関連しないアプリケーション開発においても、他のモデル(WebFormsなど)が挙げられる.
ターゲット
例として、ターゲットURLが必要です.ここでの目標は、次のアクションのURL、つまり記事の詳細ページです.
public class ArticleController : Controller
{
public ActionResult Detail(Article article)
{
...
}
}
public class Article
{
public int ArticleID { get; set; }
public string Title { get; set; }
}
私達の目標URLは文章のIDとタイトルの連合で、その中のタイトルの中のスペースはとても短い横線に置き換えます——文章のタイトルをURLに入れるのは自然にSEOのためです.そこで私たちはこのようなRouteルールを使用します.
routes.MapRoute(
"Article.Detail", // Route name
"article/{article}", // URL with parameters
new { controller = "Article", action = "Detail" } // Parameter defaults
);
URL Routingがarticleにキャプチャされた後、その形式は次のようになります.
10-this-is-the-title
私たちはこのIDだけを考えていますが、後ろの文字列はURLの中にありますが、完全に無視されています.実際のプロジェクトでは、このような文字列からIDを抽出し、対応するArticleオブジェクトを取得するModel Binderを作成できます.しかし、私たちの今はこれに注目していません.
私たちの目標はただ一つです.URLを生成する方法です.
方法1:直接接続文字列
これは最も直接的で、最も考えやすい方法です.
foreach (var article in Models.Articles) { %>
<a href="/article/= article.ArticleID %>-= Url.Encode(article.Title.Replace(' ', '-')) %>">
= Html.Encode(article.Title) %>
a>
} %>
このやり方はASP.NETの誕生は私たちと一緒に歩いてきて、もう7、8年になりました.ほとんどの友达はそれに慣れていないと信じています.その利点は自然に最も簡単で、最も直接的で、ほとんど敷居がなく、準備も必要なく直接使用することができ、理論的には性能も最適です.しかし、その欠点も明らかです.それは、ページごとにこのような文字列を繰り返す必要があります.私たちのURLの生成ルールが急に変わったらどうなるか考えてみましょう.私たちはすべてのリンクを生成する場所を見つけて、一つ一つ変えなければなりません.これは往々にして大きな工事であり、非常に間違いやすい.静的検査に頼ることができないからだ.従って,実際には,急速に開発された超小型でない限り,投げ放題の実験的プロジェクトを行うにつれて,このようなやり方は一般的に推奨されない.
方法2:補助方法の使用
方法1の欠点を回避するために、補助方法を使用してURLを生成することができます.
public static class ArticleUrlExtensions
{
public static string ToArticle(this UrlHelper helper, Article article)
{
return "/article/" + article.ArticleID + "-" + helper.Encode(article.Title.Replace(' ', '-'));
}
}
URLを生成する補助方法をUrlHelperの拡張方法と書き、ページ上でURLを生成することができます(余分なマークは省略します):
<a href="= Url.ToArticle(article) %>">...a>
このアプローチの利点は、URLを生成するロジックを1つに集約することであり、変更が必要な場合はこの場所を修正するだけでよく、副作用がほとんどなく、使用も簡単です.その欠点は、このURLの変更がRoute構成の変化に関連している場合(例えば、http://www.domain.com/article/5になるhttp://articles.domain.com/5)を選択すると、ToArticleメソッドも変更する必要があります.すなわち,この方法はDRY(Don’t Repeat Yourself)の原則を貫徹するのにまだ不十分である.しかし、一般的なプロジェクトにとって、このやり方には大きな問題はありません.これもURL方式を構築するベースラインです.
方法3:Route構成からURLを生成する
URL Routingの双方向の役割については数回も言及しましたが、Routeルールを構成すると、URLを生成するために使用できます.
public static string ToDetail(this UrlHelper helper, Article article)
{
var values = new
{
article = article.ArticleID + "-" + helper.Encode(article.Title.Replace(' ', '-'))
};
var path = helper.RouteCollection.GetVirtualPath(
helper.RequestContext, "Article.Detail", new RouteValueDictionary(values));
return path.VirtualPath;
}
Route構成では、Route Valueコレクションの値に基づいてURLを生成する方法がわかりますので、この役割を任せてください.一般的には、Routeルールの名前を指定します.これにより、各ルールを試行するコストが節約され、競合問題に悩まされることもありません.この場合,URLに変化が必要であっても,Routeルールを調整すればよい--ルールの「値」に対する需要が変わらなければよい.例えば、前に述べたURLの変更は、Route構成を次のように調整するだけです.
routes.MapDomain(
"Article",
"http://articles.{*domain}",
innerRoutes =>
{
innerRoutes.MapRoute(
"Detail",
"",
new { controller = "Article", action = "Detail" });
};
このアプローチの利点は、「自動」がRoute構成と同期し、追加の論理がほとんど必要ないことです.その欠点は、パフォーマンスの観点から「細かい」差がある可能性があることです(実際の応用で重要かどうかは別ですが).
方法4:Lambda式を使用してURLを生成する
Lambda式を使用してURLを生成するメリットもよく強調します.
<a href="= Url.Action<ArticleController>(c => c.Detail(article)) %>">...a>
ASP.NET MVCでは,1つのURLの最終目標はあくまでアクションであるため,コードにこれをより直感的に表現できれば,コードの可読性をさらに向上させることができる.この点はASP.NET MVC 1.0が持参したMvcFuturesプロジェクトにはすでに体現されているが、残念ながら十分ではなく、実用的な価値はほとんどない.しかし、MvcPatchプロジェクトを使用して開発することもできます.Lambda式を使用してURLを生成する完全な能力を提供し、MvcFuturesの補助方法に対して様々な補足を行います.
この方法では、Actionメソッドを簡単に変更する必要があります.
public class ArticleBinder : IModelBinder, IRouteBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
...
}
public RouteValueDictionary BindRoute(RequestContext requestContext, RouteBindingContext bindingContext)
{
var article = (Article)bindingContext.Model;
var text = article.ArticleID + "-" + HttpUtility.UrlEncode(article.Title.Replace(' ', '-'));
return new RouteValueDictionary(new { bindingContext.ModelName = text });
}
}
public class ArticleController : Controller
{
[RouteName("Article.Detail")]
public ActionResult Detail([ModelBinder(typeof(ArticleBinder))]Article article)
{
...
}
}
アクションメソッドにはRouteNameAttributeとマークされており、Routeルールの名前(4点目)を指定しています.また、ArticleBinderは、ArticleオブジェクトからRoute Valueに変換する新しいインタフェースIrouteBinderを実現します.
このアプローチの利点は,「URLを生成する」という作業を基本的に回避し,アクションメソッドという根本的な目標に注目することである.また、さまざまなロジックも集約されており、Actionメソッドの周囲に囲まれており、問題が発生しても四散クエリを必要とせず、ArticleオブジェクトをRoute Valueに変換する役割も対応する操作とともに、独立したユニットテストが容易になります.また、Lambda式を使用してURLを生成すると、コンパイラの静的チェックも得られ、コンパイル中にできるだけ多くの問題を解決できることが保証されます.
その欠点は主に複雑で、MvcPatchプロジェクトを使用しない場合は、そんなに簡単ではない多くの補助方法を自分で補充する必要があるかもしれません.また、ビューのコードページが少し多くなりました.また、式ツリー解析に基づいたアプローチでは、パフォーマンスが多少損なわれる可能性がありますが、次回はこの問題に注目します.
方法5:Lambda式の使用を簡略化する
5つ目の方法は実は前者の補充です.例えば、このような補助方法を準備することができます.
public static class ArticleUrlExtensions
{
public static string ToArticle(this UrlHelper urlHelper, Expression<Action<ArticleController>> action)
{
return urlHelper.Action<ArticleController>(action);
}
}
これにより、ページ上でArticleControllerクラスを指定する必要がなくなります.このクラスの名前は確かに長いです.
<a href="= Url.ToArticle(c => c.Detail(article)) %>">...a>
あるいは、方法2または3を組み合わせて、追加の補助方法を提供することができます.
public static class ArticleUrlExtensions
{
public static string ToArticle(this UrlHelper urlHelper, Article article)
{
return urlHelper.Action<ArticleController>(c => c.Detail(article));
}
}
最終的にどの補助方法を使うかについては、問題は大きくないと思います.前者の「準備作業」は簡単で、コントローラごとに補助方法を用意するだけで十分ですが、後者はアクションごとに補助方法を提供する必要がありますが、使いやすいです.
このアプローチの利点は,Lambda式によるURL構築の利点を継承することに加え,その使用を簡略化することである.欠点についてはLambda式と似ているかもしれませんが、例えば準備作業が多く、性能は理論的にやや劣っています.
5つ目の方法は、私もASPにいます.NET MVCプロジェクトで使用される「標準的なやり方」.
まとめ
今回は「URL生成」という簡単な目標を様々な方法で「進化」し、選択して使用することができます.この進化の過程は、実は一歩一歩欠点を発見し、的確な改善を行う過程でもある.私たちはASPを使っていますが.NET MVCのビューはプレゼンテーションの担体として用いられるが、その方式や考え方はこれに限らずASP.NET MVCの他の態様(ControllerでURLを生成するなど)、またはWeb開発に関連しないアプリケーション開発においても、他のモデル(WebFormsなど)が挙げられる.