January 2006 - Posts
If you are looking for an OR mapper LLBLGen is certainly worth a look. I have used it on projects and it certainly saved me a lot of work. And now there is a book out about how to use LLBLGen Pro making it even easier to get started.
Check out this
blog entry by Frans.
Recommended!
Maurice de Beijer
www.TheProblemSolver.nl
If you where planning to come to and visit Tech-Ed in Amsterdam this
year you might want to revise your plans. Why you might wonder? Well
Microsoft has decided to reschedule and reformat Tech-Ed. Instead of
July in Amsterdam it will be held in Barcelona, Spain in the beginning
of November and it will be focused more on software development
Maurice de Beijer
www.TheProblemSolver.nl
All I had to do was go to Morocco for a week and Rocky comes up with a great
post that just completely mirrors my feeling.
Users don’t care a damn bit about technology!Maurice de Beijer
www.TheProblemSolver.nl
If things are a little quite next week it is because I am off to Morocco for the week [:D] I will have some pictures to share when I get back so stay tuned for more.
Maurice de Beijer
www.TheProblemSolver.nl
Microsoft has announced that there will be a SP3 for Windows XP during 2007 and a SP2 for Windows 2003 server in the second half of this year. See
http://www.microsoft.com/windows/lifecycle/servicepacks.mspx for more details.
While still quite a long way away it is certainly good news. Just make sore you report all bugs you run into so they can get on a fix list. Of course you need to send in any crash reports as well as they are looked at and can be instrumental in prioritizing and fixing bugs.
Maurice de Beijer
www.TheProblemSolver.nl
Working with ASP.NET
and doing anything with threads or thread related info? In that case you might
want to read Rocky's post
about ASP.NET thread switching. He has some nice info to share about some of the
possible traps you might fall into.
Maurice de
Beijer
One cool, and not quite new, feature of Visual Studio 2005 is data binding to your own business objects. Just create a new business object class, add a property, add it to the Data Sources window as an object data source and drag it onto your form. Simple as that and you are good to go.
However as usual there is a gotcha :-(
It throw an exception in a property get or get during the data binding the exception is eaten by the DataBindings object. There are two ways around this, either pass False as the formattingEnabled parameters or add an event handler to the BindingComplete event and check for the Exception property being set.
The first option seems the easiest but isn’t :-( Even if you set the Format type to no formatting in the Formatting and Advanced Binding dialog the formattingEnabled will still be true.
That leaves the second option. To handle the BindingComplete event you need to ass an event handler to all Binding objects on the form. Not difficult once you have a reference to all controls. The following code does just that.
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
For Each control As Control In GetAllControls(Me)
For Each binding As Binding In control.DataBindings
AddHandler binding.BindingComplete, AddressOf BindingCompleteHandler
Next
Next
End Sub
Private Sub BindingCompleteHandler(ByVal sender As Object, ByVal e As BindingCompleteEventArgs)
If e.Exception IsNot Nothing Then
Throw New Exception("Unhandled exception during databinding actions.", e.Exception)
End If
End Sub
Private Function GetAllControls(ByVal container As Control) As List(Of Control)
Dim result As New List(Of Control)
Dim pos As Integer = 0
result.Add(container)
Do While pos < result.Count
For Each control As Control In result(pos).Controls
result.Add(control)
Next
pos += 1
Loop
Return result
End Function
End Class
Public Class SomeData
Private _lastName As String = "Maurice de Beijer"
Public Property LastName() As String
Get
Throw New Exception("Get: " + _lastName)
Return _lastName
End Get
Set(ByVal value As String)
_lastName = value
End Set
End Property
End Class
Maurice de Beijer
www.TheProblemSolver.nl
The My.Settings feature in Visual Basic 2005 is a great way
to store form settings like the forms location so the user gets the form at the
same place as he/she closed it last time. Adding it is real simple. Just go to ApplicationSettings
in the property sheet, expand it, open the combo after location, choose new and
type a name like “FormLocation”. Simple as that and you are done [:)]
However there are some problems [:(]
The property name must be unique, Give two separate forms
the same name and both will be shown at exactly the same position. Makes it
kind of hard to view the info on both [:(]
Adding the ApplicationSettings to a base form class means
that all derived forms use the same property name.
However there is an easy way around it. By using the
My.Settins.SettingsKey you can group related entries together. Adding the following
code to you base form class will ensure that all form classes keep their own
distinct location:
Public Class BaseForm
Private
_setting As New
My.MySettings()
Private Sub BaseForm_FormClosed( _
ByVal
sender As Object,
_
ByVal e
As System.Windows.Forms.FormClosedEventArgs) _
Handles
Me.FormClosed
_setting.Save()
End Sub
Private Sub BaseForm_Load( _
ByVal
sender As System.Object, _
ByVal e
As System.EventArgs) _
Handles
MyBase.Load
_setting.SettingsKey = Me.GetType().FullName
DataBindings.Add(New Binding("Location",
_
_setting, _
"FormLocation",
_
True,
_
DataSourceUpdateMode.OnPropertyChanged))
End Sub
End Class
Maurice de Beijer
www.TheProblemSolver.nl
In my last three blog
entries I showed how to use the ASP.Net membership provider in a Windows
application. I finished with the problem of storing the current user name and
the fact that there is a second overload to the IsUserInRole() function that
only takes a role name. Well it turns out that this function checks for the
current user and uses either the HttpContext.Current.User or the
Threading.Thread.CurrentPrincipal depending on the fact if the application is
hosted. As the Threading.Thread.CurrentPrincipal is the normal way access is
provided to the current user and role information in a windows application this
seems like the natural thing to do.
The System.Web.Security.RolePrincipal class implements the required
IPrincipal interface so this is the class we need to use. To create the
required object we need an IIDentity object to provide the user identity
information. This can be provided using the System.Security.Principal.GenericIdentity
class that implements the IIdentity interface.
Add the following code to the top of the Module1.vb:
Imports System.Security.Principal
Now we can set the principal and check for specific roles using the
following code:
Dim user As MembershipUser =
Membership.GetUser("Maurice")
Dim identity As New GenericIdentity(user.UserName)
Dim principal As New RolePrincipal(identity)
Threading.Thread.CurrentPrincipal = principal
If Roles.IsUserInRole("Developer") Then
Console.WriteLine("Is a
developer.")
Else
Console.WriteLine("Doesn't
write code.")
End If
An alternative way of checking the user and role is:
Console.Write(Threading.Thread.CurrentPrincipal.Identity.Name)
If
Threading.Thread.CurrentPrincipal.IsInRole("Developer") Then
Console.WriteLine(" is a
developer.")
Else
Console.WriteLine(" doesn't
write code.")
End If
So the complete console application now looks like:
Imports System.Security.Principal
Imports System.Web.Security
Module Module1
Sub Main()
' Creating a new user
Dim status As MembershipCreateStatus
Membership.CreateUser( _
"Maurice",
_
"Password_1",
_
"maurice@TheProblemSolver.nl",
_
"Password question",
_
"Password answer",
_
True, _
status)
' Check the status for errors
Console.WriteLine(status.ToString())
' Validate a username/password
If
Membership.ValidateUser("Maurice",
"Password_1")
Then
Console.WriteLine("User
validated.")
Else
Console.WriteLine("User
invalid!")
End If
' Create a new Developer role.
' Add the <roleManager
enabled="true" /> to the app.config for this to work
If Not Roles.RoleExists("Developer") Then
Roles.CreateRole("Developer")
End If
' Add a new role to a known user.
If Not Roles.IsUserInRole("Maurice", "Developer") Then
Roles.AddUserToRole("Maurice",
"Developer")
End If
' Create a second user with only
username/password
' Add the
<membership><providers> element to the app.config first
Dim user As MembershipUser
user = Membership.GetUser("User2")
If user Is Nothing Then
user = Membership.CreateUser("User2",
"p")
Console.WriteLine(user.UserName)
End If
' Check is a specified user is in a
specific role
If Roles.IsUserInRole("Maurice", "Developer") Then
Console.WriteLine("Is a
developer.")
Else
Console.WriteLine("Doesn't
write code.")
End If
' Set the current application
principal information to a known user
Dim identity As GenericIdentity
Dim principal As RolePrincipal
user = Membership.GetUser("Maurice")
identity = New
GenericIdentity(user.UserName)
principal = New
RolePrincipal(identity)
Threading.Thread.CurrentPrincipal = principal
' Check if the current principal is
in a specific role
If Roles.IsUserInRole("Developer") Then
Console.WriteLine("Is a developer.")
Else
Console.WriteLine("Doesn't
write code.")
End If
' Set the current application
principal information to another known user
user = Membership.GetUser("User2")
identity
= New
GenericIdentity(user.UserName)
principal = New
RolePrincipal(identity)
Threading.Thread.CurrentPrincipal = principal
' Use the principal to check for
role information
Console.Write(Threading.Thread.CurrentPrincipal.Identity.Name)
If
Threading.Thread.CurrentPrincipal.IsInRole("Developer") Then
Console.WriteLine(" is a
developer.")
Else
Console.WriteLine(" doesn't
write code.")
End If
Console.ReadLine()
End Sub
End Module
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<roleManager enabled="true" />
<membership
<providers>
<remove name="AspNetSqlMembershipProvider"/>
<add name="AspNetSqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider, System.Web,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="LocalSqlServer"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="false"
applicationName="/"
requiresUniqueEmail="false"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="1"
minRequiredNonalphanumericCharacters="0"
passwordAttemptWindow="10"
passwordStrengthRegularExpression="" />
</providers>
</membership>
</system.web>
</configuration>
Maurice de Beijer
www.TheProblemSolver.nl
In my last two blog
entries I showed how to use the ASP.Net membership provider in a Windows
application. Now that we can add a validate users we might want to start using
roles as well. To work with security roles we need to use the class
System.Web.Security.Roles. This class works pretty much in the same way as the
Membership provider. To add a new role we use the CreateRole() function and to
associate a user with this role we use the AddUserToRole() function. So adding
the Developer role to my previously created user account can be done with the
following code:
Roles.CreateRole("Developer")
Roles.AddUserToRole("Maurice",
"Developer")
However if you try this you will receive an error: “The Role
Manager feature has not been enabled.”. To enable roles we need to add
one more thing to the app.config. Add following line to the <system.web> section:
<roleManager enabled="true" />
Once this is done you are ready to add roles and associate users with
there roles.
Use the following code to check if a user has a specific role:
If Roles.IsUserInRole("Maurice", "Developer") Then
Console.WriteLine("Is a
developer.")
Else
Console.WriteLine("Doesn't
write code.")
End If
Of course this leaves us with a place to store the current user name so
we know which user is logged in when we need to check for a specific role. The
IsUserInRole() function has an additional overload that takes only a single
parameter, the role name. Next time more about how to use this overload.
Maurice de Beijer
www.TheProblemSolver.nl
In my last blog
entry I showed how to use the ASP.Net membership provider in a Windows
application. In the sample I used the Membership.CreateUser() function to
create a new user. However I had to supply quite a bit of information, like
password question and answer, that I would not use in a typical windows
application. Fortunately the Membership.CreateUser() also has an overload with
just the username and password combination.
Dim user As MembershipUser
user = Membership.CreateUser("User2",
"Password")
Console.WriteLine(user.UserName)
However trying to use
this overload results in the error: “The password-answer supplied is
invalid.”. Additionally there might be some other properties you might
like to change, like the requirement for at least one non alphanumeric
character in the password. Even though these settings are exposed as properties
they are read-only so setting them like:
Membership.MinRequiredNonAlphanumericCharacters = 0
Will not work. To change them we need to use the app.config so lets add
one to the application. Add the following to the bottom of the <configuration>
section:
<system.web>
<membership>
<providers>
<remove name="AspNetSqlMembershipProvider"/>
<add name="AspNetSqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider, System.Web,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="LocalSqlServer"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="false"
applicationName="/"
requiresUniqueEmail="false"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="5"
minRequiredPasswordLength="1"
minRequiredNonalphanumericCharacters="0"
passwordAttemptWindow="10"
passwordStrengthRegularExpression="" />
</providers>
</membership>
</system.web>
This removes the default membership provider as defined in the
machine.config and adds the same one but this time with more relaxed password
format and questions settings.
Now run the application again and this time we are allowed to add a
user with just a username and password combination. Because of the relaxed
password requirements even a password of just 1 single letter is accepted.
Stay posted for more.
Maurice de Beijer
www.TheProblemSolver.nl
One of the new features in ASP.Net 2.0 is the membership and role
provider system. This is nicely designed system that allows the developer to
handle the storage of user information pretty much any way he likes, all he has
to do is create the appropriate providers and configure his application to use
these. While this is very powerful there is something else I was much more
interested in and that is the fact that user and role management can be added
to an application without having to do any of the implementation work. Now this
is very convenient if you don’t already have a user database to work with
and something I would like to be able to use in my Windows forms applications
as well as in my web application.
Fortunately this is possible without much work at all! So let’s
create a very small console application with user management.
First create a new Visual Basic console application in Visual Studio
2005. No problem if you prefer C#, all you need to do is translate the
remaining syntax to C#.
Add a reference to the System.Web namespace.
Add a line with “Imports System.Web.Security”
to the top of the Module1.vb.
Now add the following code to the Sub Main()
' Validate a username/password
If Membership.ValidateUser("Maurice", "Password_1") Then
Console.WriteLine("User
validated.")
Else
Console.WriteLine("User
invalid!")
End If
Console.ReadLine()
Go ahead and run the application.
Not surprisingly the application reports that the user is invalid,
after all how it can’t know which users are valid.
Now add the following code to the top of the Sub Main()
' Creating a new user
Dim status As MembershipCreateStatus
Membership.CreateUser( _
"Maurice",
_
"Password_1",
_
"maurice@TheProblemSolver.nl",
_
"Password question",
_
"Password answer",
_
True, _
status)
Console.WriteLine(status.ToString())
Go ahead and run the application again.
If you have never used the membership provider in a Web application you
might me surprised to see this just works, the user is created and is
validated. Run the application again and the creation will return a
DuplicateUserName error but the ValidateUser() still works. How is this
possible as we haven’t done anything to configure the membership provider
or told it which database to use? Well the secret is that the membership provider
checks for, and creates if needed, a new directory under the application
directory named App_Data with a SQL Express database ASPNETDB with the required
structure. This database is then used to store the user information.
Maurice de Beijer
www.TheProblemSolver.nl