コード例 #1
0
        /// <summary>
        /// Set up the localized routes for the controller model.
        /// It uses the [LocalizationRoute] attributes and if no attributes are found it uses culture/controllerName.
        /// </summary>
        /// <param name="controllerModel"></param>
        public void AddControllerRoutes(ControllerModel controllerModel)
        {
            string controllerName = controllerModel.ControllerName;

            // If the controller is the default controller then add the "/", "/culture" routes.
            // If we don't do this then "/" or "/culture" would throw 404.
            // Instead /Default would be the only way to access the default controller.
            if (controllerName.Equals(LocalizationRouteDataHandler.DefaultController, StringComparison.Ordinal))
            {
                // Set up the "/", "/culture1", "/culture2" route templates for all supported cultures.
                foreach (var kvp in LocalizationRouteDataHandler.SupportedCultures)
                {
                    string template = LocalizationRouteDataHandler.DefaultCulture == kvp.Key ? "" : kvp.Key;

                    AttributeRouteModel defaultRoute = new AttributeRouteModel();
                    defaultRoute.Template = template;
                    AddAttributeRouteModel(controllerModel.Selectors, defaultRoute);
                }
            }

            LocalizationRouteDataHandler.AddControllerRouteData(controllerName, LocalizationRouteDataHandler.DefaultCulture, controllerName);

            // Create the route for the controller to /Default.
            // Since DefaultController also should be reachable by /Default.
            // This adds the /Default route template to controllerModel.Selectors so it is reachable by both / and /Default.
            AttributeRouteModel controllerRoute = new AttributeRouteModel();

            controllerRoute.Template = controllerModel.ControllerName;
            AddAttributeRouteModel(controllerModel.Selectors, controllerRoute);

            AddControllerLocalizedRoutes(controllerModel);
        }
コード例 #2
0
        /// <summary>
        /// Add the localized routes for the controller model
        /// </summary>
        /// <param name="controllerModel"></param>
        public void AddControllerLocalizedRoutes(ControllerModel controllerModel)
        {
            // Get all the [LocalizationRoute] Attributes from the controller
            var    controllerLocalizations = controllerModel.Attributes.OfType <LocalizationRouteAttribute>().ToList();
            string controllerName          = controllerModel.ControllerName;

            // Keep track of which cultures did not have a [LocalizationRoute] attribute so they can have one added programmatically.
            HashSet <string> notFoundCultures = LocalizationRouteDataHandler.SupportedCultures.Select(kvp => kvp.Key).ToHashSet();

            notFoundCultures.Remove(LocalizationRouteDataHandler.DefaultCulture);

            // Loop over all [LocalizationRoute] attributes
            foreach (LocalizationRouteAttribute attribute in controllerLocalizations)
            {
                string template = attribute.Culture;
                // If the attributeRoute isn't empty then we use the route name
                if (!String.IsNullOrEmpty(attribute.Route))
                {
                    // Add / if the route doesn't start with /
                    // Otherwise the template would be {culture}{route}.
                    // Instead of {culture}/{route}
                    if (!attribute.Route.StartsWith("/"))
                    {
                        template += "/";
                    }
                    template += attribute.Route;
                }
                // If attribute.Route is empty then we use the controller name so it's not an empty name.
                else
                {
                    template += "/" + controllerName;
                }

                AttributeRouteModel localRoute = new AttributeRouteModel();
                localRoute.Template = template;
                AddAttributeRouteModel(controllerModel.Selectors, localRoute);

                // Add the route to the localizations dictionary
                LocalizationRouteDataHandler.AddControllerRouteData(controllerName, attribute.Culture, template);
                // Remove it from the not Found Cultures list since the culture had a [LocalizationRoute] attribute.
                notFoundCultures.Remove(attribute.Culture);
            }

            // Add the remaining cultures that didn't have [LocalizationRoute] attributes.
            foreach (string culture in notFoundCultures)
            {
                string template = culture;
                if (!controllerName.Equals(LocalizationRouteDataHandler.DefaultController, StringComparison.CurrentCultureIgnoreCase))
                {
                    template += "/" + controllerName;
                }

                AttributeRouteModel localRoute = new AttributeRouteModel();
                localRoute.Template = template;
                AddAttributeRouteModel(controllerModel.Selectors, localRoute);

                LocalizationRouteDataHandler.AddControllerRouteData(controllerName, culture, template);
            }
        }
コード例 #3
0
        /// <summary>
        /// Get the url and url with parameter data if possible.
        /// </summary>
        /// <param name="context">The context to get attributes and route values from.</param>
        /// <param name="culture">The culture to get the url result for.</param>
        /// <returns></returns>
        public static LocalizationUrlResult GetUrlResult(TagHelperContext context, string culture)
        {
            string controllerName = context.AllAttributes["asp-controller"].Value as string;
            string actionName     = context.AllAttributes["asp-action"].Value as string;

            var urlResult = LocalizationRouteDataHandler.GetUrl(controllerName, actionName, culture);

            Dictionary <string, string> routeValues = GetRouteValues(context.AllAttributes);

            if (routeValues != null)
            {
                urlResult.Url += LocalizationRouteDataHandler.GetOrderedParameters(controllerName, actionName, routeValues);
            }

            return(urlResult);
        }
コード例 #4
0
        /// <summary>
        /// Create the new list of action models for each localized route.
        /// </summary>
        /// <param name="controllerModel"></param>
        /// <param name="actionModel"></param>
        /// <param name="parameterTemplate"></param>
        /// <param name="sortedRouteParameters"></param>
        /// <returns></returns>
        public List <ActionModel> CreateLocalizedActionRoutes(ControllerModel controllerModel, ActionModel actionModel, string parameterTemplate, List <string> sortedRouteParameters)
        {
            string controllerName = controllerModel.ControllerName;
            string actionName     = actionModel.ActionName;
            var    actionLocalizationsAttributes = actionModel.Attributes.OfType <LocalizationRouteAttribute>().ToList();

            List <ActionModel> localizedActions = new List <ActionModel>();

            // For default actions we need to check if the [LocalizationRoute] Attribute exists or not.
            // This is so we can name the default action after the controller
            // For example otherwise HomeController for finnish Culture would be Home instead of Koti.
            if (actionName.Equals(LocalizationRouteDataHandler.DefaultAction, StringComparison.OrdinalIgnoreCase))
            {
                HashSet <string> cultures = LocalizationRouteDataHandler.SupportedCultures.Select(kvp => kvp.Key).ToHashSet();

                cultures.Remove(LocalizationRouteDataHandler.DefaultCulture);
                cultures.RemoveWhere(x => actionLocalizationsAttributes.FirstOrDefault(attr => attr.Culture == x) != null);

                // Iterate over all controllers that had a [LocalizationRoute]
                foreach (string culture in cultures)
                {
                    // The localized controller name is the link for the index action
                    string localizedControllerName = GetLocalizedControllerName(controllerModel, culture);
                    if (!localizedControllerName.Equals(controllerName, StringComparison.OrdinalIgnoreCase))
                    {
                        LocalizationRouteDataHandler.AddActionRouteData(controllerName, actionName, culture, "", localizedControllerName, sortedRouteParameters);
                    }
                }
            }

            foreach (LocalizationRouteAttribute attribute in actionLocalizationsAttributes)
            {
                string route = attribute.Route + parameterTemplate;
                // This copies all existing Attributes on the ActionModel,  [Route] [HttpGet] e.t.c.
                // Source file: https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.Core/ApplicationModels/ActionModel.cs
                ActionModel newLocalizedActionModel = new ActionModel(actionModel);

                // Clear the Selectors or it will have shared selector data from default route.
                // This however clears the ActionConstraints like [HttpGet] and [HttpPost]
                newLocalizedActionModel.Selectors.Clear();
                AttributeRouteModel newLocalizedAttributeRouteModel = new AttributeRouteModel();
                newLocalizedAttributeRouteModel.Template = route;
                // Add the new actionModel for adding to controller later
                localizedActions.Add(newLocalizedActionModel);

                AddAttributeRouteModel(newLocalizedActionModel.Selectors, newLocalizedAttributeRouteModel);
                // Bug mentioned by anonymous through a comment on blog.
                // This is where the [HttpGet], [HttpPost] constraints are added back after being cleared earlier.
                foreach (var actionConstraint in actionModel.Selectors.Where(x => x.ActionConstraints.Count > 0).SelectMany(x => x.ActionConstraints))
                {
                    newLocalizedActionModel.Selectors[0].ActionConstraints.Add(actionConstraint);
                }

                string linkName = attribute.Link;
                // If the action is default (Index) and there is no LinkName set
                // Then the linkName should be the controllers name
                if (actionName.Equals(LocalizationRouteDataHandler.DefaultAction, StringComparison.OrdinalIgnoreCase) && !String.IsNullOrEmpty(linkName))
                {
                    linkName = GetLocalizedControllerName(controllerModel, attribute.Culture);
                }

                // Add the localized route for the action
                // Example of final route:  "fi/koti" + "/" + "ota_yhteyttä"
                LocalizationRouteDataHandler.AddActionRouteData(controllerName, actionName, attribute.Culture, attribute.Route, linkName, sortedRouteParameters);
            }

            return(localizedActions);
        }
コード例 #5
0
        /// <summary>
        /// Adds the localized routes for a controller
        /// </summary>
        /// <param name="controllerModel"></param>
        public void AddActionRoutes(ControllerModel controllerModel)
        {
            string controllerName = controllerModel.ControllerName;
            // All the new localized actions to add to the controllerModel after all calculations.
            List <ActionModel> newActions = new List <ActionModel>();

            // Loop through all the actions to add their routes and also get the localized actions
            foreach (ActionModel action in controllerModel.Actions)
            {
                string actionName = action.ActionName;
                // If any parameters are needed such as /{index}
                string parameterTemplate = "";

                SelectorModel defaultSelectionModel = action.Selectors.FirstOrDefault(x => x.AttributeRouteModel != null);

                List <string> sortedRouteParameters = new List <string>();

                // If there is no [Route()] Attribute then create one for the route.
                if (defaultSelectionModel == null || defaultSelectionModel.AttributeRouteModel == null)
                {
                    AttributeRouteModel attributeRouteModel = new AttributeRouteModel();

                    if (action.Parameters.Count > 0)
                    {
                        foreach (ParameterModel parameter in action.Parameters)
                        {
                            sortedRouteParameters.Add(parameter.ParameterName.ToLower());
                            // TODO: ParseParameterTemplate? I think you can't skip the [Route] attribute if you want parameters.
                        }
                    }

                    if (!action.ActionName.Equals(LocalizationRouteDataHandler.DefaultAction, StringComparison.Ordinal))
                    {
                        attributeRouteModel.Template = actionName;
                        // Add the action name as it is eg: about will be about!
                        LocalizationRouteDataHandler.AddActionRouteData(controllerName, actionName, LocalizationRouteDataHandler.DefaultCulture, actionName, actionName, sortedRouteParameters);
                    }
                    else
                    {
                        // For DefaultAction we don't want to have a template.
                        // Because the default action is reachable with /Controller as the url.
                        attributeRouteModel.Template = "";
                        LocalizationRouteDataHandler.AddActionRouteData(controllerName, actionName, LocalizationRouteDataHandler.DefaultCulture, "", controllerName, sortedRouteParameters);
                    }

                    AddAttributeRouteModel(action.Selectors, attributeRouteModel);
                }
                // If a route already existed then check for parameter arguments to add to the cultural routes
                else
                {
                    string template = defaultSelectionModel.AttributeRouteModel.Template;

                    parameterTemplate = ParseParameterTemplate(template, sortedRouteParameters);

                    LocalizationRouteDataHandler.AddActionRouteData(controllerName, actionName, LocalizationRouteDataHandler.DefaultCulture, actionName, actionName, sortedRouteParameters);
                }

                var localizedActions = CreateLocalizedActionRoutes(controllerModel, action, parameterTemplate, sortedRouteParameters);
                newActions.AddRange(localizedActions);
            } // End foreach controllerModel.Actions

            // Now add all the new actions to the controller
            foreach (ActionModel action in newActions)
            {
                controllerModel.Actions.Add(action);
            }
        }