Friday, August 19, 2011
Windows Phone 7 Resources
Windows Phone Developer Tools 7.0
Windows Phone Developer Tools 7.1 (Beta)
Silverlight Toolkit
Still WP7 doesn't support Arabic, but you can use the following library of controls to display Arabic text.
Arabic for WP7
Important Documentation:
Microsoft Windows Phone Developer Documentation - Offline Version (CHM Format)
User Experience Design Guidelines for Windows Phone
Windows Phone 7 Localization Explained (a previous post of mine).
Application Certification Requirements for Windows Phone
If you live in a country not yet eligible tosubmit apps to the AppHub, you may use:
Yalla Apps
(EDIT)
The Presentation
Tuesday, June 7, 2011
Login and Main Forms
The use case is:
- User starts an application.
- Login Form appears.
- Application Exists if the user closes the Login Form.
- Upon successful login the Login Form closes and the Main Form of the application shows.
- Application Exists if the user closes the Main Form.
Many developers suggests complex implementations including deriving from the ApplicationContext and use the derived class in an overload to the Application.Run() method.
Examples of what have been discussed:
http://stackoverflow.com/questions/1629205/windows-forms-create-the-main-application-after-login-which-form-to-run
http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/73aeabe3-42db-4747-b3c7-9a5e4ea393ac/
http://www.codeproject.com/KB/cs/applicationcontextsplash.aspx
The implemntation can be much easier than this.
The ide is to open the Login Form as a modal dialog in the MainForm Load event.
And close the main form if the result was not OK.
Try this:
Here is the entry point (nothing done here):
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}Login Form:
public partial class LoginForm : Form
{
private bool _authenticated = false;
private void _loginBtn_Click(object sender, EventArgs e)
{
if (AUTHENTICATION LOGIC)
{
_authenticated = true;
this.Close();
return;
}
MessageBox.Show("Login Failed", "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
private void LoginForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (_authenticated)
this.DialogResult = DialogResult.OK;
else
this.DialogResult = DialogResult.Abort;
}
}Main Form:
public partial class MainForm : Form
{
private void MainForm_Load(object sender, EventArgs e)
{
var loginForm = new LoginForm();
if (loginForm.ShowDialog() != DialogResult.OK)
{
this.Close();
}
}
}That's it.
Monday, April 18, 2011
ASP.NET Menu RTL
float:right !important;The !important keyword denotes that this style should overrule the inline style.You will need to do the same thing in the .menu ul li style.
To let the menu items to start from the right. Otherwise you will find the last menu item comes first.
Wednesday, April 6, 2011
WP7 Localization Explained
I’ll assume you understand that everything that applies for a language, also applies for the language-Culture.
I.e. you can use “en” for English or “en-UK” for English and United Kingdom culture.
The language will affect the translation and what’s written in the resource files will be used for that sake, and the culture will affect the formats of date, currency…etc.
Step 1 – Add Resource Files:
Anyone who has brief experience with localization in .net, will guess the first step.
You have to add a Resource file for each language you need to use in your application.
You should have a file for the default language and others for each other language used, having the same name as the default language file but with a small extension using each language abbreviation.
Let’s say I’m going to support English (default) and Italian. Then I should end up having something like:
MyResources.resx
MyResources.it.resx
If it’s your first time to use a resource file, this is added from: Project (right click) => Add => New Item => (pick Resource File).
- Needless to say, when you fill the resource files, the Name of each resource should match, and only the value should reflect the translation.
- So say I’m going to have (Hello/Hello) & (Hello/Ciao) as the English & Italian (Name/Value)s.
Step 2 – Declare the Languages you support:
We should tell the application which languages we are supporting. Guess it’s not smart enough to figure this out by itself.
And for this you we’ll have to close the project/solution. Then open the project file in notepad, and add the supported languages (except the default one) in the supported cultures tag, using semi-colon as a separator, as follows:
<SupportedCultures>it;</SupportedCultures>You’ll also need to define the default language in case the user is using a language you don’t support, and thus the default language should be used then.For that you need to go to the Project Properties => Application (Tab) => Assembly Information (button) => Set the (Neutral Language).
Step 3 – Use Resource-File in code behind:
Let’s see if this is going to work.
In the MainPage.xaml.cs, I’ll write the following in the CTor of the page.
PageTitle.Text = MyResources.Hello; Step 4 – Test:
Now you can test this on a device, and it should display the “Ciao” if you went to the phone settings and set “Italiano” as the display language.
But the Emulator won’t let you change the “Display Language”, so if you want to test this in the Emulator, you will have to set the language-culture in code. (Just for testing).
So go the App.xaml.cs and write the following in CTor or in the Launching event handler.
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("it");You may also add the following if you are testing the culture (format of dates, currencies…etc.)Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("it");** Don’t forget to remove these when you finish testing.Now you should see the localization working. I hate to say it but that’s not the end of it.
(UPDATE)
Now you can change the display language in the emulator, all you have to do is to click on the: "tap here to accept changes and restart your phone." link, which appears when you select a different Display Language.
Still this might be consume more time than applying the change in code.
Step 5 – Access the Resource Files in XAML:
To use the resource files in XAML, you need to map them to a Static Resource, to able to bind to them.
Say you have a TextBlock as follows.
<TextBlock Name="textBlock1" Text="Hello">And instead of hardcoding the Text, we want to use the resource files. In other words we want to bind the Text property of the TextBlock to the appropriate key/property of the resource files.We will go and define the generated Resource class as a static resource in the App.xaml, as follows:
<Application.Resources>
<local:MyResources xmlns:local ="clr-namespace:MyNamespace" x:Key="AnyGivenKey" />
</Application.Resources>Please make sure you replace MyNamespace with the namespace under which MyResources is defined.If you try to run the application now the following exception will blow right in your face:
AG_E_PARSER_UNKNOWN_TYPE [Line: 10 Position: 65]
Of type: System.Windows.Markup.XamlParseException
This issue has been reported here: http://connect.microsoft.com/VisualStudio/feedback/details/628281/silverlight-wp7-resource-files-and-binding
That’s because the class generated for the resource file was marked internal, and to access it from the XAML we need it to be public.
If you open each of the resx files, you will find an option in the toolbar to change the access modifier.
This should change the access modifier of the classes, but we still need to change the access modifier of the CTor. So you will have to open the default language resx.cs file, and look for the CTor and change the internal to public.
Now the application can run safely without weird exceptions.
And now it’s safe to go back to the TextBlock and change it to the following to use the Static Resource we just defined in the App.xaml:
<TextBlock Name="textBlock1" Text="{Binding Path=Hello, Source={StaticResource AnyGivenKey}}"/>That’s all? You wish…The problem now is: whenever you add extra resources to the resource files, the resx.cs class is re-generated and the modifier of the CTor gets set back to internal. So if you are happy with manually changing it each time you add a new resource and build your application, then you are done.
If it’s cumbersome tedious thing to manage, then we need to find another solution.
Step 5.2 – Access the Resource Files in XAML:
To overcome this internal access modifier thing, we will create a class that wraps the generated resources class, and use that as our static resource in the App.xaml, as follows:
public class MyResourcesWrapper
{
public MyResourcesWrapper()
{
}
private static MyResources _myWrappedResources = new MyResources();
public MyResources MyWrappedResources { get { return _myWrappedResources; } }
}And then our TextBlock should be changed to:<TextBlock Name="textBlock1" Text="{Binding Path=MyWrappedResources.Hello, Source={StaticResource AnyGivenKey}}"/>You will need to modify the Resource definition in the App.xaml into the following: <Application.Resources>
<local:MyResourcesWrapper xmlns:local ="clr-namespace:MyNamespace" x:Key="AnyGivenKey" />
</Application.Resources>One extra step to go (if you need to localize the application bar).
Step 6 – Localizing the ApplicationBar:
The application bar is not growing out of the Silverlight, it’s a shell system tray.
So using the binding method in the xaml file won’t work.
We will have to add items to the application bar in the code behind and set the required localized text as we’ve done earlier in step 3.
e.g.
MainPage.xaml
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>MainPage.xaml.cs
ApplicationBar = new ApplicationBar();
var appBarButton = new ApplicationBarIconButton(new Uri("/Images/appbar_button1.png", UriKind.Relative));
appBarButton.Text = MyResources.Hello;
ApplicationBar.Buttons.Add(appBarButton);
var appBarMenuItem = new ApplicationBarMenuItem(MyResources.Hello);
ApplicationBar.MenuItems.Add(appBarMenuItem);
References:
How to: Build a Localized Application for Windows Phone:
http://msdn.microsoft.com/en-us/library/ff637520%28v=VS.92%29.aspx
CultureInfo Class:
http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo(VS.95).aspx
Extra link for the WP7 toolkit controls:
http://blogs.msdn.com/b/delay/archive/2010/12/20/quot-and-she-d-say-can-you-see-what-i-m-saying-quot-how-to-localize-a-windows-phone-7-application-that-uses-the-windows-phone-toolkit-into-different-languages.aspx
Tuesday, January 18, 2011
Stopping IIS 6 Caching
For example a GridView didn't show inserted or updated data unless we refresh the page (F5). Or if we restart IIS (iisreset).
After some googling it was apparent that this is an IIS6 issue.
And every try to solve it by setting caching and expiration settings in IIS 6 failed.
The only solution we found working is to hardcode the following in Global.asax
protected void Application_EndRequest(Object sender, EventArgs e)
{
HttpContext.Current.Response.CacheControl = "no-cache";
}
WebForm_postbackOptions is undefined
And suddenly we stumbled acorss a script error on every page the error was:
"WebForm_postbackOptions is undefined" and it was complaining about Scriptresource.axd
It turned out to be the server clock (date in specific) was not correctly set.
It was set somewhere in the past. And so IIS felt something fishy was going on, as the assemblies required to be loaded have build dates in the future.
It took us quite some time to come to the core of this issue, having to go through many articles on the net, describing different causes and solutions to the same error.
We got the hint from Siderite blog. Thanks be to him :)
Sunday, November 7, 2010
Parser Error
/*********************************************************************************/
Server Error in '/' Application.
--------------------------------------------------------------------------------
Parser Error
Description: An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately.
Parser Error Message: Only Content controls are allowed directly in a content page that contains Content controls.
Source Error:
Line x: [/asp:content]
Line x+1:
/*********************************************************************************/
All pages were content pages of some master page. And nothing was written after the closing content tag.
At first I thought this was some kind of .NET vs IIS version mismatch or that I needed to change some IIS settings, since this was running fine on different IIS versions.
But to my surprise, some pages were displayed fine.
After banging my head few times, I found out the cause. The pages that were complaining had some spaces and empty lines after the closing content tag. This should mean nothing in html, but I guess IIS 5.1 didn't like these.
Clearing everything so that the closing content tag is practically the last thing written in a page, did the trick.
Hope this becomes helpful to anyone facing the same issue.
Sunday, July 5, 2009
Localization with MasterPages - The Final Cut
Intro:
Assuming you want your ASP.NET website/web application to have a multi-lingual interface. You'll find multiple resources on the internet on how to use LocalResources files or GlobalResources files to store specific language's data.
Nice Video Tour for Localization.
A specific language resource would be loaded according to the user's browser language preferences.
But most probably you'll need to give the user the option to switch between languages on the fly without going to the browser's preferences....makes sense.
Questions:
1- Where to store user language preference?
Some suggest using a Session variable to store the language preference across the pages. But shouldn't you be storing this for future uses?
Some suggest using a Cookie, but this will be browser specific and/or a machine specific.
IMHO, it would be perfect if the site can remember a user preference regardless of the browser or machine he uses to sign in. That's why storing it in the database might sound like the best option, and I use ASP.NET Profile for that.
Btw, Profile usage is not as easy to use in a Web-Application project as it is in a WebSite project, as no custom class gets created to hold your profile properties defined in the web.config. Please check the code below to know how to manage Profile properties in a Web-Application.
2- How to switch it on the fly?
Simply by setting 2 properties: CurrentThread.CurrentUICulture & CurrentThread.CurrentCulture
3- But where to set them?
Basic answer is to override the InitializeCulture() method on each and every page in your application....not the smartest thing to do.
Another suggestion is to let all your pages inherit from a BasePage class which in turn inherits from the Page class, and there you override the InitializeCulture() method.
The problem is that InitializeCulture() method is never called on cached pages. Ref: InitializeCulture and caching don't mix
I'm using a MasterPage, can I do this in the code behind of the MasterPage.... The answer is a striking NO. The MasterPage doesn't inherit from the Page class, and it has no idea what InitializeCulture() is.
If we want a global location to set the culture, then why not using the Global.asax class to set the culture in one of the events declared there.
That's why many people who don't like to use the BasePage approach sugests using the
Application_BeginRequest() as a good location for this code.
Good point, only that the Profile won't be read at this point, yet... so what's now.
The answer is: Application_PreRequestHandlerExecute(). It's not there by default, you should add it yourself.
Code example (might have a room for refactoring):
Here I use a couple of buttons on the master page for switching the language on the fly, you may use whatever approach you want to use.
public partial class Main : System.Web.UI.MasterPage
{
protected void English_Click(object sender, EventArgs e)
{
SwitchCulture("en-Us");
}
protected void Arabic_Click(object sender, EventArgs e)
{
SwitchCulture("ar-Eg");
}
private void SwitchCulture(string culture)
{
CultureHelper.SaveCulture(culture);
Response.Redirect(Request.Url.AbsolutePath);
}
}
As said before thie event is not there by default when you add the Global class to your application.
public class Global : System.Web.HttpApplication
{
protected void Application_PreRequestHandlerExecute(Object sender, EventArgs e)
{
CultureHelper.SetCulture();
}
}
I created a class to encapsulate the culture manipulation.
public class CultureHelper
{
public static void SaveCulture(string culture)
{
HttpContext.Current.Profile.SetPropertyValue("Culture", culture);
}
public static void SetCulture()
{
var culture = GetCulture();
if(string.IsNullOrEmpty(culture))
return;
var cultureInfo = new CultureInfo(culture);
Thread.CurrentThread.CurrentUICulture = cultureInfo;
Thread.CurrentThread.CurrentCulture = cultureInfo;
}
private static string GetCulture()
{
var culture = string.Empty;
if (HttpContext.Current.Profile != null)
{
culture = (string) HttpContext.Current.Profile.GetPropertyValue("Culture");
}
return culture;
}
And don't forget the Profile property definition in the web.config
[system.web]
[anonymousIdentification enabled="true"/]
[profile]
[properties]
[add name="Culture" allowAnonymous="true" defaultValue="Auto" type="string"/]
[/properties]
[/profile]
...
[/system.web]
Tuesday, February 17, 2009
"Agile Simplified" is being showcased
Most probably this happens for all new posted presentations, each might get showcased in its own category, and their so called editorial team might just be an electronic one :) I mean automatic selection.
So although it shouldn't mean any extra credit, it won't hurt to brag about it :) :)
Check my previous blog post about this presentation.
Saturday, February 14, 2009
An Introduction to Agile Software Development
The presentation took place at Microsoft Egypt Premises.
The slides are available here, where you can view it online (full screen if you want).
Also downloading is enabled.
It's worth mentioning that Imagine Cup World Finals will be held in Egypt.
Finally, I'd like to wish all the teams the best of luck, in the competition.
Monday, July 7, 2008
Software Development Meme
Frans Bouma has passed this torch to me. Seems like a good opportunity to get back to blogging after some busy months of work load.
Here we go:
How old were you when you first started programming?
14 years old, that's when I bought a Yamaha MSX AX-170 (Arabized and sold by Sakhr).
I bought it for gaming, but then I discovered you can do some tricks with it by writing some lines of code called Basic J
How did you get started in programming?
There was a Basic book that came with the MSX unit, I used to try out some examples from the book and try to innovate on my own. Later on when I was at high school I was convinced by a relative of mine (Hossam Ali) who was few years older and was studying Computer Engineering and he was working as a programmer at the same time.
What was your first language?
MSX basic, but just for some silly trials, then it was Turbo C at college time.
What was the first real program you wrote?
It depends on how you define "real". Do you mean a commercial program or one that you can proudly share with others. I'll assume the later one.
In fact I can't remember which was first, but either a game to shoot invading space ships before they hit the earth, or implementing Ferrari's method to solve the Quartic equation.
What languages have you used since you started programming?
I list those used in my professional career: SQL, VC++6, VB6, C#, VB.NET, JavaScript, VBScript
What was your first professional programming gig?
A document management system called TAM Pro, I started working on it as soon as I joined Raya Software, just after my graduation back in 2000, and I quit working on it when I left the company at 2005 J
If you knew then what you know now, would you have started programming?
Definitely, yes
If there is one thing you learned along the way that you would tell new developers, what would it be?
Always be open to new ideas and to change in general. Keep yourself up-to-date with what's going on the market. Try to acquire a new experience in each project.
If you find yourself doing a repetitive work (donkey work), then most probably you are the one to blame. Either reuse or auto-generate (as in code generation).
A pop-quiz if you are a .NET developer: Have you ever heard about LLBLGen Pro?
What's the most fun you've ever had … programming?
Seeing your code being used in production; serving others as a useful tool.
So who's next?
I was going to name Frans Bouma, I've already forgotten he was the one who sent it to me.
- Hosam Ali
- Mohamed Nar
- Sami Samir
- Mourad Askar
- Hazem Tourab
- Bernard Savonet
Tuesday, October 30, 2007
All about ASP.NET 2.0 Security
It's an old post but worth referencing.
It's a never ending ASP.NET 2.0 river of resources, it contains loads of links and references of resources for:
Authorization & Authentication models.
Membership, Roles, Profiles, Personalization & Providers.
Security guidelines and how-to's.
Sunday, July 8, 2007
ASP.NET Session State Brief
Introduction
HTTP is a stateless protocol, meaning that a Web server treats each HTTP request for a page as an independent request; the server retains no knowledge of variable values used during previous requests.
What's a Session?
A session is a time limited, user (browser) specific, logical connection to a web application.
In other words, a server may treat subsequent requests, made from a specific browser/user, to web pages of the same web application, as logically placed under the same umbrella (session).
This way user specific variables or properly called Session specific variables can be stored somewhere, to be available for subsequent requests.
How requests can be identified to belong to a specific session?
When a user starts a new session, or the browser sends the first request to the web application, ASP.NET starts a new session and the SessionID for that session is sent to the browser with the response.
Then the ASP.NET would expect the SessionID to be sent back from the browser in the subsequent requests, to tie them all under the same session.
A session is considered active as long as requests continue to be made with the same SessionID value. If the time between requests for a particular session exceeds the specified time-out value in minutes, then the session is considered expired. Requests made with an expired SessionID value result in a new session being started.
How is the SessionID maintained?
That's configurable in the web application, Session ID values are transmitted between the browser and the Web server in a cookie, or in the URL if cookieless sessions are specified, as shown in the following example.
http://www.anysite.com/s(lit3py55t21z5v55vlm25s55)/orderform.aspx
For the first option, it won't work if the user disables cookies in his browser.
For the second option, session will be lost if the user re-writes the URL, removing the SessionID.
Where is the Session State stored?
That's configurable in the web application too.
If enabled, Session State or Session Specific variables can be stored in the following locations:
- InProc: stores values in the memory of the ASP.NET worker process. It offers the fastest access to these values. However, the session data is lost when the ASP.NET worker process recycles or the IIS is restarted.
It's not appropriate for Server Farms, where more than one web server is used, since subsequent requests can be directed to different servers.
- StateServer: uses a stand-alone Microsoft Windows service (aspnet_state.exe) to store serialized session variables. This service may run on another machine, thus be shared among multiple web servers in a web farm.
This is somehow slower than the InProc mode, due to serialization and deserialization. Especially if run on a separate machine.
- SQLServer: although this is the slowest solution of all, this is used for highest reliability, since a failover clustering can be used. Serialization is used here as in the StateServer mode.
- Custom: stores session state data using a custom session state store provider. You must specify the type of the session state store provider using the providers sub-element of the sessionState configuration element. See Implementing a Session-State Store Provider for more details.
For Out-Of-Proc options (anything but the InProc):
- Make sure session variables are serializable. See KB 312112 for details.
- Using a web farm, the Application Path of the website (For example \LM\W3SVC\2) in the IIS Metabase should be identical in all the web servers in the web farm. See KB 325056 for details.
The following is an example of the configuration section written under [system.web] section:
[sessionState mode="InProc" stateConnectionString="tcpip=127.0.0.1:42424" sqlConnectionString="data source=127.0.0.1;user id=[username];password=[strong password]" cookieless="false" timeout="20" /]
More on using the SQL Server option:
To install the session state database on SQL Server, run the Aspnet_regsql.exe tool located in the following folder on your web server:
[systemroot]\Microsoft.NET\Framework\versionNumber
Supply the following information with the command:
-The name of the SQL Server instance, using the -S option.
-The logon credentials for an account that has permission to create a database on SQL Server. Use the -E option to use the currently logged-on user, or use the -U option to specify a user ID along with the -P option to specify a password.
-The -ssadd command-line option to add the session state database
The Aspnet_regsql.exe tool will create a database named ASPState containing stored procedures called from the ASP.NET to save and retrieve session state to and from the database.
Session data itself is stored in the tempdb database by default, which might not be the best option, since tempdb is cleared when the SQL Server restarts.
You can optionally use the -sstype option to change the storage location of session data.
The following are the possible values of the -sstype option:
t data will be stored in the SQL Server tempdb database.
p data will be stored in the ASPState database instead of in the tempdb database.
c Stores session data in a custom database. You must also include the name of the custom database using the -d option.
For example, the following command creates a database named ASPState on a SQL Server instance named "SampleSqlServer" and specifies that session data is also stored in the ASPState database: aspnet_regsql.exe -S SampleSqlServer -E -ssadd -sstype p
P.S. this turned out to be anything but a brief article, isn't it?
References:
.NET Framework Developer's Guide: Session State
ASP.NET: Session State Overview
Nothin' but ASP.NET: ASP.NET Session State
ASP.NET: Session-State Modes
.NET Framework General Reference: sessionState
INFO: ASP.NET State Management Overview
Peter A. Bromberg: ASP.NET Session State FAQ
ASP.NET Technical Articles: Session State Providers
ASP.NET: Securing Session State
Sunday, June 24, 2007
Deploying Crystal Reports - Visual Studio 2005
Now to deploy an application that uses Crystal Reports, the resources on the internet suggests using one of the following methods to deploy the Crystal Reports redistributable package.
1- Using Crystal Reports for .NET Framework 2.0 Windows Installer:
Which I failed to find online, even on the Business Objects online downloads section, but doing a complete search for "CR*.msi" on my hard disk, I managed to find it on the following path:
[Microsoft Visual Studio 8 Install Folder]\SDK\v2.0\BootStrapper\Packages\CrystalReports\CRRedist2005_x86.msi
2- Using Merge Modules:
For which you should create a setup project for your application and in there, you should right-click the setup project node in the Solution Explorer, and select "Add Merge Module", and browse to the following path:
[Windows Root Drive]\Program Files\Common Files\Merge Modules\CrystalReportsRedist2005_x86.msm
This most probably won't be found on your machine!!
I wonder why this merge module wasn't installed with Crystal Reports.
So what you need to do is to go to the Business Objects download site, download this file and put it where it should have been put (in the above path).
Now build your setup project, and Crystal Reports run-times will be installed with your application.
Wednesday, June 13, 2007
ODP.NET & LLBLGen Pro
And both of them work on top of Oracle Client. So an Oracle Client is needed for any of the above providers, which is installed automatically when you install the ODP.NET.
Many .NET developers favors the ODP.NET over the MS provider, especially those with a long track dealing with Oracle database. Because the MS provider has some limitations (lacking the support of some Oracle Native DataTypes, eg. XMLType).
Using LLBLGen Pro with the ODP.NET:
When you build the code generated by LLBLGen Pro on the Development machine, it references the Oracle.DataAccess.dll version found on your machine.
(Oracle.DataAccess.dll is the Oracle Data Provider assembly)
Also it's worth noting that the "SD.LLBLGen.Pro.DQE.OracleX.NET20.dll" the Dynamic Query Engine shipped with LLBLGen Pro, and referenced in the generated code, was built against a specific version of the Oracle.DataAccess.dll (eg. SD.LLBLGen.Pro.DQE.Oracle10g.NET20.dll was built against Oracle.DataAccess.dll v.9.2.0.401 as far as I can remember).
This shouldn't cause any problems in most of the cases, since installing the ODP.NET installs some Publisher Policy files that redirect calls to older versions of the Oracle.DataAccess.dll to the newer installed version.
I said most of the cases because some older versions of the ODP.NET missed those publisher policy files. If this is the case you may include the assembly redirections into your app.config /web.config file, which should look like the following:
[configuration](Replace the square brackets with the triangular ones used for xml.)
[runtime]
[assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"]
[dependentAssembly]
[assemblyIdentity name="Oracle.DataAccess" publicKeyToken="89B483F429C47342"/]
[bindingRedirect oldVersion="9.2.0.20-9.2.0.420" newVersion="9.2.0.700"/]
[/dependentAssembly]
[/assemblyBinding]
[/runtime]
[/configuration]
Note: Assembly redirection can work the other way around, you can re-direct calls to a new version of the Oracel.DataAccess to an older installed version.
ODP.NET Versioning Schema:
It's worth mentioning here that Oracle have changed the ODP.NET / Oracle.DataAccess versioning schema.
Starting with 10.2.0.2, Oracle Data Provider for .NET ships with two sets of binaries; one set for .NET Framework 1.x and another for .NET Framework 2.0.
For example, if the ODP.NET product version number is 10.2.0.2.10, the correspondingODP.NET assembly versions are:
■ .NET Framework 1.x version: 1.102.2.10
■ .NET Framework 2.0 version: 2.102.2.10
Note that the Oracle installer and documentation still refer to the ODP.NET product version number and not the assembly/DLL version number. As with the .NET Framework system libraries, the first digit of the assembly version number indicates the version of the .NET Framework to use with an ODP.NET assembly. Publisher Policy DLL is provided as before so that applications built with older version of ODP.NET are redirected to the newer ODP.NET assembly.
The Problems:
Problems can rise when you deploy your application on a machine with a different version of the ODP.NET, then you might see the following exception:
Could not load file or assembly 'Oracle.DataAccess, Version=x.x.x.x, Culture=neutral, PublicKeyToken=89b483f429c47342' or one of its dependencies. The system cannot find the file specified.
This should be solved by a correct assembly redirection. (From the version you see in the exception to the version already installed).
Another exception you might see is:
The Provider is not compatible with the version of the Oracle Client.
An assembly re-direction should solve this issue, too. This shows up when you have different version of the Oracle.DataAccess.dll in your machine check the Global Assembly Cash (GAC).
Due to older installations or so, while only one of them is corresponding to the latest installed version of the ODP.NET, yet your application references an older one. The first exception won't show up, since your application can find the dll, thanks to the GAC, but it's not the one that should be used.
Just to make sure which ODP.NET version is installed on your machine, check the following registry path HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\ODP.NET
In most of the cases the assembly re-direction are the answers.
In some rare cases after getting rid of the re-directions issue you might see the following exception:
Unable to cast object of type 'Oracle.DataAccess.Client.OracleConnection' to type 'Oracle.DataAccess.Client.OracleConnection'
Pretty weird!!
This can be caused by some calls to the Oracle.DataAccess.dll inside the SD.LLBLGen.Pro.DQE.OracleX.NET20.dll which were not successfully re-directed to the installed version.
To solve this issue you will have to re-build the DQE dll to reference the same version of the Oracle.DataAccess.dll found on your development machine.
Details can be found in this post:
http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=9007&StartAtMessage=0즃
Monday, June 4, 2007
OWA Issue on Vista
If you are using Outlook Web Access (OWA) on a Windows Vista, to access Exchange Server 2000/2003 , you may find yourself unable to edit any e-mail message.
i.e . Not able to write any new e-mails nor reply to any e-mail.
(You will see a small red 'x' instead of the editor area).
The Cause:
Microsoft has removed the DHTML Editing ActiveX Control (the control that enables you to edit nice rich text with html capabilities) from Windows Vista for security reasons.
The Resolution:
Ask your Exchange Admin or whoever is in charge to install the KB911829 patch for the exchange server. This patch installs a new iFrame Editor instead of the ActiveX one.
Monday, May 28, 2007
Real World ASP.NET 2.0 GridView
Matt Dotson has some nice ideas for a Real World GridView:
Bulk Editing
Two Headed & Grouping GridViews
Excel-like Frozen Headers for ASP.NET 2.0
ASP.NET 2.0 Data tutorials
In case you haven't came across these tutorials, here they are:
http://www.asp.net/Learn/DataAccess/
Good Work.
Inserting from the ASP.NET GridView
Here is the tutorial:
http://www.asp.net/Learn/DataAccess/tutorial53vb.aspx?tabid=63
And he has a follow-up post on his blog to handle the case when the GridView has no rows!!
In this case the GridView unlike the old DataGrid won't display the footer nor the header...oops, (they should have gave us the option here) anyway, the workaround is to use the EmptyDataTemplate to put some controls (a DetailsView is a good option), and here are the full details:
http://scottonwriting.net/sowblog/posts/11904.aspx
Tuesday, March 20, 2007
Building ASP.NET 2.0 Web Sites Using Web Standards
http://msdn2.microsoft.com/en-us/library/aa479043.aspx
