mvc c# asp net tutorial




「パブリックアクションメソッドがコントローラに見つかりませんでした」という例外が表示されるのはなぜですか? (2)

私は次の記事を使用しています。ASP.NET MVCローカリゼーションへの追加 -マルチカルチャールートをサポートするためにルーティング使用しています

「ルートの登録」セクションを見ると、現在のルートが({RegisterRoutes}メソッドの){culture}セグメントで更新されていることがわかります。

違いは、現在のルートを維持し、それぞれに "{カルチャー}"セグメントを持つ複製を追加したいので、 "foo / bar"のようなルートでは、 "{culture} / foo / bar "

私はまた、新しいルートが最初に来ることを確認しているのを見ることができます。

public static void MapMvcMultiCultureAttributes(this RouteCollection routes, bool inheritedRoutes = true, string defaultCulture = "en-US", string cultureCookieName = "culture")
{
    routes.MapMvcAttributeRoutes(inheritedRoutes ? new InheritedRoutesProvider() : null);

    var multiCultureRouteHandler = new MultiCultureMvcRouteHandler(defaultCulture, cultureCookieName);

    var initialList = routes.ToList();
    routes.Clear();

    foreach (var routeBase in initialList)
    {
        var route = routeBase as Route;
        if (route != null)
        {
            if (route.Url.StartsWith("{culture}"))
            {
                continue;
            }

            var cultureUrl = "{culture}";
            if (!String.IsNullOrWhiteSpace(route.Url))
            {
                cultureUrl += "/" + route.Url;
            }

            var cultureRoute = routes.MapRoute(null, cultureUrl, null, new
            {
                culture = "^\\D{2,3}(-\\D{2,3})?$"
            });

            cultureRoute.Defaults = route.Defaults;
            cultureRoute.DataTokens = route.DataTokens;

            foreach (var constraint in route.Constraints)
            {
                cultureRoute.Constraints.Add(constraint.Key, constraint.Value);
            }

            cultureRoute.RouteHandler = multiCultureRouteHandler;
            route.RouteHandler = multiCultureRouteHandler;
        }

        routes.Add(routeBase);
    }
}

"InheritedRoutesProvider"は次のようになります。

private class InheritedRoutesProvider : DefaultDirectRouteProvider
{
    protected override IReadOnlyList<IDirectRouteFactory> GetActionRouteFactories(ActionDescriptor actionDescriptor)
    {
        return actionDescriptor.GetCustomAttributes(typeof(IDirectRouteFactory), true)
            .Cast<IDirectRouteFactory>()
            .ToArray();
    }
}

私のコントローラは次のようになります:

public class MyBaseController: Controller
{
    [HttpGet]
    [Route("bar")]
    public virtual ActionResult MyAction(){
    {
        return Content("Hello stranger!");
    }
}

[RoutePrefix("foo")]
public class MyController: MyBaseController
{
}

私の "RegisterRoutes"メソッドは次のようになります:

public static void RegisterRoutes(RouteCollection routes)
{
     routes.MapMvcMultiCultureAttributes();
     routes.LowercaseUrls = true;
}

さて、もし私がしたら:

  • / foo / bar - WORKS!
  • / en-US / foo / bar - HttpExceptionパブリックアクションメソッド 'MyAction'がコントローラ 'MyController'に見つかりませんでした

私はあなたに私がそれをやる方法の例を与えることができます。 あなたが使用している例はかなり古いです。

  1. 以下のようにBeginExecuteCoreメソッドをあなたのコントローラに実装する(継承を使用する):

    protected override IAsyncResult BeginExecuteCore(AsyncCallback callback, object state)
    {
        string cultureName = RouteData.Values["culture"] as string;
    
        if (cultureName == null)
            cultureName = Request.UserLanguages != null && Request.UserLanguages.Length > 0 ?
                    Request.UserLanguages[0] :  // obtain it from HTTP header AcceptLanguages
                    null;
    
        // Validate culture name
        cultureName = CultureHelper.GetImplementedCulture(cultureName); // This is safe
    
        if (RouteData.Values["culture"] as string != cultureName)
        {
            // Force a valid culture in the URL
            RouteData.Values["culture"] = cultureName.ToLower(); // lower case too
    
            // Redirect user
            Response.RedirectToRoute(RouteData.Values);
        }
    
        // Modify current thread's cultures            
        Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cultureName);
        Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
    
        return base.BeginExecuteCore(callback, state);
    }
  2. いくつかのルートを追加する

            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
            routes.MapRoute(
                name: "Custom",
                url: "{controller}/{action}/{culture}",
                defaults: new { culture = CultureHelper.GetDefaultCulture(), controller = "Coordinate", action = "Index" }
  3. カルチャーヘルパークラスを実装する

public static class CultureHelper {private static readonly List _cultures =新しいリスト{"listOfClutures"};

    public static bool IsRighToLeft()
    {
        return System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.IsRightToLeft;
    }

    public static string GetImplementedCulture(string name)
    {
        if (string.IsNullOrEmpty(name))
            return GetDefaultCulture(); // return Default culture
        if (!CultureInfo.GetCultures(CultureTypes.SpecificCultures).Any(c => c.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)))
            return GetDefaultCulture(); // return Default culture if it is invalid
        if (_cultures.Any(c => c.Equals(name, StringComparison.InvariantCultureIgnoreCase)))
            return name; // accept it

        var n = GetNeutralCulture(name);
        foreach (var c in _cultures)
            if (c.StartsWith(n))
                return c;
        return GetDefaultCulture(); // return Default culture as no match found
    }

    public static string GetDefaultCulture()
    {
        return "en-GB"; // return Default culture, en-GB
    }
    public static string GetCurrentCulture()
    {
        return Thread.CurrentThread.CurrentCulture.Name;
    }
    public static string GetCurrentNeutralCulture()
    {
        return GetNeutralCulture(Thread.CurrentThread.CurrentCulture.Name);
    }
    public static string GetNeutralCulture(string name)
    {
        if (!name.Contains("-")) return name;

        return name.Split('-')[0]; // Read first part only. E.g. "en", "es"
    }

    public static List<KeyValuePair<string, string>> GetImplementedLanguageNames()
    {
        List<KeyValuePair<string, string>> languageNames = new List<KeyValuePair<string, string>>();

        foreach (string culture in _cultures)
        {
            languageNames.Add(new KeyValuePair<string, string>(culture, CultureInfo.GetCultureInfo(culture).EnglishName));
        }

        languageNames.Sort((firstPair, nextPair) =>
        {
            return firstPair.Value.CompareTo(nextPair.Value);
        });

        string currCulture = GetCurrentCulture();
        languageNames.Remove(new KeyValuePair<string, string>(currCulture, CultureInfo.GetCultureInfo(currCulture).EnglishName));
        languageNames.Insert(0, new KeyValuePair<string, string>(currCulture, CultureInfo.GetCultureInfo(currCulture).EnglishName));

        return languageNames;
    }

    public static string GetDateTimeUsingCurrentCulture(DateTime dateToConvert)
    {
        CultureInfo ci = new CultureInfo(GetCurrentCulture());
        return dateToConvert.ToString(ci.DateTimeFormat.ShortDatePattern + ' ' + ci.DateTimeFormat.ShortTimePattern);
    }
}

RegisterRoutesとそれに続くRouteDataに渡されるRouteCollectionがかなり違っていて、あなたが到達できない内部クラスを使用するため、属性ルーティングでこれを達成できるとは思いません。

私はRouteDataがRouteDataのコレクションである値 "MS_DirectRouteMatches"と呼ばれるキーを期待していると判断しました。 Google MS_DirectRouteあなたがさらに掘り下げたいと思ったら。

最終的に、私はこれが拡張ポイントではないと仮定します。

従来のルーティングに従えば、より多くの成功を収めることができます。 私はあなたのコードがこのシナリオではうまくいきましたが、あなたがすでにそれを知っていることを期待しています。 申し訳ありませんが、私はあなたに良い解決策を与えることができませんでした。





routing