web-dev-qa-db-ja.com

ハイフンを含むURLのASP.netMVCサポート

メソッド名またはクラス名ではハイフンがサポートされていないため、MvcRouteHandlerで受信URLのアクションセクションとコントローラーセクションのすべてのハイフンをアンダースコアに変換する簡単な方法はありますか?.

これは、MapRouteメソッドを引き続き使用しながら、アクションedit_detailsおよびコントローラーtest_pagecontrollerへのsample.com/test-page/edit-detailsマッピングなどの構造をサポートできるようにするためです。

アクション名属性を指定し、コントローラー名にハイフンをサポートして、これを実現するために手動でルートを追加できることを理解していますが、自動化された方法を探しているので、新しいコントローラーとアクションを追加するときにエラーを保存します。

32
John

私は解決策を考え出しました。 MvcRouteHandler内のrequestContextには、単純な置換を実行できるコントローラーとアクションの値が含まれています。

Public Class HyphenatedRouteHandler
    Inherits MvcRouteHandler

    Protected Overrides Function GetHttpHandler(ByVal requestContext As System.Web.Routing.RequestContext) As System.Web.IHttpHandler
        requestContext.RouteData.Values("controller") = requestContext.RouteData.Values("controller").ToString.Replace("-", "_")
        requestContext.RouteData.Values("action") = requestContext.RouteData.Values("action").ToString.Replace("-", "_")
        Return MyBase.GetHttpHandler(requestContext)
    End Function

End Class

次に、routes.MapRouteを同等のroutes.Addに置き換える必要があります。新しいルートハンドラーを指定します。 MapRouteではカスタムルートハンドラーを指定できないため、これは必須です。

routes.Add(New Route("{controller}/{action}/{id}", New RouteValueDictionary(New With {.controller = "Home", .action = "Index", .id = ""}), New HyphenatedRouteHandler()))
18
John

それを好む人のためのジョンの投稿のC#バージョン: C#とVBバージョン

public class HyphenatedRouteHandler : MvcRouteHandler{
        protected override IHttpHandler  GetHttpHandler(RequestContext requestContext)
        {
            requestContext.RouteData.Values["controller"] = requestContext.RouteData.Values["controller"].ToString().Replace("-", "_");
            requestContext.RouteData.Values["action"] = requestContext.RouteData.Values["action"].ToString().Replace("-", "_");
            return base.GetHttpHandler(requestContext);
        }
    }

...そして新しいルート:

routes.Add(
            new Route("{controller}/{action}/{id}", 
                new RouteValueDictionary(
                    new { controller = "Default", action = "Index", id = "" }),
                    new HyphenatedRouteHandler())
        );

次の方法も使用できますが、ビューにMy-Actionという名前を付ける必要があることに注意してください。これは、VisualStudioでビューファイルを自動生成する場合に煩わしい場合があります。

[ActionName("My-Action")]
public ActionResult MyAction() {
    return View();
}
32
Andrew

この場合、実際に行う必要があるのは、URLに表示するハイフンを使用してビューに名前を付け、コントローラーでハイフンを削除してから、ハイフンを含むActionName属性を追加することです。アンダースコアを付ける必要はまったくありません。

edit-details.aspxというビューがあります

そして、このようなコントローラーを持っています:

[ActionName("edit-details")]
public ActionResult EditDetails(int id)
{
    // your code
}
14
Chris Conway

これはかなり古い質問だと思いますが、私にとってこれはハイフンを含むURLを受け入れる話の半分に過ぎず、残りの半分はMVCフレームワークでHtml.ActionLinkやその他のヘルパーを使用しながらこれらのURLを生成しています。私は同様のカスタムルートクラスを作成することでこれを解決しました。これは、グーグル検索からここに来る人を助ける場合のコードです。また、URLの下部ケーシングも含まれています。

public class SeoFriendlyRoute : Route
{
     // constructor overrides from Route go here, there is 4 of them

     public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
     {
          var path = base.GetVirtualPath(requestContext, values);

          if (path != null)
          {
              var indexes = new List<int>();
              var charArray = path.VirtualPath.Split('?')[0].ToCharArray();
              for (int index = 0; index < charArray.Length; index++)
              {
                  var c = charArray[index];
                  if (index > 0 && char.IsUpper(c) && charArray[index - 1] != '/')
                      indexes.Add(index);
              }

              indexes.Reverse();
              indexes.Remove(0);
              foreach (var index in indexes)
                  path.VirtualPath = path.VirtualPath.Insert(index, "-");

              path.VirtualPath = path.VirtualPath.ToLowerInvariant();
          }

          return path;
     }
}

次に、ルートを追加するときに、RouteCollection拡張機能を作成するか、グローバルルーティング宣言で以下を使用することができます。

routes.Add(
        new SeoFriendlyRoute("{controller}/{action}/{id}", 
            new RouteValueDictionary(
                new { controller = "Default", action = "Index", id = "" }),
                new HyphenatedRouteHandler())
    );
9
dsteuernol

この答えをくれたdsteuernolに感謝します-まさに私が探していたものです。ただし、現在のページからコントローラーまたはエリアが暗示されるシナリオをカバーするために、HyphenatedRouteHandlerを拡張する必要があることがわかりました。たとえば、@ Html.ActionLink( "My Link"、 "Index")を使用します

GetHttpHandlerメソッドを次のように変更しました。

public class HyphenatedRouteHandler : MvcRouteHandler
    {
        /// <summary>
        /// Returns the HTTP handler by using the specified HTTP context.
        /// </summary>
        /// <param name="requestContext">The request context.</param>
        /// <returns>
        /// The HTTP handler.
        /// </returns>
        protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
        {

            requestContext.RouteData.Values["controller"] = ReFormatString(requestContext.RouteData.Values["controller"].ToString());
            requestContext.RouteData.Values["action"] = ReFormatString(requestContext.RouteData.Values["action"].ToString());

            // is there an area
            if (requestContext.RouteData.DataTokens.ContainsKey("area"))
            {
                requestContext.RouteData.DataTokens["area"] = ReFormatString(requestContext.RouteData.DataTokens["area"].ToString());
            }

            return base.GetHttpHandler(requestContext);
        }


        private string ReFormatString(string hyphenedString)
        {
            // lets put capitals back in

            // change dashes to spaces
            hyphenedString = hyphenedString.Replace("-", " ");

            // change to title case
            hyphenedString = CultureInfo.InvariantCulture.TextInfo.ToTitleCase(hyphenedString);

            // remove spaces
            hyphenedString = hyphenedString.Replace(" ", "");

            return hyphenedString;
        }
    }

大文字を元に戻すということは、暗黙のコントローラーまたは領域が正しくハイフンでつながれたことを意味します。

2
Sylvia

EveryMvc/Urlをevery-mvc/urlに暗黙的に変換するこの問題のオープンソースNuGetライブラリを開発しました。

破線のURLは、SEOにやさしく、読みやすくなっています。 ( 私のブログ投稿の詳細

NuGetパッケージ: https://www.nuget.org/packages/LowercaseDashedRoute/

これをインストールするには、プロジェクトを右クリックしてNuGetパッケージマネージャーを選択し、Visual StudioでNuGetウィンドウを開き、[オンライン]タブで「小文字の破線のルート」と入力するとポップアップが表示されます。

または、パッケージマネージャーコンソールでこのコードを実行することもできます:

Install-Package LowercaseDashedRoute

その後、App_Start/RouteConfig.csを開き、既存のroute.MapRoute(...)呼び出しをコメントアウトして、代わりにこれを追加する必要があります。

routes.Add(new LowercaseDashedRoute("{controller}/{action}/{id}",
  new RouteValueDictionary(
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }),
    new DashedRouteHandler()
  )
);

それでおしまい。すべてのURLは小文字で、破線で、何もしなくても暗黙的に変換されます。

オープンソースプロジェクトのURL: https://github.com/AtaS/lowercase-dashed-route

1
Ata S.

プロジェクトをMVC5にアップグレードすると、属性ルーティングを利用できます。

[Route("controller/my-action")]
public ActionResult MyAction() {
    return View();
}

承認されたソリューションよりもこのアプローチの方がはるかに好きです。これにより、コントローラーのアクション名とビューのファイル名にアンダースコアが残り、ビューのUrl.Actionヘルパーにハイフンが残ります。私は一貫性を好み、名前がどのように変換されるかを覚えておく必要はありません。

0
Rob

MVC 5.2.7では、属性を使用して簡単に指定できます

ActionName

[ActionName("Import-Export")]
public ActionResult ImportExport()
{
    return View();
}

次に、ビューに名前を付けます

Import-Export.cshtml

その場合、リンクは次のようになります。

@Html.ActionLink("Import and Export", "Import-Export", "Services")

これは次の形式です。

@Html.ActionLink("LinkName", "ActionName", "ControllerName")
0
Paul Zahra

各URLのマップを作成せずに方法がわからない:

routes.MapRoute("EditDetails", "test-page/edit-details/{id}", new { controller = "test_page", action = "edit_details" });
0
Paul Hiles