ASP.NET MVCの「クラシック」フレンドリーURL

画像

このトピックでは、ASP.NET MVCアプリケーションでwww.site.com/helloworldのようなリンクを作成する方法に焦点を当てます。 「なぜこれが必要なのですか?」と「なぜ通常の人間のルーティングに慣れていないのですか?」とinする感嘆の声が聞こえます。



実際、私たちのプロジェクトはWebフォームを使用したMVCに移行しており、コンテキスト広告は長い間支払われてきました。 ルーティングは素晴らしいことですが、サイトがランディングページだけで構成されているわけではないため、通常のMVCリンク/コントローラー/アクションと信じられないほどフレンドリーなURLが引き続き機能するようなunningな方法でサイトを調整することはできません。 理由は単純です:デフォルトのルーティング( "{controller}/{action}/{id}", new { controller = "Default", action = "Index", id = UrlParameter.Optional }



)はデフォルト値を想定しているため、アクセスするときwww.site.com/helloworldは、アクションインデックスでhelloworldコントローラーに転送しようとします。

悲しみ。

何かしなければなりません。 さらに、各リンクのコントローラーを作成するオプションは明らかに私たちには適していません-それらの暗闇、そして一般的にはポルノですよね?



私たちは他の方法で行きます。 ©





コンセプト



リンクの親しみやすさをチェックするハンドラーをルーティングに配置します-このために正規表現を使用します。

リンクがMVC-shnayaの場合、不要なジェスチャーを行わずに続行します。

リンクが典型的なMVCリンクのように見えない場合、データベースで一致するものを探します-使用するコントローラーとアクション。

何も見つからない場合は、標準のルーティングとデフォルト値を使用してみてください。 404が既にあるので、404。





モデル



画像



とてもシンプルで気取らない。 ここではContentIDが外部キーですが、必要に応じてVARCHAR(MAX)を使用して、ここにコンテンツを書き込むことができます。 コンテンツが複数の部分(メインコンテンツ、タイトル、メタディスクリプションタグなど)に分割されているという事実により、このような実装があります-SEO、わかりました。





実装



実装の基本は次のとおりです。

 routes.MapRoute( "Default", "{controller}/{action}/{id}", new { controller = "Default", action = "Index", id = UrlParameter.Optional } ).RouteHandler = new FriendlyUrlRouteHandler();
      
      





ルーター(MvcRouteHandlerの子孫)にハンドラーをアタッチし、既製の値を処理します。 つまり、最初に、ルーティングメカニズムがリンクを特定し、デフォルト値を入力してから、ビジネスを開始し、必要に応じて値を私たちのものに置き換えます。



  public class FriendlyUrlRouteHandler : MvcRouteHandler { private static readonly Regex TypicalLink = new Regex("^.+/.+(/.*)?"); protected override IHttpHandler GetHttpHandler(RequestContext requestContext) { // Path  www.site.com/helloworld?id=1   /helloworld //      var url = requestContext.HttpContext.Request.Path.TrimStart('/'); if (!string.IsNullOrEmpty(url) && !TypicalLink.IsMatch(url)) { PageItem page = RedirectManager.GetPageByFriendlyUrl(url); if (page != null) { FillRequest(page.ControllerName, page.ActionName ?? "GetStatic", page.ID.ToString(), requestContext); } } return base.GetHttpHandler(requestContext); } /// <summary>  request-   ,    </summary> private static void FillRequest(string controller, string action, string id, RequestContext requestContext) { if (requestContext == null) { throw new ArgumentNullException("requestContext"); } requestContext.RouteData.Values["controller"] = controller; requestContext.RouteData.Values["action"] = action; requestContext.RouteData.Values["id"] = id; } }
      
      







レコードIDをパラメーターとして使用し、ページを読み込むときに、複数のテーブルが結合されたビューを使用します。 このようなトラブルが不要な場合は、レコード全体のIDではなく、ContentIDパラメーターとして渡すだけで済みます。



デフォルトのアクションはGetStaticで、コントローラーの基本クラスで仮想として定義されています。 特定のコントローラーで、彼はデータベースからページのテキストを取得し、セクションの機能とレイアウトを考慮してページを生成します。

  public abstract class BaseController : Controller { /// <summary>     </summary> public virtual ActionResult GetStatic(int id) { return HttpNotFound(); } }
      
      







そして最後に、リダイレクトメカニズム自体。 率直に言って、私が彼を別のクラスに連れて行った理由を覚えていません。 一方、なぜそうではありません。

  public static class RedirectManager { public static PageItem GetPageByFriendlyUrl(string friendlyUrl) { PageItem page = null; using (var cmd = new SqlCommand()) { cmd.Connection = new SqlConnection(/*YourConnectionString*/); cmd.CommandText = "select * from FriendlyUrl where FriendlyUrl = @FriendlyUrl"; cmd.Parameters.Add("@FriendlyUrl", SqlDbType.NVarChar).Value = friendlyUrl.TrimEnd('/'); cmd.Connection.Open(); using (var reader = cmd.ExecuteReader(CommandBehavior.CloseConnection)) { if (reader.Read()) { page = new PageItem { ID = (int) reader["Id"], ControllerName = (string) reader["ControllerName"], ActionName = (string) reader["ActionName"], FriendlyUrl = (string) reader["FriendlyUrl"], }; } } return page; } } }
      
      









結果



最終的に、私たちはまさに私たちが目指していたものを手に入れました。 データベースに入力した後、正しいページへのリダイレクトを取得しましたが、アドレスバーには何も変化がなく、追加のダンスなしで200 OKを取得しました。



もちろん、状況は非常に一般的ではありません-ほとんどの場合、標準ルーティングで十分です:たとえば、URLを使用してデータベースからデータを取得するStaticなどのコントローラーを作成できます。 しかし、コンテキスト広告がすでに支払われている場合、または追加のスラッシュが1つもないリンクを作成したいという単純な欲求がある場合、説明されているオプションは非常に適しています。



最後に、タスクを設定し、正常に対処しました。

私の意見では、これは良いことです。



All Articles