Accessing resource strings with CultureInfo in .NET - asp.net

Another simple questions.
I have website with different languages. If I want to access a string from the resource file I would use it like this
Resources.MyResourceFile.MyStringIdentifier
Very easy. That way I know during compile time, that the resource string exists.
Now, this works only if I want to use the current Culture. Sometimes I need to specify a specific culture (let's say that the current user uses German as a language, but his action triggers messages to be sent to other users which will be in the recipient's language). Now, I see two options:
Resources.MyResourceFile.ResourceManager.GetString("MyStringIdentifier", neededCulturInfo)
The other would be to change the current thread's culture info which I would need to do several times.
Is there a third way? Something which tells me at compile time that the resources exist but without the need to change the thread's culture all the time?

(For your scenario) the idea of the ResourceManager is to provide culture specific informations at runtime not at compile time (aka side-by-side with fallback).
So the answer is "NO", there isn't a buildin way to determinate the existance of those resource files at compile time - to do so you would require a kind of "hard coding" for all strings in every single langauge and also code to access to those. The side by side idea is exactly the opposite of hardcoding ;)
What you could do, is writng a unit test for the resources, that itterates your langauges and checks if the default or a localized value was used. Further if you are using a source control system that provides check-in policies (e.g. TFS) you could this unit test as part of the check-in policy.

Have you tryied :
public static Object GetLocalResourceObject (
string virtualPath,
string resourceKey,
CultureInfo culture)
Try this link Click here
You can also try:
public static Object GetGlobalResourceObject (
string classKey,
string resourceKey,
CultureInfo culture)
Try this link Click here

ResourceSet has a method
public virtual IDictionaryEnumerator GetEnumerator()
that gives access to key-value pairs of the resource file.
E.g. (assuming we deal only with strings - N.B. the key-value pairs are of type object):
while (set.MoveNext())
{
string key = (string)set.Key;
// string value = (string)set.Value;
string value = ResourceManager.GetString(key, neededCulturInfo);
}
This is not what you should do, because things become complicated - just to point it out.
You could create different resource files for different cultures and use a switch code block in a method that has a CultureInfo as parameter.

You construct a class that looks inside the resource or use the Enumerator solution,look for the value and if it does not exist, make it use the value in the default language.
But in compile time, it cannot be verified.
The easiest option is a try-catch and return the value in the general language in the catch.
Nevertheless, if we are using resources, all the keys must always be present in all the related files, even if you copy them with the general language values.
My solution is what it should be, all the resources should be consistent, if not we are using this great tool badly.

The generated Resources.MyResourceFile class has a static Culture property, which you can set to neededCultureInfo to override the current thread's CurrentUICulture.

1) At the start maybe could be useful to store the UICulture into a session, in order to change it when you want, at the begin you can change it from there.
2) You can override the UICulture in preRender and set it from there and than storing it into session.
You can store it in a cookie as well but is not the best solution for it.

You can use WorkItems to send the messages asynchronously. Since you're now running on a different Thread, you should be able to modify the CurrentUICulture as needed.
P.S.: this is a good example why static dependencies are bad and everything should be interfaces & instances.

Related

best approach to implement getRealPath()

I am working on struts 2.0 . I am designing a web application.
I am using Jasper Report in my application. I want to access the *.jrxml files in my action class. I don't want to give hard coded path to the files. So to get the path dynamically I googled it and got the solution that I can get the path using getRealPath() method. But I found two implementation of doing this:
Using HttpSession to get object of ServletContext and using the getRealPath() method of the ServletContext object.
Like this:
HttpSession session = request.getSession();
String realPath = session.getServletContext().getRealPath("/");
The second approach to do it directly using the static method getServletContext() of ServletActionContext. And then we can get the real path of the application using the getRealPath() method.
Like this:
String realPath = ServletActionContext.getServletContext().getRealPath("/");
Please tell me, is there any difference between the above two and also please tell me whether there is any other way to get the path?
Neither is "better", really, and I'd argue that neither is particularly good, either.
I might try getting the context path in an initialization servlet and stick it into the application context, then make your action(s) ApplicationAware and retrieve the value from the map.
This has the added benefit of aiding testability and removing the static references in the action.
That said, I see zero reason to go through the extra mechanics of your first approach: it adds a lot of noise for no perceivable benefit; I'm not even sure why it wuld be considered.
I'd also be a little wary of tying your actions to a path like this unless there's a real need, what's the specific use? In general you shouldn't need to access intra-app resources by their path.

Keep a history of values for specific properties of EF entities

I have a requirement to keep a history of values of some fields in an EF4 ASP.NET MVC3 application. This just needs to be a log file of sorts, log the user, datetime, tablename, fieldname, oldvalue, newvalue.
Although it would be pretty easy to code this in various save routines, I'm wondering if I can get global coverage by wiring it into some sort of dataannotation, so that I can perhaps declare
[KeepHistory()]
public string Surname { get; set; }
in my partial class (I'm using POCO but generated from a T4 template).
So Questions
1) Is this a bad idea ? I'm basically proposing to side-effect changes to an entity, not directly referenced by the code, as a result of an annotation.
2) Can it be done ? Will I have access to the right context to tie up with my unit of work so that changes get saved or dropped with the context save?
3) Is there a better way?
4) If you suggest I do this, any pointers would be appreciated - everything I've read is for validation, which may not be the best starting point.
Actually, validation might be a good starting point. Since an attribute does not know about which property or class it was assigned to, but a validation-attribute gets called by the validation framework with all the necessary informátion. If you implement the System.ComponentModel.DataAnnotations.ValidationAttribute class you can override the IsValid(object, ValidationContext) method, which gives you the actual value of the property, the name of the property and the container.
This might take a lot of work, since you need to get to the currently logged-in user etc. I'm guessing that the .NET implementation provides some sort of caching for the specific attributes on an entity type, which would be a pain to implement by yourself.
Another way, would be to use the ObjectStateManager exposed by your EF ObjectContext, which can provide you with the ObjectStateEntry-objects for all entities of a given state. See the
ObjectStateManager.GetObjectStateEntries(EntityState) method, for more information about how to call it (and when). The ObjectStateEntry actually contains a record of the original and current-values, which can be compared to find any changes made within the lifetime of the current ObjectContext.
You might consider using the ObjectStateManager to inject your custom logging behavior, while this behavior decides based on property-attributes which change should be logged.

Type Safe Coding

When i started developing web applications i stored the authentication details of the user in two session variables
Session["UserName"]="username";
Session["Password"]="paswword-123";
But someone proposed me an idea to create a class which holds the UserName and Password properties and on succesful authentication i have been asked to create an instance of the class and set the UserName and Password properties and store that instance in the session.
I have been told that the session object is TypeSafe. Can someone explain what is typesafe coding and the advantage of storing the object in the session.
Basically, the classic approach of storing values directly in Session["something"] has two drawbacks:
Magic strings: If you mistype something, your code compiles fine but you get either a runtime error or, worse, an unnoticed bug in your code.
Casting: After reading Session["something"], you need to cast it to the type you need. (This is what is meant by "not type-safe".)
Using a strongly-typed object that is stored in the Session eliminated the second problem. Well, actually, your custom object still needs to be cast, but it's only one cast instead of two (or ten) casts, which reduces the likelyhood of something going wrong. Again, a wrong cast is something which is only detected at run-time.
Another approach is to encapsulate the access to Session variables in static properties:
public class MySession {
public static string UserName {
get { return (string)HttpContext.Current.Session["UserName"]; }
set { HttpContext.Current.Session["UserName"] = value; }
}
}
Of course, both approaches can be combined, allowing you to group related properties (UserName and Password) in a common object.
Having a User class with 2 fields can be good for many reasons, as for type safety, if you ever type Session["Pasword"] somewhere you will get an error that wont be so easy to find, you will have to check for both parameter names everywhere. You need them to be correct, and its a great source of errors. Once you store User object instead of 2 unconnected strings you will have be able to use type safe code like User.Password instead of trying to access password by string indexer in Session. Also if your user ever gets more fields , which is very common you will simply add them to User class, not start creating new parameters & names and store them in Session heap.
As for typesafe coding I think http://en.wikipedia.org/wiki/Type_safety should help, or any other type of article on topic which is very popular I think.
Also I dont think you should store password in session, depends on your program logic but usually password should only be used to compute its md5 hash and never be used afterwards.
Well you're friend is half right, but I don't believe Session is inherently type safe. The Session collection stores instances of Object. So you can store an instance of any type (a string, an int, or a custom login class) because they all derive from object. However, when you retrieve that object, you don't know what type it is, and need to carefully cast it, with exception handling, before you use it.
eg this works fine:
Session["UserName"] = "Freddy";
string theUserName = (string)Session["UserName"];
However you could try to do the following, which will cause errors.
Session["UserName"] new StrangeDataClass(); //Uh Oh, that's not a string.
string theUserName = (string)Session["UserName"]; //unexpected behaviour based on StrangeDataClass.ToString() implementation.
To work around this, you'd have to do the following:
string theUserName = Session["UserName"] as string;
if (string != null)
//The cast worked...
else
//The cast failed, (or the string stored in session was null)
Having a custom login object slightly solves this problem, because you'd only have one object to worry about, and one cast to make. You could also extend the login object easily with extra information, and still not have to do any more casts.

Optional parameters in ASP.NET web service

I have a ASP.NET web service. This web service works fine. However, the WSDL lists some parameters as optional (minoccurs = 0) and others as non-optional. Some of the optional parameters are actually not optional, others which are marked as non-optional are actually optional. I would like to fix this, but I can't find the location where this information is coming from.
It seems to me that all primitive types (int, boolean etc.) are non-optional and all other parameters are marked as optional. However, I can't find a location where I can change this. I would like to specify default values for the primitive values if they are missing in the request and specify which non-primitive parameter is actually optional. Where do I do this?
I am assuming that when you say ASP.net web services, you are creating web services with ASMX extension. I think that what happens in this case is that all nullable types become optional and non-nullable become non-optional.
You could perhaps manually edit the generated WSDL file. But then you would have to redo that work if the wsdl was regenerated.
I would suggest that you switch to WCF with basisHttpBinding (except for the name of you service your clients should not notice the difference).
Using WCF you can simply mark the parameter in the data contract as required or not:
[DataMember(IsRequired="false")]
The primitives are not reference types, but rather they are value types. You can make a value type "nullable" a couple ways.
The short-hand is
int? i;
or long-hand here
Nullable<int> i;

ASP.NET Localized web site -- updating on the fly

I think I have a solution to this, but is there a better way, or is this going to break on me?
I am constructing a localized web site using global/local resx files. It is a requirement that non-technical users can edit the strings and add new languages through the web app.
This seems easy enough -- I have a form to display strings and the changes are saved with code like this snippet:
string filename = MapPath("App_GlobalResources/strings.hu.resx");
XmlDocument xDoc = new XmlDocument();
XmlNode xNode;
xDoc.Load(filename);
xNode = xDoc.SelectSingleNode("//root/data[#name='PageTitle']/value");
xNode.InnerText = txtNewTitle.Text;
xDoc.Save(filename);
Is this going to cause problems on a busy site? If it causes a momentary delay for recompilation, that's no big deal. And realistically, this form won't see constant, heavy use. What does the community think?
I've used a similar method before for a very basic "CMS". The site wasn't massively used but it didn't cause me any problems.
I don't think changing a resx will cause a recycle.
We did something similar, but used a database to store the user modified values. We then provided a fallback mechanism to serve the overridden value of a localized key.
That said, I think your method should work fine.
Have you considered creating a Resource object? You would need to wrap your settings into a single object that all the client code would use. Something like:
public class GuiResources
{
public string PageTitle
{
get return _pageTitle;
}
// Fired once when the class is first created.
void LoadConfiguration()
{
// Load settings from config section
_pageTitle = // Value from config
}
}
You could make it a singleton or a provider, that way the object is loaded only one time. Also you could make it smart to look at the current thread to get the culture info so you know what language to return.
Then in your web.config file you can create a custom section and set restartOnExternalChanges="true". That way, your app will get the changed when they are made.

Resources