如何实现MVC全局操作

时间:2017-02-17 18:49:38

标签: c# asp.net-mvc-5 asp.net-routing

我正致力于将全球化 / 本地化添加到相当大规模的应用程序中。除了观点本身,一切都很完整。到目前为止,我的方法是添加一个全局操作,每个视图都可以调用它来获取本地化字符串。我遇到的问题是我似乎无法创造出这样的全球行动。

到目前为止,我向常规action添加了controller ...我可以点击它,一切正常。但是,当我将此方法移动到BaseController中时,操作不再被命中,我收到错误:

  

路由表中没有路由与提供的值匹配。

所以,BaseController方法并不适合我。

接下来,我尝试在" Areas"之外创建一个新的全局控制器。任何视图都应该能够调用。这也不起作用......我无法采取行动。

这是结构的样子:

enter image description here

正如您所看到的,有许多区域都必须有权访问我在蓝色突出显示的controller文件夹中创建的Controllers

以下是我的观点:

 @Html.Action("GetLocalizedString", new { key = "Avatar" })

这是我的行动:

[GET("getlocalizedstring")]
public ActionResult GetLocalizedString(string key)
{
    return Content(ResourceController.GetResourceManger(Identity)[key]);
}

同样,这适用于呈现视图的controller,但我无法从区域外的控制器或basecontroller调用它。我甚至尝试添加area = string.empty来摆脱区域属性,但仍然没有运气。

编辑1(添加路由配置):

private void RegisterMVCRoutes()
{
    try
    {
        Application.Lock();

        RouteTable.Routes.Clear();

        System.Web.Http.GlobalConfiguration.Configure(c => { c.EnableCors(); c.MapHttpAttributeRoutes(); });

        RouteTable.Routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        RouteTable.Routes.IgnoreRoute("{*allaxd}", new { allaxd = @".*\.axd(/.*)?" });

        // bring back MiniProfilers
        if (MiniProfiler.Settings.ProfilerProvider != null)
            StackExchange.Profiling.UI.MiniProfilerHandler.RegisterRoutes();

        RouteTable.Routes.MapAttributeRoutes(config =>
        {
            config.AddRoutesFromAssembly(System.Reflection.Assembly.GetExecutingAssembly());
            config.UseLowercaseRoutes = true;
        });

        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);

        int aspNetRoutingTableEntries = Components.PageRouteEngine.GetInstance().Initialize(RouteTable.Routes);

        // Page Routes for Design Mode
        if (Environment == Constants.SystemEnvironment.Staging || Environment == Constants.SystemEnvironment.RD)
        {
            RouteTable.Routes.Add(new CMSPageRoute("{*designUrlForAddColumn}", new { area = "CMS", controller = "Designer", action = "AddColumn" }, new { designUrlForAddColumn = @".*\.design/AddColumn(/.*)?" }, "CMS"));
            RouteTable.Routes.Add(new CMSPageRoute("{*designUrlForAddRowAbove}", new { area = "CMS", controller = "Designer", action = "AddRowAbove" }, new { designUrlForAddRowAbove = @".*\.design/AddRowAbove(/.*)?" }, "CMS"));
            RouteTable.Routes.Add(new CMSPageRoute("{*designUrlForAddRowAtBottom}", new { area = "CMS", controller = "Designer", action = "AddRowAtBottom" }, new { designUrlForAddRowAtBottom = @".*\.design/AddRowAtBottom(/.*)?" }, "CMS"));
            RouteTable.Routes.Add(new CMSPageRoute("{*designUrlForDeleteRow}", new { area = "CMS", controller = "Designer", action = "DeleteRow" }, new { designUrlForDeleteRow = @".*\.design/DeleteRow(/.*)?" }, "CMS"));
            RouteTable.Routes.Add(new CMSPageRoute("{*designUrlForUpdateUseFullWidthForRow}", new { area = "CMS", controller = "Designer", action = "UpdateUseFullWidthForRow" }, new { designUrlForUpdateUseFullWidthForRow = @".*\.design/UpdateUseFullWidthForRow(/.*)?" }, "CMS"));
            RouteTable.Routes.Add(new CMSPageRoute("{*designUrlForSaveMovedWidget}", new { area = "CMS", controller = "Designer", action = "SaveMovedWidget" }, new { designUrlForSaveMovedWidget = @".*\.design/SaveMovedWidget(/.*)?" }, "CMS"));
            RouteTable.Routes.Add(new CMSPageRoute("{*designUrlForAddNewWidget}", new { area = "CMS", controller = "Designer", action = "AddNewWidget" }, new { designUrlForAddNewWidget = @".*\.design/AddNewWidget(/.*)?" }, "CMS"));
            RouteTable.Routes.Add(new CMSPageRoute("{*designUrlForDeleteWidget}", new { area = "CMS", controller = "Designer", action = "DeleteWidget" }, new { designUrlForDeleteWidget = @".*\.design/DeleteWidget(/.*)?" }, "CMS"));
            RouteTable.Routes.Add(new CMSPageRoute("{*designUrlForMergeColumn}", new { area = "CMS", controller = "Designer", action = "MergeColumn" }, new { designUrlForMergeColumn = @".*\.design/MergeColumn(/.*)?" }, "CMS"));
            RouteTable.Routes.Add(new CMSPageRoute("{*designUrl}", new { area = "CMS", controller = "Designer", action = "Index" }, new { designUrl = @".*\.design(/.*)?" }, "CMS"));
        }

        // Page Routes... Page Index will also be a 404 catch all for routes not found.
        RouteTable.Routes.Add(new CMSPageRoute("{*url}", new { area = "CMS", controller = "Page", action = "Index" }, "CMS"));
    }
    finally
    {
        Application.UnLock();
    }
}

我认为我们的大部分路线配置仅针对我们应用,但也许会有所帮助。再次感谢。

1 个答案:

答案 0 :(得分:0)

我最终使用的方法类似于NightOwl888建议的方法。我没有通过@Html.Action()调用控制器,而是编写了一个扩展方法,并通过@ Html.Translate()调用它。这会将“翻译”代码拉入单个中心位置,并且不需要我修改任何控制器。因为我们将用户语言默认存储在用户的Web身份上,所以我必须从HtmlHelper对象获取它,而不是依赖于我的基本控制器。这是我最终使用的代码 - 希望它能帮助其他人。

    public static class ExtensionMethods
    {
        public static IHtmlString Translate(this HtmlHelper helper, string text)
        {
            if (string.IsNullOrWhiteSpace(text))
                return new HtmlString(string.Empty);

            var identity = (WebIdentity)helper.ViewContext.HttpContext.User.Identity;

            return new HtmlString(ResourceController.GetResourceManger(identity.Learner.SystemLanguageId)[text]);
        }
    }