LoginSignup
0
0

More than 5 years have passed since last update.

ASP.NET MVC 共有する部分ビューにもローカルリソースを使いたい

Last updated at Posted at 2016-07-21

ASP.NET MVC 共有する部分ビューにもローカルリソースを使いたい

ASP.NET MVC プロジェクトの多言語化の下ごしらえのために、「しばやん」さんの記事を参考にさせていただきました。

しばやん雑記 ASP.NET MVC 3 の Razor でも多言語対応を試してみる

ただ、プロジェクトには複数のビューで共有する部分ビュー ~/Views/Shared/_Navigation.cshtml などがあり、それらに与えたローカルリソース ~/Views/Shared/App_LocalResources/_Navigation.cshtml.resx を読み込むことができませんでした。

部分ビューは、その名のとおり、親ビューの一部分になるので、GetVirtualPath は親ビューのパスを返すことが要因のようです。そりゃそうだ。

少し手を加えました、変更点は 2つです。

  • Resource メソッドに virtualPath を指定できるようにした。
  • ResourceRaw メソッドを追加。 ActionLink などのヘルパに渡す文字列もリソースにしたかったのが理由です。
    public static class LocalizationHelper
    {
        // 1. virtualPath を指定できるように
        public static MvcHtmlString Resource(this HtmlHelper helper, string expression, string virtualPath = null, params object[] args)
        {
            return MvcHtmlString.Create(ResourceRaw(helper, expression, virtualPath, args));
        }

        // 2. string も返せるように
        public static string ResourceRaw(this HtmlHelper helper, string expression, string virtualPath = null, params object[] args)
        {
            if (virtualPath == null)
            {
                virtualPath = GetVirtualPath(helper);
            }

            return GetResourceString(helper.ViewContext.HttpContext, expression, virtualPath, args);
        }

        public static string Resource(this Controller controller, string expression, params object[] args)
        {
            return GetResourceString(controller.HttpContext, expression, "~/", args);
        }

        private static string GetResourceString(HttpContextBase httpContext, string expression, string virtualPath, object[] args)
        {
            var context = new ExpressionBuilderContext(virtualPath);
            var builder = new ResourceExpressionBuilder();
            var fields = (ResourceExpressionFields)builder.ParseExpression(expression, typeof(string), context);

            if (!string.IsNullOrEmpty(fields.ClassKey))
            {
                return string.Format((string)httpContext.GetGlobalResourceObject(fields.ClassKey, fields.ResourceKey, CultureInfo.CurrentUICulture), args);
            }

            return string.Format((string)httpContext.GetLocalResourceObject(virtualPath, fields.ResourceKey, CultureInfo.CurrentUICulture), args);
        }

        private static string GetVirtualPath(HtmlHelper helper)
        {
            // WebFormView 決め打ちではなくて基底クラスにキャストするように変更
            var view = helper.ViewContext.View as BuildManagerCompiledView;

            if (view != null)
            {
                return view.ViewPath;
            }

            return null;
        }
    }

呼び出し側はこんな感じでしょうか。

// ~/Views/Shared/App_LocalResources/_Navigation.cshtml.resx に定義したキー MyTitle を読み出す
@Html.Resource("MyTitle", "~/Views/Shared/_Navigation.cshtml")

呼び出し側からみると virtualPathが目立ちすぎて少し不細工ですね。
やりようがあるのかもしれませんが、本日はここまで。

最後になりましたが、しばやんさんのソース、リンクのおかげで助かりました、ありがとうございます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0