为什么我收到异常“;在控制器“”上找不到公共操作方法;
本文关键字:找不到 操作方法 异常 为什么 控制器 | 更新日期: 2023-09-27 18:20:04
我正在使用以下文章添加到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-工作
- /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" }
-
实现文化助手类
公共静态类CultureHelper{private静态只读List_cultures=新列表{"俱乐部列表"};
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需要一个名为"MS_DirectRouteMatches"的密钥,该密钥的值是RouteData的集合。谷歌MS_DirectRouteMatches如果你想进一步挖掘。
最终,我认为这不是一个扩展点。
如果你坚持传统的路线,你会获得更多的成功。我发现你的代码在这种情况下运行得很好,但我想你已经知道了。对不起,我不能给你一个更好的解决方案。
从我所看到的,它没有使用父ActionResult。我不知道为什么会发生这种事。您可以重写派生类中的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!");
}
}
这至少会告诉你继承是否有缺陷,你可以检查你的代码。
另一种解决方法是使用一个控制器和两种不同格式的方法。