Skip to content
This repository has been archived by the owner on Feb 23, 2021. It is now read-only.

Commit

Permalink
Add a sample demonstrating culture based selection for Razor Pages
Browse files Browse the repository at this point in the history
  • Loading branch information
pranavkm committed Aug 3, 2018
1 parent 2fcbabe commit 7a53120
Show file tree
Hide file tree
Showing 9 changed files with 213 additions and 1 deletion.
17 changes: 16 additions & 1 deletion Entropy.sln
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.12
MinimumVisualStudioVersion = 10.0.40219.1
Expand Down Expand Up @@ -131,6 +131,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mvc.CustomRazorPageHandlers
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mvc.RazorPagePartial", "samples\Mvc.RazorPagePartial\Mvc.RazorPagePartial.csproj", "{D98E6BE8-F1A8-47E7-BC34-017825DCF24E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mvc.LocalizedRazorPages", "samples\Mvc.LocalizedRazorPages\Mvc.LocalizedRazorPages.csproj", "{507E3F7C-DB1A-4674-B542-BA33BAD419D8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -729,6 +731,18 @@ Global
{D98E6BE8-F1A8-47E7-BC34-017825DCF24E}.Release|x64.Build.0 = Release|Any CPU
{D98E6BE8-F1A8-47E7-BC34-017825DCF24E}.Release|x86.ActiveCfg = Release|Any CPU
{D98E6BE8-F1A8-47E7-BC34-017825DCF24E}.Release|x86.Build.0 = Release|Any CPU
{507E3F7C-DB1A-4674-B542-BA33BAD419D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{507E3F7C-DB1A-4674-B542-BA33BAD419D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{507E3F7C-DB1A-4674-B542-BA33BAD419D8}.Debug|x64.ActiveCfg = Debug|Any CPU
{507E3F7C-DB1A-4674-B542-BA33BAD419D8}.Debug|x64.Build.0 = Debug|Any CPU
{507E3F7C-DB1A-4674-B542-BA33BAD419D8}.Debug|x86.ActiveCfg = Debug|Any CPU
{507E3F7C-DB1A-4674-B542-BA33BAD419D8}.Debug|x86.Build.0 = Debug|Any CPU
{507E3F7C-DB1A-4674-B542-BA33BAD419D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{507E3F7C-DB1A-4674-B542-BA33BAD419D8}.Release|Any CPU.Build.0 = Release|Any CPU
{507E3F7C-DB1A-4674-B542-BA33BAD419D8}.Release|x64.ActiveCfg = Release|Any CPU
{507E3F7C-DB1A-4674-B542-BA33BAD419D8}.Release|x64.Build.0 = Release|Any CPU
{507E3F7C-DB1A-4674-B542-BA33BAD419D8}.Release|x86.ActiveCfg = Release|Any CPU
{507E3F7C-DB1A-4674-B542-BA33BAD419D8}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -794,6 +808,7 @@ Global
{8A61FA46-3FD4-42BE-80C6-E5931387590C} = {5BCA2B8A-37DA-4A88-A221-3D5B4796B07F}
{C673D327-412E-45E6-A12F-A8D37551793F} = {8B204FB8-31A6-4559-AE7F-0412F504983C}
{D98E6BE8-F1A8-47E7-BC34-017825DCF24E} = {5BCA2B8A-37DA-4A88-A221-3D5B4796B07F}
{507E3F7C-DB1A-4674-B542-BA33BAD419D8} = {8B204FB8-31A6-4559-AE7F-0412F504983C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5DF584CA-249D-432C-BBA9-4498414C8E97}
Expand Down
11 changes: 11 additions & 0 deletions samples/Mvc.LocalizedRazorPages/Mvc.LocalizedRazorPages.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

</Project>
73 changes: 73 additions & 0 deletions samples/Mvc.LocalizedRazorPages/PageCultureConvention.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using System;
using System.Diagnostics;
using System.Globalization;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc.ActionConstraints;
using Microsoft.AspNetCore.Mvc.ApplicationModels;

namespace LocalizedRazorPages
{
public class PageCultureConvention : IPageRouteModelConvention
{
public void Apply(PageRouteModel model)
{
var path = model.ViewEnginePath;
var lastSeparator = path.LastIndexOf('/');
Debug.Assert(lastSeparator != -1);
var lastDot = path.LastIndexOf('.', path.Length - 1, path.Length - lastSeparator);

// /SomeFolder/MyPage.fr-FR -> fr-FR
if (lastDot != -1)
{
var cultureName = path.Substring(lastDot + 1);
var constraint = new CultureConstraint(new CultureInfo(cultureName));
for (var i = model.Selectors.Count - 1; i >= 0; i--)
{
var selector = model.Selectors[i];

selector.ActionConstraints.Add(constraint);
var template = selector.AttributeRouteModel.Template;
template = template.Substring(0, lastDot - 1);

selector.AttributeRouteModel.Template = template;
var fileName = template.Substring(lastSeparator);

if (fileName == "Index")
{
selector.AttributeRouteModel.SuppressLinkGeneration = true;

var indexSelector = new SelectorModel(selector);

template = selector.AttributeRouteModel.Template.Substring(0, lastSeparator);
indexSelector.AttributeRouteModel.Template = template;
model.Selectors.Add(indexSelector);
}
}
}
}

private class CultureConstraint : IActionConstraint
{
private readonly CultureInfo _culture;

public CultureConstraint(CultureInfo culture)
{
_culture = culture;
}

public int Order => 0;

public bool Accept(ActionConstraintContext context)
{
var feature = context.RouteContext.HttpContext.Features.Get<IRequestCultureFeature>();
if (feature == null)
{
// The page is associated with a culture but the request is not.
return false;
}

return string.Equals(feature.RequestCulture.Culture.Name, _culture.Name, StringComparison.OrdinalIgnoreCase);
}
}
}
}
4 changes: 4 additions & 0 deletions samples/Mvc.LocalizedRazorPages/Pages/Index.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@page
@model IndexModel

Neutral culture
17 changes: 17 additions & 0 deletions samples/Mvc.LocalizedRazorPages/Pages/Index.cshtml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace LocalizedRazorPages.Pages
{
public class IndexModel : PageModel
{
public void OnGet()
{

}
}
}
4 changes: 4 additions & 0 deletions samples/Mvc.LocalizedRazorPages/Pages/Index.fr-FR.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@page
@model IndexModel

French culture
3 changes: 3 additions & 0 deletions samples/Mvc.LocalizedRazorPages/Pages/_ViewImports.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@using LocalizedRazorPages
@namespace LocalizedRazorPages.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
24 changes: 24 additions & 0 deletions samples/Mvc.LocalizedRazorPages/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace LocalizedRazorPages
{
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}
61 changes: 61 additions & 0 deletions samples/Mvc.LocalizedRazorPages/Startup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace LocalizedRazorPages
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddRazorPagesOptions(options =>
{
options.Conventions.Add(new PageCultureConvention());
});
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseRequestLocalization(options =>
{
var supportedCultures = new[] { "en-US", "fr-FR" };
options.AddSupportedCultures(supportedCultures);
options.AddSupportedUICultures(supportedCultures);
});

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();

app.UseMvc();
}
}
}

3 comments on commit 7a53120

@hishamco
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pranavkm how this different from using RouteRequestCultureProvider?

@pranavkm
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's attempting to select a Razor page path based on the request culture. Not entirely sure how it's similar to the culture provider

@hishamco
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing RouteRequestCultureProvider attempting to select a proper view based on the culture provided by route

Please sign in to comment.