Feed Subscribe
Exception has been thrown by the target of an invocation.


Globalization is not an enemy

by ondrejsv 9. December 2009 18:36

System.FormatException: Input string was not in a correct format. The exception I see again and again because I’m running an English Windows 7 with Slovak regional settings and some developers just can’t imagine there are regions in the world where the decimal separator is not a period (.) but a comma (,) or where they use more than 12 hours a day. It’s unfortunate for them because many more people live outside the USA so reach of their application is far less than it could be.

Today I want to build a demonstration utilizing a Ribbon bar in my Silverlight application and I found one. A sample was attached but it crashed immediately after start with the aforementioned exception. The Ribbon control stores some default brushes in an XML file and parses on its own with code like this:

string xStr = pointAsString.Substring(0, pointAsString.IndexOf(","));
string yStr = pointAsString.Substring(pointAsString.IndexOf(",") + 1);

return new Point(double.Parse(xStr), double.Parse(yStr));

If we take a look at a fragment of the XML:


<LinearGradientBrush Name="GroupedButtonSemiHighlight" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#FFFEF7" Offset="0.0" />
<GradientStop Color="#FFF7DF" Offset="0.5" />
<GradientStop Color="#FFEEBE" Offset="0.6" />
<GradientStop Color="#FFF6DD" Offset="1.0" />
</LinearGradientBrush>

we see that it cannot succeed on any client configuration which does not use a point as decimal separator because the double.Parse method without providing an IFormatProvider would parse the string using the current regional settings.

If you write code that parses numbers from a content not edited or viewable directly by users and don’t want to take regional settings into account, always use the Invariant Culture as your IFormatProvider.

So I fixed the code:

string xStr = pointAsString.Substring(0, pointAsString.IndexOf(","));
string yStr = pointAsString.Substring(pointAsString.IndexOf(",") + 1);

return new Point(double.Parse(xStr, CultureInfo.InvariantCulture), double.Parse(yStr, CultureInfo.InvariantCulture));

More detailed information on internationalization, globalization and localization issues can be found on the Globalization Step By Step Microsoft site.

kick it on DotNetKicks.com [digg]

Tags:

Entity Framework metadata deployment

by ondrejsv 15. March 2008 18:41

Every project targeting Microsoft ADO.NET Entity Framework requires creating a conceptual entity data model, a storage model describing physical data source and a mapping between these two. Each of these metadata resides in its own XML file with its own XML schema (CSDL, SSDL and MSL, respectively). Today I want to spend a few words about what possibilities you have regarding deployment of them.

Besides very simple scenarios I suppose that all Entity Framework models will be defined within standalone projects that are part of a bigger solution to preserve modularity and maintainability. Such a project contains one or more .edmx files created and edited in the Visual Studio EDM designer most of the time. An .edmx file is just a blend of CSDL, SSDL, and MSL content together with some data for diagramming support. This file is processed by EntityModelCodeGenerator tool which extracts corresponding .csdl, .ssdl and .msl files. Note that hand crafting these files is a perfectly valid way.

You then write path to the metadata files (.csdl, .ssdl and .msl) as part of your Entity Framework client connection string:


<connectionStrings>
<add name="NorthwindEntities"
connectionString="metadata=.\Northwind.csdl|.\Northwind.ssdl|.\Northwind.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=SERVER\SQL2000;Initial Catalog=Northwind;Integrated Security=True;MultipleActiveResultSets=False&quot;" providerName="System.Data.EntityClient" />
</connectionStrings>

You have a couple of choices here (most of them have not been fully documented yet). An obvious choice is a physical file system path. The problem with this approach is that if you write a relative path, it is resolved against the current directory which is a very fragile thing. Take for example an ASP.NET web site/project -- the current directory is set up by the process hosting the site and it's usually anything what you don't expect. When you host your site in the IIS, most likely it's the system directory, while when you are debugging the site inside Visual Studio ASP.NET Development Server, it's C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE or something similar.

Better alternative in case of an ASP.NET web site is to use a well known tilde (~) prefix. This option is undocumented as far as I know. Internally the Entity Framework resolves the path using the HostingEnvironment.MapPath method so you may use any virtual path. For example let's suppose that we have a directory called models in the root virtual directory. Then the connection string could look like:


<connectionStrings>
<add name="NorthwindEntities"
connectionString="metadata=~\models\Northwind.csdl|~\models\Northwind.ssdl|~\models\Northwind.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=SERVER\SQL2000;Initial Catalog=Northwind;Integrated Security=True;MultipleActiveResultSets=False&quot;" providerName="System.Data.EntityClient" />
</connectionStrings>

The last option is to embed the metadata as resources. Let's say that our Entity Framework models (.edmx files) are defined within a project called Models. We can automatically embed the generated .csdl, .ssdl and .msl files as resources by setting the Metadata Artifact Processing property of the conceptual entity model (this is what shows up when you open an .esmx file in the Visual Studio) to Embed in Output Assembly:

EmbedMetadata

However, do not set Build Action in the properties of the .edmx file itself to Embeded Resource nor to Resource, just leave it as Entity Deploy:

EdmxFileProperties

Of course, if you craft the files by hand, just embed them into the assembly as usual (Build Action to Embeded Resource for all of them).

Entity Framework client connection string recognizes the res:// prefix for locating metadata in resource manifests. Common syntax is res://assembly/resourcepath. In our case it could be:


<connectionStrings>
<add name="NorthwindEntities"
connectionString="metadata=res://Model/Northwind.csdl|res://Model/Northwind.ssdl|res://Model/Northwind.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=SERVER\SQL2000;Initial Catalog=Northwind;Integrated Security=True;MultipleActiveResultSets=False&quot;" providerName="System.Data.EntityClient" />
</connectionStrings>

One special note: instead of a specific assembly name you may use an asterisk (*) to force the Entity Framework to search in all referenced assemblies which is quite useful when you have a single ASP.NET web site (not an ASP.NET web project) with .edmx files placed directly in the site -- then the ASP.NET compiler generates many assemblies with generated names so you don't know the name of the assembly your metadata will be part of in advance:


<connectionStrings>
<add name="NorthwindEntities"
connectionString="metadata=res://*/Northwind.csdl|res://*/Northwind.ssdl|res://*/Northwind.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=SERVER\SQL2000;Initial Catalog=Northwind;Integrated Security=True;MultipleActiveResultSets=False&quot;" providerName="System.Data.EntityClient" />
</connectionStrings>

Unfortunately, the tilde (~) and res:// prefix for locating files given as either virtual paths or resources are not any kind of widely universal standard in the .NET framework. Entity Framework parses input and locates files on its own as many other frameworks/libraries and even parts of the .NET framework itself. I think that a standard describing common schemas (prefixes) and a standard component in the .NET framework handling it would be very useful.

kick it on DotNetKicks.com

Tags: ,

AppSettingsReader and reading typed and nullable application settings

by ondrejsv 8. January 2008 21:38

I'm pretty sure that almost every .NET developer has heard of the possibility to include various application settings in the configuration file (app.config or web.config). Application settings are just plain string key-value pairs we used to store in the past inside plethora of .ini files and in the Registry. A common way to read them in the .NET framework is to use the static AppSettings property of the ConfigurationManager class. This property returns an object of the NameValueCollection type containing the application settings key-value pairs.

However, there is a class named AppSettingsReader which is a wrapper around the AppSettings collection and I found that only a few know it. The only "useful" method (i.e. not inherited from the Object class) is the GetValue method. It takes two parameters: key of the application settings item we want to retrieve and type to convert the value to, so we don't need to convert the value manually. Another difference over directly using AppSettings is that this method throws InvalidOperationException if no item with the specified key is present.

Suppose we have a configuration file as following:

<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="Color" value="Red"/> <add key="FailAttemptCount" value="5" /> </appSettings> </configuration>

We may then use the following snippet to read these settings:

AppSettingsReader appSettingsReader = new AppSettingsReader(); Console.WriteLine( appSettingsReader.GetValue("Color", typeof(string))); int failCount = (int) appSettingsReader.GetValue("FailAttemptCount", typeof(int));

Internally GetValue uses the ChangeType method of the Convert class to explicitly convert the read value. However, GetValue returns the value as object so we must use a formal downcast to assign the value to a typed variable (see below for a possible solution). Note that the Convert class supports converting only to .NET base types.

There is another feature of the AppSettingsReader which is undocumented as far as I know. For string values you may use "(None)" as value to indicate there is in fact no value but the setting is present. In a rare case you want to have "(None)" as a valid value, just enclose it within parenthesis. If we introduce these values to our configuration file:

<add key="PreferredName" value="(None)"/> <add key="NoneString" value="((None))"/>

then

appSettingsReader.GetValue("PreferredName", typeof(string))

returns a null string and

appSettingsReader.GetValue("NoneString", typeof(string))

returns "(None)" as value.

As I've mentioned, in the original implementation this trick works only for string values but it is straightforward to extend it to other types. In the attached demonstration project you can find MyAppSettingsReader class -- an implementation derived from AppSettingsReader. Then if we have:

<add key="PreferredName" value="(None)"/>

then

int? maxOpenFiles = (int?)myAppSettingsReader.GetValue("MaxOpenFiles", typeof(int?));

maxOpenFiles will be assigned a null value.

Last note: the final downcast is very annoying and indeed it could be made unnecessary by implementing GetValue method as a generic one. With introduction of extension methods, we can atone this very easily with no access to original code and even without creating a derived class:

public static T GetValue<T>(this AppSettingsReader appSetReader,string key) { return (T)appSetReader.GetValue(key, typeof(T)); }

Then we may use it just like:

Console.WriteLine( appSettingsReader.GetValue<string>("Color")); failCount = appSettingsReader.GetValue<int>("FailAttemptCount");

I attached a demonstration project so be sure to have a look at it.

kick it on DotNetKicks.com

Tags: