Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么我会收到例外情况;在控制器“上未找到公共操作方法”;?_C#_Asp.net Mvc_Exception_Routing - Fatal编程技术网

C# 为什么我会收到例外情况;在控制器“上未找到公共操作方法”;?

C# 为什么我会收到例外情况;在控制器“上未找到公共操作方法”;?,c#,asp.net-mvc,exception,routing,C#,Asp.net Mvc,Exception,Routing,我使用下面的文章来支持多文化路线 如果您查看“注册路由”部分,您将看到当前路由(在“RegisterRoutes”方法中)用“{culture}”段更新 不同之处在于,我希望保留当前路由,并为每个路由添加一个重复的“{culture}”段,因此对于像“foo/bar”这样的路由,我将获得一个重复的“{culture}/foo/bar” 你可以看到,我也在确保新路线优先 public static void MapMvcMultiCultureAttributes(this RouteCollec

我使用下面的文章来支持多文化路线

如果您查看“注册路由”部分,您将看到当前路由(在“RegisterRoutes”方法中)用“{culture}”段更新

不同之处在于,我希望保留当前路由,并为每个路由添加一个重复的“{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
{
}
public static void RegisterRoutes(RouteCollection routes)
{
     routes.MapMvcMultiCultureAttributes();
     routes.LowercaseUrls = true;
}
我的“RegisterRoutes”方法如下所示:

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
{
}
public static void RegisterRoutes(RouteCollection routes)
{
     routes.MapMvcMultiCultureAttributes();
     routes.LowercaseUrls = true;
}
现在,如果我这样做:

  • /foo/bar-工作
  • /en US/foo/bar-HttpException在控制器“MyController”上未找到公共操作方法“MyAction”

我可以给你举一个我将如何做的例子。你正在使用的那个例子很古老

  • 在控制器中实现(使用继承)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);
    }
    
  • 添加一些路线

            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
            routes.MapRoute(
                name: "Custom",
                url: "{controller}/{action}/{culture}",
                defaults: new { culture = CultureHelper.GetDefaultCulture(), controller = "Coordinate", action = "Index" }
    
  • 实现一个区域性帮助器类

  •         routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    
            routes.MapRoute(
                name: "Custom",
                url: "{controller}/{action}/{culture}",
                defaults: new { culture = CultureHelper.GetDefaultCulture(), controller = "Coordinate", action = "Index" }
    
    公共静态类CultureHelper { 私有静态只读列表_cultures=新列表{ “目录” })

    公共静态bool IsRighToLeft()
    {
    返回System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.IsRightToLeft;
    }
    公共静态字符串GetImplementedCulture(字符串名称)
    {
    if(string.IsNullOrEmpty(name))
    return GetDefaultCulture();//返回默认区域性
    if(!CultureInfo.GetCultures(cultureType.SpecificCultures).Any(c=>c.Name.Equals(Name,StringComparison.InvariantCultureIgnoreCase)))
    return GetDefaultCulture();//如果默认区域性无效,则返回默认区域性
    if(_cultures.Any(c=>c.Equals(name,StringComparison.InvariantCultureIgnoreCase)))
    返回name;//接受它
    var n=GetNeutralCulture(名称);
    foreach(文化中的变量c)
    如果(c.StartsWith(n))
    返回c;
    return GetDefaultCulture();//返回默认区域性,因为找不到匹配项
    }
    公共静态字符串GetDefaultCulture()
    {
    返回“en GB”;//返回默认区域性,en GB
    }
    公共静态字符串GetCurrentCulture()
    {
    返回Thread.CurrentThread.CurrentCulture.Name;
    }
    公共静态字符串GetCurrentNeutralCulture()
    {
    返回GetNeutralCulture(Thread.CurrentThread.CurrentCulture.Name);
    }
    公共静态字符串GetNeutralCulture(字符串名称)
    {
    如果(!name.包含(“-”)返回名称;
    返回名称。拆分('-')[0];//仅读取第一部分。例如“en”、“es”
    }
    公共静态列表GetImplementedLanguageNames()
    {
    List languageNames=新列表();
    foreach(字符串区域性在_区域性中)
    {
    添加(新的键值对(culture,CultureInfo.GetCultureInfo(culture.EnglishName));
    }
    languageNames.Sort((第一对,下一对)=>
    {
    返回firstPair.Value.CompareTo(nextPair.Value);
    });
    字符串currCulture=GetCurrentCulture();
    移除(新的键值对(currCulture,CultureInfo.GetCultureInfo(currCulture.EnglishName));
    插入(0,新的键值对(currCulture,CultureInfo.GetCultureInfo(currCulture.EnglishName));
    返回语言;
    }
    公共静态字符串GetDateTimeUsingCurrentCulture(DateTime dateToConvert)
    {
    CultureInfo ci=新的CultureInfo(GetCurrentCulture());
    返回dateToConvert.ToString(ci.DateTimeFormat.ShortDatePattern+''+ci.DateTimeFormat.ShortTimePattern);
    }
    }
    
    我认为使用属性路由无法实现这一点,因为传递给RegisterRoutes的RouteCollection及其后续RouteData非常不同,并且使用了无法访问的内部类

    我已经确定RouteData需要一个名为“MS_DirectRouteMatches”的键,其值是RouteData的集合。如果您想进一步挖掘,请使用谷歌MS_DirectRouteMatches

    最终,我假设这不是一个扩展点


    如果你坚持传统的路线,你会获得更多的成功。我发现您的代码在这个场景中运行得非常好,但我希望您已经知道这一点。很抱歉,我无法为您提供更好的解决方案。

    据我所知,它没有使用父操作结果。我不知道为什么会这样。您可以在派生类中重写ActionResult,但对我来说,继承中似乎有问题。。你管理班级的方式有问题

    public class MyBaseController: Controller
    {
        [HttpGet]
        [Route("bar")]
        public virtual ActionResult MyAction(){
        {
            return Content("Hello stranger!");
        }
    }
    
    因此,假设这不起作用:

    [RoutePrefix("foo")]
    public class MyController: MyBaseController
    {
    
        [HttpGet]
        [Route("foo")]
        public override ActionResult MyAction(){
        {
            return Content("Hello stranger!");
        }
    }
    
    我建议这样做:

    [RoutePrefix("foo")]
    public class MyController: MyBaseController
    {
    
        [HttpGet]
        [Route("foo")]
        public  ActionResult MyAction(){
        {
            return Content("Hello stranger!");
        }
    }
    
    这至少会告诉您继承是否有缺陷,您可以检查代码


    另一种解决方法是使用一个控制器和两种不同格式的方法。

    您的
    注册表项
    方法内容是什么。@RezaAghaei更新了。您在哪里声明了默认路由?没有默认路由,我完全依赖于属性(我不希望使用默认值的经典控制器/操作路由)。哦,没有看到该控制器。感谢您的示例,但我不希望在当前路由与指定路由不同(或为空)的情况下重定向,我还希望{culture}段成为第一段,并使用任何类型的路由(普通路由或路由属性)。因此用户将能够使用指定的或未指定的区域性访问我的路由(无重定向)。