Understanding Resource files in MVC6 RC1 - localization

I've been trying to wrap my head around on how best to implement resource files for multiple languages in MVC6 but due to the changes with every release has me a bit confused on how to actually implement them properly. What is required and what are the constraints?
A few articles I've looked at:
https://damienbod.com/2015/10/21/asp-net-5-mvc-6-localization/
MVC 6 : how to use RESX files?
http://pratikvasani.github.io/archive/2015/12/25/MVC-6-localization-how-to/
I'm trying to set up resource files so that I have English and German available to my users, which would either be based on browser settings or a personal setting within their account.
What would be the best way of achieving this?
Thanks in advance!
Edit:
So as per the article, I've added the following code to Startup.cs:
services.AddLocalization(options =>
options.ResourcesPath = "Resources");
services.AddMvc()
.AddViewLocalization(Microsoft.AspNet.Mvc.Razor.LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();
var supportedCultures = new[]
{
new CultureInfo("de-DE"),
new CultureInfo("en-US")
};
//Set Default Localization Culture
app.UseRequestLocalization(new RequestLocalizationOptions
{
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures
}, new RequestCulture(new CultureInfo("en-US")));
Then within the Resources folder I created new resx files with file names:
"Views.Shared._LocalizationTest.en-US.resx"
"Views.Shared._LocalizationTest.de-DE.resx"
And my partial view looks like:
#using Microsoft.AspNet.Localization
#using Microsoft.AspNet.Mvc.Localization
#inject IViewLocalizer Localizer
<div>
#Localizer["TestString"]
</div>
I still seem to be missing something as I am getting "TestString" to show instead of "Test String" for English or "German: Test String" (as per my resource files).
Any ideas?

The ASP.NET core default approach is to NOT have your default language strings in a resource file, but just have them wrapped in code. So you could write the app using English strings wrapped in the localizer, and have one German resource file. See my article https://learn.microsoft.com/aspnet/core/fundamentals/localization

Related

ASP.NET Core 2: how to RedirectToPage with area?

RedirectToPage("Companies") will redirect to /Pages/Companies.cshtml (from an ASP.NET MVC controller)
But what if want redirect to this page /Areas/MyArea/Pages/Companies.cshtml ?
All those and many others don't work:
RedirectToPage("/MyArea/Companies.cshtml")
RedirectToPage("MyArea/Companies.cshtml")
RedirectToPage("./MyArea/Companies.cshtml")
RedirectToPage("/MyArea/Companies")
RedirectToPage("MyArea/Companies")
RedirectToPage("./MyArea/Companies")
Sometimes I get "Page not found" error. Sometimes get "Specify a root relative path with a leading '/' to generate a URL outside of a Razor Page". There are no Pages folder. I know all this can change all rules again.
P.S. Razor pages configred with plain .SetCompatibilityVersion(CompatibilityVersion.Version_2_1); no specific routing added.
Use the overload of RedirectToPage that takes an object representing RouteValues:
return RedirectToPage("/Companies", new { area = "MyArea" });
Note that the '/' is required if you use RedirectToPage in a controller (or anywhere outside of a Razor Page). Otherwise it is not required (but will still work).
This works for me:
return RedirectToPage("/Companies", new { area = "MyArea" });
Works under plain .SetCompatibilityVersion(CompatibilityVersion.Version_2_1); no specific routing configured.
I feel this will be a popular question... Thanks to Mike Bring, he show me a path.
P.S. If you have Pages folder - all rules will be changed once more. That is the way how "Razor Pages" try to run out from "MVC magic"

Another ASP to MVC migration > routes

Migrating our classic ASP site to ASP.Net 4.5 MVC. Our site is pretty large, hundreds of file, and SEO optimized. All URLs are SEO friendly, via web.config, eg.:
www.ourdomain.com/articles/2013/120/the-best-article
www.ourdomain.com/blog/2013/122/the-best-blog
www.ourdomain.com/video/2013/123/the-best-video
ie. www.ourdomain.com/{contenttype}/{year}/{id}/{url encoded title}
The ASP files to render are stored in a folder like /render/content.asp
We don't want to change any URLs in this migration. The new files of the MVC app will be in all new directories than the existing site. For example, a view: /MVC/content.vbhtml
How would you go about adding links in your Views, with ActionLink or other, to use the existing SEO friendly path instead of the default path, without hardcoding the path in the links in the view (adopt from currently URL, more or less). For example:
#Html.ActionLink("Edit", "Edit", New With {.id = currentItem.ID})
That creates an Edit link like : /MVC/Edit/120
But, what I would like is: /article/edit/120.
Any help appreciated.
Use
#Html.RouteLink("Edit", "myRouteName", New With { ... route params ... } );

Considerations when turning on RouteExistingFiles

I am looking to generate some CSS files dynamically in my Content folder.
At the moment, this folder has an ignore route (routes.IgnoreRoute("Content/{*wildcard}");) and, I'd like that to remain, as I don't need/want most of my content folders to go into the MVC request lifecycle.
Example:
routes.MapRoute(
"DynamicCSS",
"Content/Css/Dynamic/{guid}.css",
new { controller = "Site", action = "GenerateCSS" },
new { guid = #"^([0-9a-fA-F]){8}([0-9a-fA-F]){4}([0-9a-fA-F]){4}([0-9a-fA-F]){4}([0-9a-fA-F]){12}$" }
);
//If the file has already been generated, IIS should just return the file, saving a request in MVC.
routes.RouteExistingFiles = true; //was formerly false
//Ignore routes
routes.IgnoreRoute("Content/{*wildcard}");
I have a couple questions/concerns about this setup:
Will this work? Routes in ASP.NET MVC are lazy, but I don't know if the ignore routes are checked first. There's no documentation (I've Googled!) on this form of usage.
Are there any security implications to consider when switching on RouteExistingFiles? I don't want IIS to pick up any of my Model/Views folders by directly referencing them.
Many thanks for any suggestions.
Edit:
After further research, I have found an article on my first issue.
Scott Hanselman got a blog post "Plug-In Hybrids: ASP.NET WebForms and ASP.MVC and ASP.NET Dynamic Data Side By Side" in which he talked about his too. http://www.hanselman.com/blog/PlugInHybridsASPNETWebFormsAndASPMVCAndASPNETDynamicDataSideBySide.aspx
Hope this helps,
Ray.

I'm getting a "Does not implement IController" error on images and robots.txt in MVC2

I'm getting a strange error on my webserver for seemingly every file but the .aspx files.
Here is an example. Just replace '/robots.txt' with any .jpg name or .gif or whatever and you'll get the idea:
The controller for path '/robots.txt'
was not found or does not implement
IController.
I'm sure it's something to do with how I've setup routing but I'm not sure what exactly I need to do about it.
Also, this is a mixed MVC and WebForms site, if that makes a difference.
You can ignore robots.txt and all the aspx pages in your routing.
routes.IgnoreRoute("{*allaspx}", new {allaspx=#".*\.aspx(/.*)?"});
routes.IgnoreRoute("{*robotstxt}", new {robotstxt=#"(.*/)?robots.txt(/.*)?"});
You might want to ignore the favicon too.
routes.IgnoreRoute("{*favicon}", new {favicon=#"(.*/)?favicon.ico(/.*)?"});
You can adjust the regular expression to exclude paths.
Haacked from the source.
The ignore route given above didn't work for me but I found a similar one that did:
routes.IgnoreRoute("{*staticfile}", new { staticfile = #".*\.(css|js|gif|jpg)(/.*)?" });
This error could also happen if inside a view in your area, you use the Html.Action helper. This helper will always use the area as a prepend, unless you specifically tell it not to. E.g.,
#Html.Action("Main", "Navigation", new { area = string.Empty })
I found another solution too... While I don't think I'll use it, it's worth showing here in the answers:
The following should (in theory) ignore looking for controllers for anything with a '.' in it.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" }, // Parameter defaults
new { controller = #"[^\.]*" } // Parameter contraints.
);
Do you still have:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
... in your Global.asax.cs?
MVC puts it there by default, and it's supposed to handle this.
If you do, then the problem may be how you're mixing MVC and WebForms.
I encountered this error when I request resources that did not exist.
Specifically, I was requesting a custom IE css file:
<!--[if lt IE 8]>#Styles.Render("~/Content/ie7.css")<![endif]-->
(These are condition comments, interpreted by IE)
However, the actual resource existed on ~/Content/ie/ie7.css.
So, without any modifications to the routing, the error was solved by using the correct url of the resource.

ASP.NET MVC localization

I'd like to use resource file (.resx) to do localization in ASP.NET MVC. My thought is:
Make a default resource file under App_GlobalResources folder
Make several local resource files under App_LocalResources folder
read cookie info to set CultureInFo
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
then, I'd like to use resource file in controller to set ViewData value, something like:
ViewData["Title"] = Resources:Resource, PageTitle;
but the syntax is wrong, how can I do this?
Any idea?
Did you tried following?
ViewData["Title"] = Resources.Resource.PageTitle;
If you have Resource.aspx file in your App_GlobalResources this should work.

Resources