Sto tentando di ignorare la cultura della richiesta corrente. L'ho fatto funzionare in parte usando un custom ActionFilterAttribute
.Sovrascrivere facoltativamente la cultura della richiesta tramite url/route in un'applicazione ASP.NET Core 1.0
public sealed class LanguageActionFilter : ActionFilterAttribute
{
private readonly ILogger logger;
private readonly IOptions<RequestLocalizationOptions> localizationOptions;
public LanguageActionFilter(ILoggerFactory loggerFactory, IOptions<RequestLocalizationOptions> options)
{
if (loggerFactory == null)
throw new ArgumentNullException(nameof(loggerFactory));
if (options == null)
throw new ArgumentNullException(nameof(options));
logger = loggerFactory.CreateLogger(nameof(LanguageActionFilter));
localizationOptions = options;
}
public override void OnActionExecuting(ActionExecutingContext context)
{
string culture = context.RouteData.Values["culture"]?.ToString();
if (!string.IsNullOrWhiteSpace(culture))
{
logger.LogInformation($"Setting the culture from the URL: {culture}");
#if DNX46
System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo(culture);
System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture);
#else
CultureInfo.CurrentCulture = new CultureInfo(culture);
CultureInfo.CurrentUICulture = new CultureInfo(culture);
#endif
}
base.OnActionExecuting(context);
}
}
Sul controller Io uso il LanguageActionFilter
.
[ServiceFilter(typeof(LanguageActionFilter))]
[Route("api/{culture}/[controller]")]
public class ProductsController : Controller
{
...
}
Questo funziona fino ad ora, ma ho due problemi con esso:
- che non mi piacciono dover dichiarare
{culture}
in ogni controller, come ho intenzione di bisogno su ogni percorso. - Avendo una cultura predefinita non funziona con questo approccio, anche se lo dichiaro come
[Route("api/{culture=en-US}/[controller]")]
per ovvi motivi.
L'impostazione di un risultato di instradamento predefinito non funziona nessuno.
app.UseMvc(routes =>
{
routes.MapRoute(
name: "DefaultRoute",
template: "api/{culture=en-US}/{controller}"
);
});
Ho anche studiato in un'implementazione personalizzata IRequestCultureProvider
e aggiungerlo al metodo UseRequestLocalization
come
app.UseRequestLocalization(new RequestLocalizationOptions
{
RequestCultureProviders = new List<IRequestCultureProvider>
{
new UrlCultureProvider()
},
SupportedCultures = new List<CultureInfo>
{
new CultureInfo("de-de"),
new CultureInfo("en-us"),
new CultureInfo("en-gb")
},
SupportedUICultures = new List<CultureInfo>
{
new CultureInfo("de-de"),
new CultureInfo("en-us"),
new CultureInfo("en-gb")
}
}, new RequestCulture("en-US"));
ma poi non ho accesso alle vie di lì (suppongo causano i percorsi sono fatti più tardi nella pipeline). Ovviamente potrei anche provare ad analizzare l'url richiesto. E non so nemmeno se potrei cambiare il percorso in questo posto in modo che corrisponda al percorso sopra con la cultura in esso.
Il passaggio della coltura tramite parametro di query o la modifica dell'ordine dei parametri all'interno del percorso non è un'opzione.
Entrambi gli URL api/en-us/products
come noi come api/products
devono essere indirizzati allo stesso controller, in cui i primi non cambiano la cultura.
L'ordine in cui la coltura viene determinato deve essere
- Se definito URL, portarlo
- Se non definito in URL, controllare stringa di query e utilizzare tale
- Se non definito interrogare, controllare i cookie
- Se non definito nel cookie, utilizzare l'intestazione
Accept-Language
.
2-4 viene effettuato tramite UseRequestLocalization
e ciò funziona. Inoltre, non mi piace l'approccio attuale che deve aggiungere due attributi a ciascun controller ({culture}
in route e allo [ServiceFilter(typeof(LanguageActionFilter))]
).
Edit: Mi piace anche a limitare il numero delle zone valide a quello impostato in SupportedCultures
proprietà della RequestLocalizationOptions
passato al UseRequestLocalization
.
IOptions<RequestLocalizationOptions> localizationOptions
nel LanguageActionFilter
sopra non funziona in quanto restituisce una nuova istanza di RequestLocalizationOptions
dove SupportedCultures
è sempre null
e non quello passato al.
FWIW è un progetto WebApi RESTful.
Quindi, per quanto ho capito dalla tua domanda, stai cercando di far funzionare quel percorso di URL, sì? Che dire se definisci due percorsi? Uno con '{culture}' e uno senza di esso? – Dealdiane
Non solo, mi piacerebbe evitare di usare 'LanguageActionFilter' per diversi motivi, uno è che devo ripeterlo su ogni controller e l'altro è che non ho accesso a' RequestLocalizationOptions'. Come si può vedere nell'esempio, ho provato a iniettarlo, ma ottengo sempre la versione predefinita 'RequestLocalizationOptions' con' SupportedCultures' come null, non quella che è stata passata al middleware di localizzazione della richiesta – Tseng
Aggiunta di 'api/{controller}' e 'api/{culture = en-US}/{controller}' dentro 'app.UseMvc (routes => ...)' non funziona – Tseng