Skip to content
This repository was archived by the owner on Nov 29, 2018. It is now read-only.

Get segment from mapped route for CustomRequestCultureProvider #122

Closed
Codenator81 opened this issue Oct 20, 2015 · 29 comments
Closed

Get segment from mapped route for CustomRequestCultureProvider #122

Codenator81 opened this issue Oct 20, 2015 · 29 comments

Comments

@Codenator81
Copy link

I tested after

app.UseMvc(routes =>

in startup class app.UseRequestLocalization not work.
For example user want culture segment been in:

routes.MapRoute(
                    name: "transRoute",
                    template: "{controller=Home}/{culture=en-US}/{action=Index}/{id?}");

So how I can get {culture} segment to find route match?

This is all way not processed:

options.RequestCultureProviders.Insert(0, new CustomRequestCultureProvider(async context =>
            {
                var routeContext = new RouteContext(context); // IsHandled all ways false

Thanks Alex

@BenjiZombie
Copy link

What I did was create a RouteRequestCultureProvider instead.

namespace Microsoft.AspNet.Localization
{
    /// <summary>
    /// Determines the culture information for a request via values in the route.
    /// </summary>
    public class RouteRequestCultureProvider : RequestCultureProvider
    {
        #region Overrides of RequestCultureProvider

        public override Task<RequestCulture> DetermineRequestCulture(HttpContext httpContext)
        {
            if (httpContext == null)
            {
                throw new ArgumentNullException(nameof(httpContext));
            }

            var request = httpContext.Request;
            if (!request.Path.HasValue)
            {
                return Task.FromResult((RequestCulture) null);
            }

            var cultureValue = Regex.Match(
                request.Path.Value,
                @"^/([a-z]{2})",
                RegexOptions.IgnoreCase);

            if (cultureValue.Success)
            {
                var culture = CultureInfoCache.GetCultureInfo(cultureValue.Groups[1].Value);
                var uiCulture = CultureInfoCache.GetCultureInfo(cultureValue.Groups[1].Value);

                if (culture == null || uiCulture == null)
                {
                    return Task.FromResult((RequestCulture) null);
                }

                var requestCulture = new RequestCulture(culture, uiCulture);
                requestCulture = ValidateRequestCulture(requestCulture);

                return Task.FromResult(requestCulture);
            }

            return Task.FromResult((RequestCulture) null);
        }

        #endregion
    }
}

Then simply register it in the Configure method:

// Add localization to the request pipeline.
var requestLocalizationOptions = new RequestLocalizationOptions
{
    SupportedCultures = new List<CultureInfo>
    {
        new CultureInfo("en"),
        new CultureInfo("fr"),
        new CultureInfo("es")
    },
    SupportedUICultures = new List<CultureInfo>
    {
        new CultureInfo("en"),
        new CultureInfo("fr"),
        new CultureInfo("es")
    }
};
requestLocalizationOptions.RequestCultureProviders.Insert(2, new RouteRequestCultureProvider
{
    Options = requestLocalizationOptions
});
app.UseRequestLocalization(requestLocalizationOptions);

My route mapping is different from yours, but you can easily modify the code to fit your needs

// Add MVC to the request pipeline.
app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{culture?}/{controller}/{action}/{id?}",
        defaults: new { culture = "en", controller = "Home", action = "Index" });
});

@Codenator81
Copy link
Author

@BenjiZombie thanks for good example.
I do similar in my code https://github.com/WeebDo/WeebDo.CMF/blob/master/src/WeebDoCMF/Startup.cs#L190
I think there no way to get segment {culture} from route for now before

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{culture?}/{controller}/{action}/{id?}",
        defaults: new { culture = "en", controller = "Home", action = "Index" });
});

@hishamco
Copy link
Contributor

@Codenator81
Copy link
Author

@hishamco Thanks I implement my code based on your links 👍
Here question more about how get culture as I do in MVC 5 from Controller

RouteData.Values["culture"] as string;

@hishamco
Copy link
Contributor

@Codenator81
Copy link
Author

@hishamco
Copy link
Contributor

What is the value of ViewBag.Trans when you print it out, because I don't know what is the issue in your sample

@Codenator81
Copy link
Author

@hishamco There everything work great. My issue is how get route segment from route template before UseMVC middleware. But I think it is not possible. I will try different approach.

@hishamco
Copy link
Contributor

Why you need it before MVC middleware?!! if that's the case i will try to look in your sample

@Codenator81
Copy link
Author

@hishamco You are right 👍
I will write own middleware which going to work after UseMVC and set needed culture thread

@hishamco
Copy link
Contributor

All the best @Codenator81 , be free to ask if you have an issue again

@danroth27
Copy link
Member

@kirthik @DamianEdwards We should look at what our guidance is for using path segments for determining the culture and maybe provide a sample on how to do it.

@hishamco
Copy link
Contributor

@danroth27 i provide a simple unit test in https://github.com/aspnet/Localization/blob/dev/test/Microsoft.AspNet.Localization.Tests/CustomRequestCultureProviderTest.cs#L46, also I already suggest #43, if this will help i will make a PR for that

@Codenator81
Copy link
Author

Middlewares don`t work after UseMVC middleware

@hishamco
Copy link
Contributor

@Codenator81 if what you are looking for is in culture segment in "{controller=Home}/{culture=en-US}/{action=Index}/{id?}", I will try to look to into your sample or i will write a code snippet to display the culture segment

@Codenator81
Copy link
Author

@hishamco Yes I looking for that.

@damienbod
Copy link

I think this should be an extra default Provider like the others as this is a common use case. What do you think?

Greetings Damien

@hishamco
Copy link
Contributor

Ok @Codenator81 I will dig into that
@damienbod as I said before, I already suggest that in #43

@hishamco
Copy link
Contributor

@Codenator81 for saving time do you have a repo with the latest changes that you did?

@damienbod
Copy link

@hishamco

Thanks for your answer, your PR sounds great, I was thinking more of a MVC 6 extension which would allow me to define my culture in the MVC attribute routing.

Greetings Damien

@hishamco
Copy link
Contributor

@damienbod IMHO while there's RequestCultureProvider is out-of-the-box it will be nice to be provider than extension

@hishamco
Copy link
Contributor

@Codenator81 have you look to this sample https://github.com/aspnet/Mvc/tree/9342cb0ab78add8c527edcbc4c0988edc96f01e3/test/WebSites/LocalizationWebSite if you didn't get your answer, I will add a sample demo for that

@Codenator81
Copy link
Author

@hishamco I see that example long time ago. For now it is outdated? For example app.UseCultureReplacer(); I don`t find (may be removed from code)?
I think there is good example for starters or people who moving from < MVC5.

As I wrote one comment before I looking for segment in Controller. Same people do simelar approach in filter. But for now it is not possible get segment from middleware. I think it is routing feature or issue.
Not Localization.

@hishamco
Copy link
Contributor

I see, but as I mentioned before issue #54 and https://github.com/aspnet/Localization/blob/dev/test/Microsoft.AspNet.Localization.Tests/CustomRequestCultureProviderTest.cs#L57 do such thing without using routes, I used segments instead, probably the idea is same. I'm not sure such sample should be in localization repo or mvc?!!
/cc @Eilon

@Codenator81
Copy link
Author

@hishamco I see all that examples. All of them great 👍 My issue different.
I wrote before:

routes.MapRoute(
         name: "transRoute",
         template: "{controller=Home}/{culture=en-US}/{action=Index}/{id?}");

So I wont detect culture segment if it is at end route or at middle without rewrite code and just get that segment as I do in code there:

string cultureFromRoute = RouteData.Values["culture"] as string;

but segments can be detected only after routes initilized. So there no way get segment in middleware. Hope I explain my issue?

@hishamco
Copy link
Contributor

Could you please add a repo summarize your scenario without any other stuff (MiniMVC), i already saw WeebDoCMF but I don't wanna miss on any other stuff 😄

@Codenator81
Copy link
Author

Ok I will do it. May be today evening.

@Eilon Eilon added this to the Backlog milestone Dec 2, 2015
@hishamco
Copy link
Contributor

It's in the way @Codenator81 😄
53a8fa6

@Eilon Eilon modified the milestones: 1.1.0, Backlog Aug 20, 2016
kichalla added a commit that referenced this issue Sep 24, 2016
…nformation.

[Fixes #122] Get segment from mapped route for CustomRequestCultureProvider
kichalla added a commit that referenced this issue Sep 25, 2016
…nformation.

[Fixes #122] Get segment from mapped route for CustomRequestCultureProvider
kichalla added a commit that referenced this issue Sep 25, 2016
…nformation.

[Fixes #122] Get segment from mapped route for CustomRequestCultureProvider
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants