Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Michalis Koukoumakis 5 posts 95 karma points
    Aug 13, 2023 @ 08:41
    Michalis Koukoumakis
    0

    How to get Current Published Content in Middleware.

    Hello everybody,

    When a user get in the a page I get the first culture of the browser and then what I want is to redirect the specific page to culture of browser. So, I use the following middleware to do this.

    private readonly IUmbracoContextFactory _umbracoContextFactory;
    private readonly IVariationContextAccessor _variationContextAccessor;
    private readonly IDomainService _domainService;
    private readonly RequestDelegate _next;
    private readonly ILocalizationService _localizationService;
    private readonly IUmbracoContextAccessor _umbracoContextAccessor;
    
    public SetUserLanguageOnStartupMiddleware(IUmbracoContextFactory umbracoContextFactory, IVariationContextAccessor variationContextAccessor, IDomainService domainService, RequestDelegate next,
        ILocalizationService localizationService, IUmbracoContextAccessor umbracoContextAccessor)
    {
        _umbracoContextFactory = umbracoContextFactory;
        _variationContextAccessor = variationContextAccessor;
        _domainService = domainService;
        _next = next;
        _localizationService = localizationService;
        _umbracoContextAccessor = umbracoContextAccessor;
    }
    
    public async Task InvokeAsync(HttpContext context)
    {
            //Browser Cultures
            string[] browserLanguages = request.GetTypedHeaders()
                           .AcceptLanguage
                           ?.OrderByDescending(x => x.Quality ?? 1) // Quality defines priority from 0 to 1, where 1 is the highest.
                           .Select(x => x.Value.ToString())
                           .ToArray() ?? Array.Empty<string>();
    
            //Culture to use
            //ILanguage UmbracoLanguageToUse = GetUmbracoLanguageToUse(browserLanguages);
            ILanguage UmbracoLanguageToUse = _localizationService.GetLanguageById(2);
    
            if (UmbracoLanguageToUse.CultureInfo.Name != CultureInfo.CurrentCulture.Name)
            {
                //_variationContextAccessor.VariationContext ??= new VariationContext(UmbracoLanguageToUse.CultureInfo.Name);
                //var umbracoContextReference = _umbracoContextFactory.EnsureUmbracoContext();
    
                IPublishedContent CurrentPage = _umbracoContextAccessor?.GetRequiredUmbracoContext()?.PublishedRequest?.PublishedContent;
                if (CurrentPage != null)
                {
                    string LanguageUrl = CurrentPage.Url(UmbracoLanguageToUse.CultureInfo.Name, mode: UrlMode.Default);
                    context.Response.Redirect(LanguageUrl);
                }
            }
    
        await _next(context);
    }
    

    but the Current Page is always null.

    Can you suggest me a way to get the PublishedContent so I will be able to find the url of different culture? Or, is there another way to get all urls by language of the current page?

    Thanks a lot

  • Huw Reddick 1929 posts 6697 karma points MVP 2x c-trib
    Aug 14, 2023 @ 11:50
    Huw Reddick
    0

    I think you need to do this

    using (var cref = _umbracoContextFactory.EnsureUmbracoContext())
                {
     //Do stuff   
                }   
    
  • Michalis Koukoumakis 5 posts 95 karma points
    Aug 17, 2023 @ 14:45
    Michalis Koukoumakis
    0

    Hi Huw. Thanks a lot for your reply.

    I try to find the IPublishedContent by the Url Address

    so I try this:

    string UrlAddress = context.Request.Path.Value.ToLower();
    _variationContextAccessor.VariationContext ??= new VariationContext(CultureInfo.CurrentCulture.Name);
    var umbracoContextReference = _umbracoContextFactory.EnsureUmbracoContext();
    IUmbracoContext umbracoContext = umbracoContextReference.UmbracoContext;
    IPublishedContent homePage = umbracoContext.Content.GetAtRoot().FirstOrDefault() as HomePage;
    foreach (var item in homePage.Children)
    {
    
    }
    

    which helps, but not in all cases.

    So, I try to find the IPublishedContent by urlAlias (variable UrlAddress)

    Any suggestion of how to achieve this?

  • Huw Reddick 1929 posts 6697 karma points MVP 2x c-trib
    Aug 17, 2023 @ 15:06
    Huw Reddick
    0

    you should be able to use

    umbracoContext.Content.GetByRoute(url);
    

    where url = "/some-page/sub-page/"

  • Michalis Koukoumakis 5 posts 95 karma points
    Aug 18, 2023 @ 08:45
    Michalis Koukoumakis
    0

    You are right. Because my site is multilanguage I used the url = "/el/some-page/" instead of url = "/some-page/"

  • Michalis Koukoumakis 5 posts 95 karma points
    Aug 18, 2023 @ 08:51
    Michalis Koukoumakis
    100

    In case, someone want to use this approach the code is:

    The middleware class:

    public class SetUserLanguageOnStartupMiddleware {

    private readonly IUmbracoContextFactory _umbracoContextFactory;
    private readonly IVariationContextAccessor _variationContextAccessor;
    private readonly IDomainService _domainService;
    private readonly RequestDelegate _next;
    private readonly ILocalizationService _localizationService;
    
    public SetUserLanguageOnStartupMiddleware(IUmbracoContextFactory umbracoContextFactory, IVariationContextAccessor variationContextAccessor, IDomainService domainService, RequestDelegate next,
        ILocalizationService localizationService)
    {
        _umbracoContextFactory = umbracoContextFactory;
        _variationContextAccessor = variationContextAccessor;
        _domainService = domainService;
        _next = next;
        _localizationService = localizationService;
    }
    
    public async Task InvokeAsync(HttpContext context)
    {
        //Cookie wchich inform us if user's language has been checked
        string cookieValue = context.Request.Cookies[PublicConstants.CookieCultureExamined];
    
        if (string.IsNullOrWhiteSpace(cookieValue))
        {
            ArgumentNullException.ThrowIfNull(context);
    
            HttpRequest request = context.Request;
            string UrlAddress = request.Path.Value.ToLower();
    
            //Get the Current Culture. We are using Domains, because CultureInfo.CurrentCulture.Name is always the Default Language of RequestLocalizationOptions
            string CurrentCultureName = CultureInfo.CurrentCulture.Name;
            IEnumerable<IDomain> Domains = _domainService.GetAll(true);
            foreach (IDomain Domain in Domains)
            {
                if (UrlAddress.StartsWith(Domain.DomainName + "/") && Domain.DomainName != "/")
                {
                    CurrentCultureName = Domain.LanguageIsoCode;
                    //Domain Name (Language) must be removed from UrlAddress, otherwise GetByRoute is not working
                    UrlAddress = UrlAddress.ReplaceFirst(Domain.DomainName + "/", "/");
                    break;
                }
            }
    
            //Prefered language of user
            ILanguage UmbracoLanguageToUse = GetUmbracoLanguageToUse(request);
    
            //Inform cookie that user's language has been checked
            CookieOptions cookieOptions = new() { Expires = DateTime.Now.AddDays(1) };
            context.Response.Cookies.Append(PublicConstants.CookieCultureExamined, "yes", cookieOptions);
    
            //In case, where prefered culture of user is different than current culture
            if (UmbracoLanguageToUse.CultureInfo.Name != CurrentCultureName)
            {
                 _variationContextAccessor.VariationContext ??= new VariationContext(CurrentCultureName);
                var umbracoContextReference = _umbracoContextFactory.EnsureUmbracoContext();
                IUmbracoContext umbracoContext = umbracoContextReference.UmbracoContext;
                IPublishedContent CurrentPage = umbracoContext?.Content.GetByRoute(UrlAddress);
                //IPublishedContent CurrentPageB = umbracoContext?.Content.GetByRoute(UrlAddress, culture: CurrentCultureName.ToLower());
    
                if(CurrentPage != null)
                {
                    string UriByLanguage = GetUriOfPublishedContent(CurrentPage, UmbracoLanguageToUse);
                    if (!string.IsNullOrEmpty(UriByLanguage))
                        context.Response.Redirect(UriByLanguage);
                }
            }
        }
    
        await _next(context);
    }
    
    /// <summary>
    /// Get Language (UmbracoLanguages) that user prefers
    /// </summary>
    private ILanguage GetUmbracoLanguageToUse(HttpRequest request)
    {
        //Get browser's cultures
        string[] browserLanguages = request.GetTypedHeaders()
                       .AcceptLanguage
                       ?.OrderByDescending(x => x.Quality ?? 1) // Quality defines priority from 0 to 1, where 1 is the highest.
                       .Select(x => x.Value.ToString())
                       .ToArray() ?? Array.Empty<string>();
    
        IEnumerable<ILanguage> UmbracoLanguages = _localizationService.GetAllLanguages();
    
        if (UmbracoLanguages != null && browserLanguages != null)
        {
            //Check if any culture that application uses exists in browser's cultures
            foreach (string browserLanguage in browserLanguages)
            {
                foreach (ILanguage UmbracoLanguage in UmbracoLanguages)
                {
                    if (UmbracoLanguage.CultureInfo.Name.ToLower() == browserLanguage.ToLower())
                        return UmbracoLanguage;
                    else if (!string.IsNullOrEmpty(UmbracoLanguage.CultureInfo.Parent.Name) && UmbracoLanguage.CultureInfo.Parent.Name.ToLower() == browserLanguage.ToLower())
                        return UmbracoLanguage;
                }
            }
        }
    
        return null;
    }
    
    /// <summary>
    /// Get Uri of Page by Language
    /// </summary>
    /// <param name="publishedContent">PublishedContent of page</param>
    /// <param name="UmbracoLanguage">Language to search</param>
    private string GetUriOfPublishedContent(IPublishedContent publishedContent, ILanguage UmbracoLanguage)
    {
        string res = string.Empty;
    
        string LanguageUri = publishedContent.Url(UmbracoLanguage.CultureInfo.Name, mode: UrlMode.Default);
        if (LanguageUri.StartsWith("/"))
            res = LanguageUri;
        else
        {
            string FallbackUri = string.Empty;
            if (UmbracoLanguage.FallbackLanguageId != null)
            {
                ILanguage FallbackLanguage = _localizationService.GetLanguageById(UmbracoLanguage.FallbackLanguageId.Value);
                FallbackUri = publishedContent.Url(FallbackLanguage.CultureInfo.Name, mode: UrlMode.Default);
            }
            if (FallbackUri.StartsWith("/"))
                res = FallbackUri;
            else
            {
                string DefaultUri = string.Empty;
                int? DefaultLanguageId = _localizationService.GetDefaultLanguageId();
                if (DefaultLanguageId != null)
                {
                    ILanguage DefaulLanguage = _localizationService.GetLanguageById(DefaultLanguageId.Value);
                    DefaultUri = publishedContent.Url(DefaulLanguage.CultureInfo.Name, mode: UrlMode.Default);
                    if (DefaultUri.StartsWith("/"))
                        res = DefaultUri;
                }
            }
        }
    
        return res;
    }
    

    }

    Extension for IApplication:

    public static class IApplicationExtensions
    {
        public static IApplicationBuilder SetUserLanguageOnStartup(this IApplicationBuilder app)
        {
            return app.UseMiddleware<SetUserLanguageOnStartupMiddleware>();
        }
    }
    

    and in Startup.cs

    app.SetUserLanguageOnStartup();
    

    before app.UseUmbraco()

Please Sign in or register to post replies

Write your reply to:

Draft