ASP.NET MVC4 Multi-lingual Data Annotations - c#

In a standard application I have the following:
[Required]
[DisplayName("Email Address")]
public string EmailAddress { get; set; }
...this in turn generates a label for this form field automatically in English.
Now, if I need my app to support 5 languages, what is the best approach from a ASP.NET MVC application to handle this?
Scope of application is about 400 - 600 data fields.
UPDATE: I will also require support for updating small sections of text in the application like page names and introductions to each form (small paragraph).

Instead of assigning the actual values to the attribute properties, assign keys for resource strings. Then, you can use a custom ModelMetadataProvider that is aware of the localization context and will provide the appropriate string. To get a better solution, you can make your custom ModelMetadataProvider infer conventions, (which cuts down on the need for verbose attributes).
Phil Haack has a blog article called Model Metadata and Validation Localization using Conventions that explains how this works. There is also a corresponding NuGet package called ModelMetadataExtensions with source code available on github at https://github.com/Haacked/mvc-metadata-conventions .
As a side note, I'd recommend reviewing some of the awesome answers I got on an old question of mine: Effective Strategies for Localization in .NET. They don't specifically address your question, but will be very helpful if you are working on a multilingual .NET app.

I would make custom attribute, like [MyDisplayName("Section", "Key")]
And this would provide translation based on selected language. Also check out database driven resources manager, like http://www.west-wind.com/presentations/wwDbResourceProvider/

The best approach for localization is to store your strings in the database and not resource files unless,
Your app is very static
Your language set is very static
You can decorate your model with custom attribute where you set default string and DB id for the resource e.g.
[MyResource("email", 123)]
You can write custom http delegating handler to get resource out of cache (for example). Once you authenticate client, you know client's language demand and resource id. So, the client with Spanish and resource id = 1 will get "Si", the one with English will get "Yes". The resource id will be mapped to language-specific string.

Related

How to display fields of a content part when we add a new instance of a content type?

I'm trying to create a custom module which includes a content type (Project) which contains a content-part (ProjectPart). Projects will be created by admin. And the goal is to show these created project on a specific page.
When I try to instantiate a new project on the admin menu, I only see one field (Description). Other fields are not shown.
I followed the steps (starting from PersonPart.cs) in "Lombiq.TrainingDemo" project, and managed to create a custom module which includes a content type (Project), a content part (ProjectPart). Comments in the project claim that we can create an instant with all fields. But this is not true for my case.
Here is my code:
https://gist.github.com/vogucore/efb0096e349591c235103e4f3f9e60d1
Here you can see what I exactly mean.
I expect to see & edit all of its field, but only "Description" field is shown up.
Could you please tell me whether I'm missing something, or the explanation in the project is not true?
Thanks in advance. Peace! (;
It seems you are confusing properties of a content part with fields of a content part, which are two different concepts in Orchard.
Parts are regular C# objects that can have regular C# properties. Using such properties is the valid and mainstream way for developers to extend the CMS and build custom parts in Orchard.
Fields are smaller units of contents (typically a single string, or a number, or an image, etc.) that can be dynamically added to a part, trough code or through the admin's content type definition editors. They have the advantage that the administrator of the site can add, remove and modify them at runtime.
It's very understandable that you'd confuse them: they are both name/value thingies that you can attach to a part. In terms of actual usage, a good way to choose between the two is to ask the following question:
Is this a core property that is firmly attached to the part concept I'm building, or something that would be nice for administrators to attach to it if it makes sense to them?
For example, if I build a commerce product part, it would make sense that the SKU and price would be part properties. Now a product photo is different in that not all products may necessarily have a photo, some may have several, may be videos, who knows? It's just not an intrinsic property that makes a product a product. So make that a field (a media picker field to be specific).
To get back to your specific example, you should not be adding that field in your migration: it's basically creating something that looks like it's your Description property, but actually is a Description field, in addition to your property of the same name.
The reason why your part properties don't appear on your editor is that you aren't done with your part. You still need to build a driver, and views for it (the field didn't need that because they were already built by whoever built that field).
As a side note, I think the good Lombiq folks made a lousy choice by giving that Biography property the TextField type. It's very confusing, and should really be a string, in my opinion, and so should your Description property.

How can I localize AspNetCore built in messages in French?

Using the AspNetCore 1.1 preview 1 bits all examples I can found on the documentation demonstration how to localize my own resouces, I would like to localize the built in messages, for instance validation messages.
My application is only intented to be used by French people so my default culture is fr-FR.
How can I localize all the built in resources into French ?
As of 1.1 preview 1, there is no API to convert all framework messages into a different language.
For data annotation validation, you can customize error messages in code. Given that you are just looking to support French, you may find it easiest to override the ValidationAttribute.ErrorMessage property.
Example:
public class LoginViewModel
{
[EmailAddress(ErrorMessage = "(Translation for 'this email is invalid' here)")]
public string Email { get; set; }
}
You could also use the ValidationAttribute.ErrorMessageResourceName and ValidationAttribute.ErrorMessageResourceType properties. See https://learn.microsoft.com/en-us/dotnet/core/api/system.componentmodel.dataannotations.validationattribute for more details
If you want even more low-level control, you would need to override framework localization. API such IStringLocalizer exist. The documentation you linked to introduces some of those extensibility points. (Checkout https://aspnetsource.azurewebsites.net if you want to inspect how framework code calls these APIs.)

How do I validate data in C# based on a Struts validation.xml?

I have a validation.xml file from Struts, and am going to implement a server-side validation in .NET based on it. The validation.xml file is accompanied with a validationMessages.properties file. Are there any .NET libraries which are capable of performing a validation based on a Struts validation file?
In case this has never been done I'll have to either create such a class, since the validation file is too long and complex to be implemented as mere C# logic. Which begs the question: How would I even begin?
The end-goal is to be able to populate a C# class with properties for all fields, execute a validation method with that class as a parameter and have it return a list of validation error messages (or no errors in case of success).
I'd be surprised if anything like that existed; it's relatively unusual to move from Java -> .NET.
First, see if there are any custom validators. That code would need to be duplicated.
Then pick apart the different forms (or actions, depending on how they did validation). Put each of those into a C# class (but see below) rather than one giant one. I'm not sure what you mean by "A C# class with properties for all fields"; personally I'd go more granular.
Or just use an existing C# validation package and do a translator from Apache Commons Validation to the C# configuration (or code).
It should be a relatively straight-forward process since the validation config is well-known and documented, and all the code is available.

Audit Logging using ASP.NET MVC 4 ActionFilter

I'm building a web app using ASP.NET MVC 4, with data storage provided by T-SQL database via Entity Framework. I'm integrating audit logging as I go, and I'd like to provide a nice human-readable summary of the action, so that I can present a friendly logs view with clear statements like "User Bob logged in", "User Alice updated article 'Foo'", etc.
An audit record currently consists of:
GUID
timestamp
user ID
action category (controller name)
action (action method name)
IsError (boolean; true means either this is a record of an error, or this action did not complete successfully)
blob of serialised details
At the moment, my logging uses a custom attribute which implements IActionFIlter; the OnActionExecuting() method logs the attempted action (serialising things like URL, parameters etc to the detail blob) and the OnActionExecuted() method goes back and sets IsError to true if there are no errors, and appends either the returned result or exception with error message and stack trace etc to the details. I want to add another column for description strings, but I can't see a tidy way to do it.
The furthest I got was to pass a string to the attribute, something like "User $user logged in" and then have the log method scan the string for the $ character and replace that word with anything from the parameters dictionary whose key value matches that word (minus the $ character). This is a little limited; for example, if articles are stored by ID number, then the best you can manage is "User 18 edited article 37". There's no real way to get at the username or article title; you can't pass instance data to the attribute because it's baked in at compile time, and I don't really want my logging method to be making all sorts of database calls to get that sort of data, not least because it then becomes impossible (or at least a real pain) to have a single generic logging method.
The alternative to all this is to have a static audit logging class and call something like AuditRecord.WriteLog(foo); all over the place, perhaps with some kind of descriptor class I can use (or inherit from) to describe different types of action, storing all the parameters and generating a description string as needed, but seems less elegant to me; I really like being able to just tag [AuditLog] on top of a method and know that it'll be recorded.
I'd like to avoid huge amounts of conditional logic, like using the controller and action names in some big switch statement to select the correct string template. If I could just get hold of things like article titles in the logging method then it'd be fine. Is there a neat, simple way to do this?
We recently had a similar discussion at work regarding both logging audit history and applying more complex security rules across our new MVC project.
In the end the most "elegant" solution that we came up with was to have the method calls within the controller actions (Your alternative method).
For example:
[HttpPost]
public ActionResult CreateItem(Item item)
{
//Simplified
CheckSecurity(SecurityTypes.ItemCreation);
LogActivity("Created an item");
//Rest of action code
}
This gave us the flexibility to account for all possible use cases, and allowed us to wrap up the logic into simple to use methods to reduce code repetition.
It may be late to answer, but I think there is a good alternative to keep using action filter attributes and to be able to access per-request lifecycle objects.
As anaximander noted it above, the underlying problem is that attributes are resolved by the CLR, so their lifetime cannot be controlled and they don't mix very well with an IoC container (to make them transient, per request instance, etc.).
Usually, in .NET a new instance of attribute is created each time it is resolved by reflection (GetCustomAttribute method).
Furthermore, in the case of MVC/webapi, action filter attributes are cached, so they normally are created just once.
The conclusion is that attributes are designed to annotate only, in other word, they should contain only metadata (they are DTO). Unfortunately, my understanding is MVC and WebApi frameworks are not designed in this way. To restrict action filter attributes to simple DTOs and to be able to manage lifecycle of the logic part around them, special means must be taken.
I think your use case fits perfectly to the solution provided in a Steven van Deursen's great article. It demonstrates how to separate attributes data from logic and it is based on an action filter registered globally, the so called "dispatcher", with the ioc container as a dependency.
The container is not resolved statically. It is provided in the constructor of the global filter when it is registered at the application initialization.
So each time it is executed, it looks for any attribute marker on the action being executed and it resolves a generic interface where the attribute is the generic parameter. Instead of having an action filter attribute which merge data and behavior, you end up using two classes: a plain old attribute - the marker - and the corresponding implementation of the generic interface for its logic counterpart. The container is used to resolve the generic interface. If your filter depends on per-request components, you can create an implementation of the generic interface with the services you need. If it does not depend on other services but you need a per-request lifetime (to measure time between the beginning and the end of an action for example), it also does the job, thank to the use of the container to resolve the generic interface. The aforementioned article contains code examples for WebApi, MVC and ASP.NET 5.
Also, Mark Seemann has made an article on the same approach.
I think it does not provide a good solution for all cases, like authorizations filters and perhaps exception filters, but to me it is the most elegant way for many action filters.
The better way would be to format this data when you view it, rather than build these things during the logging process.
If the action is "login", and the recorded user is available (which you should do) then you build that message in the viewer.
So you log all the raw events, then build the "view model" or "read model" based on this data that is more descriptive. this can allow you to even re-parse all the raw data if you want to change it's description. You could log a lot of data that isn't used yet so you could implement it later within the description.
IMO, sprinkling methods this way inside actions doesn't seem like a good idea and an Action Filter on the controller or base controller is cleaner. if you wanted to do that you could use an AOP (aspect oriented programming) framework to avoid cross cutting...

Data-annotation getting errormessage out database

With asp.net mvc you can use the annotation
[Required (errormessage="This is required")]
How can I create something like this:
[Required (errormessage="ERRORXX")]
So I can look up in a database what this ERRORXX is and display it on my form. Now my form displays ERRORXX.
How can I create something that solves my problem?
Thx!
Just an idea: why not pull the error messages from a resx file? I think this is the common way of doing this. It even allows you to localize your error messages easily.
I think that by using a resource file (resx file) it's even easier to change the error messages later on. A resx file can be opened and edited in Word Pad for example. You don't need to access a database with username/password, query it, etc.
Localizing ASP.NET MVC Validation
Globalizing ASP.NET MVC Client Validation
Take a look here too:
Model Validation & Metadata in ASP.NET MVC 2
Customizing ASP.NET MVC 2 - Metadata and Validation
The default route to take is with Resources.
However, I understand your pain :) The way I've achieved it is a little unusual, but I'll give you a quick rundown.
In our project, using resource files is not an option as its way too limited for our purposes, the details of which I won't bore you with now! :)
At it's most basic principle, we're setting the errorMessage property of the validation attribute to some sort of "key", and then just using that as a way to lookup the correct (languaged) response in our CMS database, when the validation fails (in our case using MVC, when we update the model and check the state - all at Controller level).
This is the same principle as using the resources (by specifying "ErrorMessageResourceName" and "ErrorMessageResourceType"), but you get to do what you want with it.
To be clear, we originally extended the RequiredAttribute (as one example) with our own stuff, including putting in properly named arguments to allow us to retrieve a sensible CMS value from the database later on. To be extra clear, we're using MVC and custom HtmlHelpers to render our own ValidationControls, which are what ultimately consume the custom values from our custom annotations, etc - None of this affects the dumbed-down principle here though, which is to just use "errorMessage" , or something like it, as a way to look up the actual message from where YOU want to, and WHEN you want to.
I think you mean you want to read/use attribute declarations for a given property?
If so, you could either make your own RequiredAttribute class (to allow adding new or more appropriate properties as you wish). See: Attributes Tutorial

Categories