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 96 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 1932 posts 6722 karma points MVP 3x 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 96 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 1932 posts 6722 karma points MVP 3x 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 96 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 96 karma points
    Aug 18, 2023 @ 08:51
    Michalis Koukoumakis
    101

    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()

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies