I'm trying to localize error messages from NHibernate.Validator. From what I have read, the messages should automaticaly be localized if I set the CurrentCulture/CurrentUICultule ; wich I tried without success. I'm using S#arp Architecture with the default configuration. As I said, the only thnig I changed is the CurrentCulture/CurrentUICultule.
Do I have to create a custom message interpolator for nhibernate validator?
I have posted in my blog about creating a Custom Interpolator that overrides the default messages if they exist in your resources. It allows you to override the default messages and add new messages for your validators.
Check it out: NHibernate Validator Custom Messages
Changing the culture for was not a good idea, since all my website is in spanish, so the path that I took was to create a SpanishMessageInterpolator and then set it up in my nhv.config like:
<property name="message_interpolator_class">NHibernateValidator.SpanishMessageInterpolator, Assembly</property>
And finally I did modify my global.asax.cs file to include the nhv.config file on NHibernate initialization, like:
NHibernateSession.Init(
webSessionStorage,
new string[] { Server.MapPath("~/bin/Assembly.dll") },
new AutoPersistenceModelGenerator().Generate(),
Server.MapPath("~/NHibernate.config"), Server.MapPath("~/nhv.config"));
Related
I'm new to azure and also a rookie in .net, so this may be a noob question :)
Anyway, I have successfully managed to log to Azure Log Analytics using this code snippet:
var loggerConfig = new LoggerConfiguration().
Enrich.WithExceptionDetails().
Enrich.WithApplicationInformation(serviceName).
MinimumLevel.Debug().
MinimumLevel.Override("Microsoft", LogEventLevel.Information).
Enrich.FromLogContext().
Destructure.ByTransforming<ExpandoObject>(JsonConvert.SerializeObject).
//Enrich.WithProperty("ErrorMsg_CF","test").
WriteTo.AzureAnalytics(workspaceId: "MyWorkSpaceID",
authenticationId: "MyAuthID",
logName: "MyCustomLog_CL",
restrictedToMinimumLevel: LogEventLevel.Debug)
And:
Logging.Logger.Initialize(serviceName: "Logging Web Test v1.1");
Logging.Logger.GetLogger().Log(LogLevel.Debug, "{ErrorMsg_CF}:{TraceID_CF}:{UserName_CF}", errorMsg,traceID,userName);
I have, in my Log Analytics custom log table, created 3 custom fields: "ErrorMsg_CF", "TraceID_CF" and "UserName_CF", and I want to either be able to directly log to these custom fields, or somehow split my errormsg into these three custom fields.
When I import a file, I see that the message is stored in the "RawData" field, and with that field I am able to use the custom field generator and create custom fields, and also let Log Analytics split the message into the fields for me. But, when I do it through my application, the message is stored in the "LogMEssage_s" field, and seems like it's not possible to create custom fields from that field.
So, anyone know how I can log to my custom fields from my application?
The default formatting configuration is a line by line event logging. ALN can be ingested using JSON so that will be the best way to format log entry in that way.
.WriteTo.DESTINATION(new CompactJsonFormatter(), OTHER OPTIONS HERE)
Serilog formatting
I can do this in .net core
_logger.LogInformation("Token validated {clientId}", "MyId");
And then logging libraries like NLog will know that there is a property called clientId with the value MyId in the message and can render it in a special way.
I am trying to do the same without including the property in the message itself, but cannot manage to nail it. This is what I have done so far and it does not result in a property in NLog:
LogEventInfo info = new LogEventInfo
{
Properties = {{"clientId", "MyId"}},
};
_logger.Log(Microsoft.Extensions.Logging.LogLevel.Information, "Token validated", info, null, info.MessageFormatter);
This results in a message without property. Is there a better way to do this or have I done something wrong?
The whole idea with Microsoft-Extension-Logging (MEL) ILogger-interface is not being dependent on a specific Logging-Framework.
If you start creating NLog LogEventInfo-objects, then you might as well call NLog.LogManager.GetCurrentClassLogger() and use that as Logger.
But maybe this wiki-page can give you some ideas:
https://github.com/NLog/NLog.Extensions.Logging/wiki/NLog-properties-with-Microsoft-Extension-Logging
We are working on a legacy C# enterprise app. Its client uses several web services, whose URLs, among lots of other settings, are read from the local app.config file. We want to migrate these settings into a global DB to simplify their management. However, I can't figure out how (and whether) it is possible to migrate the web service URLs. These are read from the service client code generated by VS and I can't seem to find a way to tell VS to use a different settings provider than the one generated into Settings.Designer.cs .
We can overwrite the service facade's Url property with the value we want, after it is created - this is the solution currently used in several places in the code. However, I wouldn't like to touch every part of our codebase where any of these services is used (now and in the future). Even less would I like to modify generated code.
There has to be a better, cleaner, safer solution - or is there?
Btw our app runs on .NET 2.0 and we won't migrate to newer versions of the platform in the foreseeable future.
The Refernce.cs file that is generated by the Visual Studio indicates that the URL of the webservice will be retrieved from the settings:
this.Url = global::ConsoleApplication1.Properties.
Settings.Default.ConsoleApplication1_net_webservicex_www_BarCode;
I believe that John Saunders gave you a wonderful suggestion in his comment. You need a SettingsProvider class which:
...defines the mechanism for storing configuration data used in the
application settings architecture. The .NET Framework contains a
single default settings provider, LocalFileSettingsProvider, which
stores configuration data to the local file system. However, you can
create alternate storage mechanisms by deriving from the abstract
SettingsProvider class. The provider that a wrapper class uses is
determined by decorating the wrapper class with the
SettingsProviderAttribute. If this attribute is not provided, the
default, LocalFileSettingsProvider, is used.
I don't know how much you have progressed following this approach, but it should go pretty straighforward:
Create the SettingsProvider class:
namespace MySettings.Providers
{
Dictionary<string, object> _mySettings;
class MySettingsProvider : SettingsProvider
{
// Implement the constructor, override Name, Initialize,
// ApplicationName, SetPropertyValues and GetPropertyValues (see step 3 below)
//
// In the constructor, you probably might want to initialize the _mySettings
// dictionary and load the custom configuration into it.
// Probably you don't want make calls to the database each time
// you want to read a setting's value
}
}
Extend the class definition for the project's YourProjectName.Properties.Settings partial class and decorate it with the SettingsProviderAttribute:
[System.Configuration.SettingsProvider(typeof(MySettings.Providers.MySettingsProvider))]
internal sealed partial class Settings
{
//
}
In the overridden GetPropertyValues method, you have to get the mapped value from the _mySettings dictionary:
public override SettingsPropertyValueCollection GetPropertyValues(
SettingsContext context,
SettingsPropertyCollection collection)
{
var spvc = new SettingsPropertyValueCollection();
foreach (SettingsProperty item in collection)
{
var sp = new SettingsProperty(item);
var spv = new SettingsPropertyValue(item);
spv.SerializedValue = _mySettings[item.Name];
spv.PropertyValue = _mySettings[item.Name];
spvc.Add(spv);
}
return spvc;
}
As you can see in the code, in order to do that, you need to know the setting name as it was added in the app.config and the Settings.settings when you have added the reference to the web service (ConsoleApplication1_net_webservicex_www_BarCode):
<applicationSettings>
<ConsoleApplication30.Properties.Settings>
<setting name="ConsoleApplication1_net_webservicex_www_BarCode"
serializeAs="String">
<value>http://www.webservicex.net/genericbarcode.asmx</value>
</setting>
</ConsoleApplication30.Properties.Settings>
</applicationSettings>
This is a very simple example, but you might use a more complex object to store the configuration information in conjunction with other properties available in the context such as item.Attributes or context in order to get the proper configuration value.
In my MVC 3 application I am using fluent validation.
public class AccountModelValidator : AbstractValidator<AccountModel>
{
public AccountModelValidator()
{
m.NewPassword).WithMessage(Translator.Data["ConfirmPasswordValidation"]);
}
}
For localization I am using an example that I have found from here, but I have found that I have the same validation message for all languages.
The reason is that validator doesn't know that I have change the language.
How can I correctly do this?
Maybe I should use WithLocalizedMessage but it works only with .resx
When the WithLocalizedMessage returns the same value for all languages, most likely the culture isn't set yet (this happens on a POST, where the action handlers haven't run yet)
Solution is to set the culture in a different location:
Best place to set CurrentCulture for multilingual ASP.NET MVC web applications
I know I can set a CultureInfo object with an specified culture in the Application_BeginRequest event as is described here, but I don't want to do it for each request but in the application startup.
All I can imagine is that I can use the Application_Start event, but I don't know how to set the global culture.
Set it in your web.config:
<globalization uiCulture="es" culture="es-MX" />
More info here: http://msdn.microsoft.com/en-us/library/bz9tc508.aspx
Thread.CurrentThread.CurrentUICulture
Keep in mind, this is overriding the settings that the WinForm app will have gotten from the computer. For example, if the user has a custom date format defined, this will replace that.
gattaca's answer is right, but if you want to really dynamically change the cultureinfo based on use's preference or browser's language setting, the best place is override Page class' InitializeCulture method. So you can write a base class to this.
protected override void InitializeCulture()
{
LanguageHelper.RestoreUserLangugagePreferrenceIfAvailabe();
}
Of course this seems to over kill, because you need the change the base class. There are other place to put at, like using a module to inject your code, but I try all those solutions, page_load event, but they all do not work 100% with .net localization architecture. Try the localresource file, global resource file, and you will see what I mean.