January 2008 - Posts

The blog is (moving) reopening :)
Tue, Jan 29 2008 21:45

to the weblogs.asp.net site. Since most of the content I write is web related, I think it makes sense to start writing my posts over there. I'm not going to close this blog since I'm not migrating my old posts.

If you want to keep following my blog and you're consuming my feedburner feed, then you don't need to do anything since I've already updated the feed to point to that blog. If you prefer to check the online version of the site, then you can check it here.

I couldn't end this post without thanking the guys at msmvps.com for hosting my blog and keeping everything working out smoothly on these last years.

Since things didn't really go well with my move to the weblogs.asp.net site I'm reopening this blog. Until the end of the day I'll port my entries on the weblogs.asp.net site to this site (so I'm sorry if this will duplicate the posts on your RSS reader). If you're already consuming my feed from feedburner, you won't need to do anything.

Making NHibernate play nice with TransactionScope
Tue, Jan 29 2008 11:26

Another day with NHibernate, one more thing learnt...Ok, so if you're going to use NH and you want it to play nice with the TransactionScope class introduced by .NET 2.0 and you're using a provider which is capable on enlisting in an existing transaction (ex.: you're connecting to SQL Server), then the only thing you need to remember is to call session.Flush before committing the trnasaction (ie, before calling the Complete method over the TransactionScope instance you're using).

This is really important if you've got an entity which holds a collection of components. Fortunately for me, I've ended up finding this post by Oren which helped me putting it to work. You see, besides being an NH rookie, I was under the impression that if the session is associated with a transaction, then committing the transaction would automatically call Flush over that session's instance. This seems to be true when you use an NH ITransaction, but it seems like it simply doesn't work when you have component collections and you're using TransactionScopes.

by luisabreu | with no comments
Filed under:
More NHibernate gotchas
Mon, Jan 28 2008 23:29

Today I've just wasted a couple of hours trying to get something to make NHibernate persist an custom object graph. My scenario wasn't really complicated and looked something like this:

root object --->Item(s)---->Components

My root is a reference object which has a collection of other reference types (Item). Now, the fun part: I was under the impression that adding a bag to my root object and putting a <one-to-many> element inside it was enough for persisting the root and the associated collection. oh well, not so. If you try to do that you'll have to configure your FK so that it accepts nulls (and in this case, it will stop being a FK, right?). It seems like the easiest way is to have a bi-directional association. When you do this, NH will automatically persist the object graph correctly (many thanks to marcal for confirming this on the NH forums).

Ok, after solving this, then another problem popped up: after running some tests, I've noticed that the component collection owned by the item object wasn't being persisted. WTF? why? After asking in the forums, I've ended up recalling an old post that talked about some problems regarding WCF and collection serialization. And so I decided to try it out and guess what? it worked. So, if  you want to pass collections through WCF services, you should take a look at this post.

by luisabreu | with no comments
Filed under:
Application Services III: implementing a win forms credential provider
Sun, Jan 27 2008 23:20

In the last post on the series we've seen how we can use the new ClientFormsAuthenticationMembershipProvider to authenticate a user. Today we're going to see how we can implement the IClientFormsAuthenticationCredentialsProvider in order to create or own windows forms login form. The IClientFormsAuthenticationCredentialsProvider interface has only one method: GetCredentials. This method returns an instance of the ClientFormsAuthenticationCredentials which is responsible for keeping the login information that is going to be validated (ie, it will have to be filled with the username, password and the remember me field).

The idea here is that you should build a  class that implements the interface. This class will be responsible for getting the necessary data and packaging it into an instance of the ClientFormsAuthenticationCredentials. The recommended way of doing this is to create a new form which has the necessary windows forms' controls for getting the necessary data and implements the previous interface.

Ok, now that we know the theory, lets see how easy it is. Suppose that we've already created a new Form (called Login) which has two textboxes (txtUsername and txtPassword). I could also have added a remember me checkbox, but I've decided to always ask for the credentials during a login operation. This is what I've got:

public partial class Login : Form, IClientFormsAuthenticationCredentialsProvider
{
        public Login()
        {
            InitializeComponent();
        }

        private String a = "";

        public ClientFormsAuthenticationCredentials GetCredentials()
        {
            if( this.ShowDialog() == DialogResult.OK)
            {
                return new ClientFormsAuthenticationCredentials(txtUsername.Text, txtPassword.Text, false);
            }
            return null;
        }

}

The code might be a little different from what you'd expect:

  • the form is responsible for showing itself to the user. You may be used to creating a new form and then calling ShowDialog over that instance. That would have worked here too, but you'd have to write additional code so that you could get the values from the textboxes. This approach is much more simple and involves writing less code (that makes it a clear winner, right :) );
  • If the user doesn't hit the OK, I just return null. This will automatically cancel the current login process.

By now you may be thinking on how you configure your windows forms app to use this new class. First, you need to setup the provider on the app.config file so that it knows that your app has a credentials provider. To do this, we need to setup the credentialsProvider attribute when we add the provider:

<membership defaultProvider="ClientAuthenticationMembershipProvider">
      <providers>
        <add name="ClientAuthenticationMembershipProvider"
             type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
             serviceUri="http://saturn/login/Authentication_JSON_AppService.axd"
             credentialsProvider="login.Login, login" />
      </providers>
    </membership>

Now, to automatically get the credentials provider instantiated you only need to call the Membership.ValidateUser but this time you need to pass empty strings for both the username and password parameters:

static class Program
{
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

           if(! Membership.ValidateUser("", "") )
            {
                return;
            }
            Application.Run(new Form1());
        }
}

If you run the previous code (I'm assuming that you've already set up the server side as explained before), you'll automatically get the login dialog when the ValidateUser method is called. As a bonus, you'll see that you'll have 3 chances for getting the introducing the correct credentials. If you miss those three attempts and have similar code to the one I've show above, the application will be automatically terminated (it won't run the main form).

What could have been a cool feature ended up being a "wanna be" cool feature. Unfortunately, you cannot setup the number of retries. It's simply hard coded to three, as you can see by looking at the ValidateUserCore method with .NET Reflector. Now, I can tell you that I've tried understanding this, but I simply didn't found any good explanation for this behavior. After all, how hard would it be to get the number of retries from an attribute that would be setup on the app.config file???

Anyway, there are still one or two things to talk about these providers, but I'll leave them for a future post.

by luisabreu | 2 comment(s)
Filed under:
Application services II: configuring the client
Sat, Jan 26 2008 0:25

In the first post of the series, we've configured a web app so that we can use the new application services from a client desktop app. Today we'll see how a windows forms (or other type of client desktop application) can consume those services. After creating a Windows Forms app, we need to start by adding references to the System.Web and System.Web.Extensions assemblies.

We need both because the desktop app will reuse the provider pattern (introduced by ASP.NET 2.0) to get the necessary info from the server side. What this means is that we'll need to set up the providers in the windows forms app with code similar to this one:

<system.web>
   <membership defaultProvider="ClientAuthenticationMembershipProvider">
     <providers>
       <add name="ClientAuthenticationMembershipProvider"
            type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            serviceUri="
http://saturn/login/Authentication_JSON_AppService.axd" />
     </providers>
   </membership>
   <roleManager defaultProvider="ClientRoleProvider" enabled="true">
     <providers>
      <add
           name="ClientRoleProvider"
           type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
           serviceUri="
http://saturn/login/Role_JSON_AppService.axd" />
     </providers>
   </roleManager>
</system.web>

If you're an ASP.NET developer you'll probably recognize the previous code and you'll know that it's adding two providers (one for membership and another for roles). Now, what might be strange is the type of these providers...Both of them were introduced in the latest version of the platform (take a look at the System.Web.ClientServices.Providers namespace on the System.Web.Extensions assembly) and they don't fully implement the provider interface specified by each kind of provider. For instance, the ClientFormsAuthenticationMembershipProvider won't delete or create users...In other words, these providers will only let you perform some of operations that you'd normally expect to see in a provider of each type. If you want to get a full list of the methods that each provider implements, then you'll have to go through .NET Reflector.

Now that everything is set up, we can move on and see how easy it is to validate a user. Since both providers were setup as the default providers, then we can reuse our beloved Membership and Roles classes. Let's start with authentication... If you have a login form, then you can authenticate a user by writing code similar to this:

Boolean isValid = Membership.Validate( username.Text, password.Text );

Yes, we're talking about a Windows App here :) When the previous line is executed, the ClientFormsAuthenticationMembershipProvider will call our authentication WCF service (that's why this provider expects a serviceUri attribute) which was previously configured on the server side and it will automatically set the current principal property of the current thread (ie, the Thread.CurrentPrincipal property) if the credentials are correct. If you want, after authenticating the user, you can also check if a user belongs to a specific role by calling the Roles.IsUserInRole or, if you prefer, by calling the CurrentPrincipal.IsInRole method. Now, if you think that you can use the 1st option to see if  user X belongs to a role Y, then you're wrong. Unfortunately, you'll only be able to get info about the roles to which the current authenticated user has been associated (if you ask me, this sucks). In fact, you'll quickly see that this is the only thing you can do  with this provider. period.

There are still some more cool things to talk about these new services, but I'll leave them for the next posts...

by luisabreu | with no comments
Filed under:
Are you working with paths?
Wed, Jan 23 2008 21:54

I believe that everyone has had to (at least once) write code that needs to work with paths. How many of us have gone into writing something like this:

String basePath = "c:\\myPath";
String fileName  = "myfile.doc";
String completeFilePath = basePath + "\\" + "myfile.doc";

That was the best possible scenario. How many times did you had to write code to check if the basePath ended with the necessary \ char before adding one? Have you been there? (I believe that everyone has done written code like this at least once!) Are you still doing that? NO. Ok. You can stop reading :)

If you're still reading, then you still haven't heard of the Path and VirtualPathUtility utility classes. Whenever you need to work with paths, do use these classes. Both of them have several cool methods which will help you getting your paths right. For instance, getting the complete path in the previous example could be done like this:

String basePath = "c:\\myPath";
String fileName  = "myfile.doc";
String completeFilePath = Path.Combine(basePath, filename);

You may be wondering why I have decided to write about this topic. Well, You might not believe me, but there are still lots of guys out there that haven't heard about these classes. Even worst, I've just finished reading an article which works with paths and uses the string concatenation approach for getting a file name...

by luisabreu | with no comments
Filed under: ,
Application services I: configuring the server
Wed, Jan 23 2008 21:39

The latest version of ASP.NET introduced several new classes (defined on the System,Web.ApplicationServices, System.Web.ClientServices and System,Web.ClientServices.Providers namespace) which you can use in client apps for using the well known ASP.NET membership, roles and profiles services. Currently, you have two options for authentication: Windows or Forms. As you'd expect, using either of these options will end up setting the Thread.CurrentPrincipal property on your client app (more info about that in future posts).

Today I'm only talking about the necessary steps for setting up your server for using these new services. Since the most complete example uses forms based authentication, that is what we'll use in the series of posts. The first thing you need to do is to create a new 3.5 Web Application. By doing that you'll automatically get some of the necessary entries for using the new ASP.NET 3.5 services. The only thing left is activating the services. Fortunately, this will only require adding a few entries to the web.config file:

<system.web.extensions>
        <scripting>
            <webServices>
                <authenticationService enabled="true"/>
                <profileService enabled="true"/>
                <roleService enabled="true"/>
            </webServices>
        </scripting>
    </system.web.extensions>

In the previous snippet, we activated the three services. Btw, you should only activate the ones you'll need. So, if you're using only authentication, then there's no need for enabling the roles and the profiles services.

Internally, all the services are WCF services which we're already using when we use the client AJAX services. I've already written some posts about them on the past. So, if you're interested in getting more info, you can search the blog or go through the several good resources that are available on the Internet.

As you can see, configuring the server for letting desktop apps use these ASP.NET services is really easy. In the next post, we'll see what is needed for calling these services from the client app.

by luisabreu | with no comments
Filed under:
Syndication and WCF
Wed, Jan 16 2008 15:16

The latest release of .NET has added several interesting new things. One of those is support for Syndication. The System.ServiceModel.Web assembly has several classes that you can use to expose an ATOM or RSS feed. There's already a cool article on how to achieve this  which has been published on MSDN, so I'm not going to bother you with the details (you can check the code online, but don't download it because it's not updated; instead, browse the online version). The only thing I'd like to add to what is presented on the article is how to make Firefox interpret the RSS generated as RSS (instead of interpreting it like XML).

The problem with FF is that it will only consider the XML to be RSS feed if it has all the mandatory elements. If you're like me, you're probably going to go through all the public properties of the SyndicationFeed object and you'll set those that make sense. Unfortunately, there really isn't any called link (though there's a Links collection property) so I didn't set up that element from my code (and <link> is one of the mandatory channel elements! - ok, my fault. Should have read the specs to see which items were mandatory...).  And that's why  I lost almost one hour trying to understand why FF wasn't applying its default XSLT stylesheet to my RSS content. I could see the XML, but then I got that awful message that said that there wasn't any stylesheet file applied to my XML document. In fact, it looks like I wasn't the only one that forgot to define the RSS link element: if you try to run the code presented on the sample, you'll see something like this:

Untitled

The only thing you need to fix the code is to add a link element to the feed, which can be done with code that looks like this:

feed.Links.Add(SyndicationLink.CreateAlternateLink(new Uri("put a valid URI here")));

where feed is a reference to a SyndicationFeed object.

Now, if I only could make it add global namespaces, then I'd really be a happy man! (ok, You can add namespaces to the <channel> element, but what I want is to add those declarations on the top <rss> element)

by luisabreu | 1 comment(s)
Filed under: ,
Are you trying to reduce your lock contention?
Mon, Jan 7 2008 23:48

Michael Suess has a great blog on parallel programming and concurrency. Even though this post has already got some months, I still recommend it to everyone that wants to improve their knowledge on lock contention reduction.

by luisabreu | with no comments
Filed under: ,
ASP.NET AJAX: generating the proxy's JS code on the fly
Mon, Jan 7 2008 23:45

Before talking about the ProxyGenerator class, I'll have to add one more observations on the previous posts on the new role service: for the code I've shown to work you do need to have an authenticated user. The easiest way to see the previous code working is just to create a new login page which uses the FormsAuthentication class to authenticate the user and then redirect to the page that contained the code presented on the previous posts.

Now, lets go on and see how to generate the JS code for a web service proxy on the fly. If you fire up Reflector and navigate to the System.Web.Script.Services namespace you'll find  a class called ProxyGenerator. The class exposes a single method: GetClientProxyType. It expects to receive a type (the type of the service you're building a proxy to access), a path (to the service file) and a boolean (which lets you specify if you want it to generate debug or release code - true means debug code). Lets build a simple page that reuses the custom role WCF service (even though it was build to be used with the Role client service, nothing prevents you from injecting it on a page and calling its methods through the generated client proxy):

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
    <script type="text/javascript">
        function printRoles() {
            la.net.tests.CustomRoleService.GetRolesForCurrentUser(
                    function(res){
                        alert(res);
                    } );
        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager runat="server" ID="manager" />
        <input type="button" value="print roles" onclick="printRoles()" />
    </div>
    </form>
</body>
</html>

As you can see, we're not adding a web service reference to the ScriptManager control. In this case, we're injecting the proxy by using the ProxyGenerator class, as you can see in the following snippet:

public partial class Default2 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        String serviceJS = ProxyGenerator.GetClientProxyScript(
            typeof (CustomRoleService), "CustomRoleService.svc", false);
        ClientScript.RegisterStartupScript(
            typeof(Default2), "service", serviceJS, true);
    }
}

As you can see, we're using an instance of the ClientScriptManager to insert the JS proxy on the page (do notice that if you need to insert JS code during partial postbacks, you should use the static RegisterXXX methods available on the ScriptManager class). If you're curious about the difference in the JS code generated when you toggle the debug parameter, then just try it and check the source of the page :)

by luisabreu | 1 comment(s)
Filed under: ,
ASP.NET AJAX: Building a custom role service provider
Sun, Jan 6 2008 22:53

Yesterday I've talked about the new Role service which was introduced by ASP.NET AJAX. Today, I'll keep talking about it and I'll show how easy it is to build a custom role service that is responsible for feeding the client role classes. After enabling the role service, the first thing you need to do is create a new web service which must expose two public methods named GetRolesForCurrentUser and IsCurrentUserInRole. These methods should return the roles for the current user and check if a user is associated with a specific role. Unfortunately, the latest version of the platform did not introduced an interface which would define the contract that would have to be implemented by a custom role service. This means that I had to use Reflector to get the correct name/signature for these methods.

In this case, I'm going to use a WCF service that will return roles Role1 and Role2 only when the current user is luis and it will return Role3 for all other users. It's important to keep in mind that you do need to configure the service so that it uses JSON. The easiest way to accomplish this is by adding a new AJAX-enabled WCF Service (do keep in mind that when you add more than one, you'll get several unnecessary entries on your web.config. This means that you'll have to clean it up...). Here's the code for my service:

[ServiceContract(Namespace = "http://la.net/tests")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class CustomRoleService
{
    // Add [WebGet] attribute to use HTTP GET
    [OperationContract]
    public String[] GetRolesForCurrentUser()
    {
        EnsureServiceAvailable();
        String username = GetCurrentUsername();
        if( String.IsNullOrEmpty(username))
        {
            return new String[0];
        }
        //just making something up
        if( String.Compare("luis", username) == 0)
        {
            return new String[] {"Role1", "Role2"};
        }

        //just return role3
        return new String[] {"Role3"};
    }
    [OperationContract]
    public Boolean IsCurrentUserInRole(String role)
    {
        if( role == null )
        {
            throw new ArgumentNullException("role");
        }
        EnsureServiceAvailable();

        String username = GetCurrentUsername();
        return IsUserInRole(username, role);
    }

    private static Boolean IsUserInRole(String username, String role)
    {
        if( String.IsNullOrEmpty(username))
        {
            return false;
        }
        if( String.Compare(username, "luis") == 0)
        {
            return String.Compare(role, "Role1") == 0 ||
                   String.Compare(role, "Role2") == 0;
        }
        return String.Compare(role, "Role3") == 0;
    }

    private static String GetCurrentUsername()
    {
        IPrincipal user = GetCurrentUser();
        return user != null && user.Identity != null ? user.Identity.Name : "";
    }

    private static IPrincipal GetCurrentUser()
    {
        if(HttpContext.Current == null )
        {
            return Thread.CurrentPrincipal;
        }
        return HttpContext.Current.User;
    }

    private static void EnsureServiceAvailable()
    {
        if( !IsRoleServiceEnabled())
        {
            throw new InvalidOperationException();
        }
    }

    private static Boolean? _roleService;
    private static Boolean IsRoleServiceEnabled()
    {
        if( !_roleService.HasValue )
        {
            ScriptingRoleServiceSection section = (ScriptingRoleServiceSection)
                    WebConfigurationManager.GetWebApplicationSection("system.web.extensions/scripting/webServices/roleService");
            _roleService = section.Enabled;
        }
        return _roleService.Value;
    }
}

As you can see, you should always start by checking if the service is enabled. After doing that, you need to get the current logged in user. In this case, we start by checking the current HttpContext: If it's null, we'll just use the principal associated with the current thread (this is the same approach which is taken by the default WCF service). The rest of the code is just boilerplate code needed for guaranteeing that the previous conditions are enforced (ie, that user luis is associated with roles Role1 and Role2 and that all the other users are associated with Role3).

The next snippet shows how to use our service on an ASP.NET AJAX page:

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
    <script type="text/javascript">
       function printRoles(){
            Sys.Services.RoleService.load(
                function(){
                    alert( Sys.Services.RoleService.get_roles() )
                }
            );
        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
       <asp:ScriptManager runat="server" ID="manager">
            <RoleService LoadRoles="false" Path="CustomRoleService.svc" />
        </asp:ScriptManager>
        <input type="button" value="Get roles" onclick="printRoles()" />
    </div>
    </form>
</body>
</html>

There is one thing you should keep in mind when using a custom role service: you cannot load the roles automatically (ie, you must set the LoadRoles property to false). Not following this guideline means that you'll get an exception at runtime. So, on the client side, you'll always need to call the load method and you'll have to pass it a callback method so that you're notified when the client role service gets an answer from our custom service.

by luisabreu | 1 comment(s)
Filed under: ,
ASP.NET AJAX: the new role service
Sat, Jan 5 2008 23:54

The latest version of the ASP.NET AJAX framework added a new client service which will let you get info about the roles of the current user: I'm talking about the Sys.Services._RoleService. The class exposes two important methods which you might end up using if you need to get info about the roles of the current user:

  • get_roles: returns an array with the roles that have been associated to the current user;
  • isUserInRole: receives a string and returns true if the user is associated with that role.

You'll normally use the global Sys.Services.RoleService object to call these methods. To do that, you'll need to start by activating the service. You can accomplish this by adding the necessary info to the web.config file:

<system.web.extensions>
        <scripting>
            <webServices>
                <roleService enabled="true"/>
            </webServices>
        </scripting>
</system.web.extensions>

After doing this, if you drop a ScriptManager control on a page, you'll automatically get some JS code inserted into the page that configures the client class so that it's able to communicate with the server side in order to retrieve the roles associated with the current user. It's important to note that this client service will only get the roles associated with the current user (which means that you need to have a user logged in to get any meaningful information).

So, if you build a really simple page like this one (I'm just showing the body portion of the page):

<body>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager runat="server" ID="manager">          
        </asp:ScriptManager>
    </div>
    </form>
</body>

and if you load the page on the browser and take a look at its source, you should find a line that looks like this:

Sys.Services._RoleService.DefaultWebServicePath = 'Role_JSON_AppService.axd';

This line is configuring the client class so that it knows which service it should call in the server side to call when you use one of the client methods presented earlier. You can take this to next level and automatically inject the roles associated with the current user on the page by setting the LoadRoles property of the RoleServiceManager to true (exposed by the RoleService property of the ScriptManager element):

<asp:ScriptManager runat="server" ID="manager">
            <RoleService LoadRoles="true" />
</asp:ScriptManager>

When you do this, you'll see that besides setting the path to the web service, the server side will also inject the roles associated with the current user with code similar to this one:

Sys.Services.RoleService._roles = Sys.Serialization.JavaScriptSerializer.deserialize('[\"Role1\"]');

In my previous example, the current user had was associated with only one role (Role1).

Btw, I believe that it's important to mention that you can force the client object to load the roles from the client side by calling the load method. The next page shows a snippet that shows how this can be accomplished:

<body>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager runat="server" id="manager">
            <RoleService LoadRoles="false" />
        </asp:ScriptManager>
        <input type="button" value="Show roles" onclick="printRoles()" />
    </div>
    </form>
    <script type="text/javascript">
        Sys.Application.add_load( handleLoad );
        var _loaded = false;
        function handleLoad(){
            Sys.Services.RoleService.set_defaultLoadCompletedCallback(
                                                function(){
                                                    _loaded = true;
                                                }           
            );
        }
        function printRoles() {
            if(!_loaded){
                Sys.Services.RoleService.load();
                alert( "Loading roles...please try again in a few moments" );
                return;
            }
            var arr = Sys.Services.RoleService.get_roles();
            alert( arr );
        }
    </script>
</body>

In this case, we have a page with a single button that will be responsible for printing the roles associated with the current user. As you can see, we start by checking a global variable which will only be set after the roles associated with the current user have been loaded. we need this flag because when we call the load method, we'll start an async operation and we need to be sure that we've already got the answer from the server side before printing a message to the user.

Before ending the post, there's still time to tell you that you can build your own Role web service: you just need to inform the client object that it should call your method instead of calling the default one. The easiest way to achieve this is to use the RoleServiceManager's Path property (though you can also force this by using the set_path property of the RoleService global object).

by luisabreu | 1 comment(s)
Filed under: ,
Making the DataPager generate a block element
Thu, Jan 3 2008 20:39

I do really like the new paging model introduced with the new ASP.NET 3.5 version. However, there is one thing I don't like: the fact that the DataPager control will always generate an inline element (in this case, a SPAN). So, how can we change this default behavior? Well, I see at least 2 options:

  1. create a new derived control and override the TagKey property. From a conceptual view, I believe this is what should be done
  2. DataPager is a Control, so why not re-use our knowledge on how the parser performs its work and just drop a style attribute that sets its display mode to block (which will be automatically copied to the HTML tag that gets inserted in the page)

As I've said before, in real code I'd probably go with 1 since it feels more natural and I really don't like adding style attributes to my HTML. On the other hand, it's just too damn difficult to resist to something like this:

<asp:DataPager runat="server" ID="myPager"   
    style="clear: both"         
    PageSize="4"
    PagedControlID="myList">
    <Fields>           
        <asp:NumericPagerField ButtonCount="5"                       
                ButtonType="Link"
                RenderNonBreakingSpacesBetweenControls="true" />                     
    </Fields>
</asp:DataPager>

XUnit: NotEqual messes parameter order
Thu, Jan 3 2008 0:39

I've been using XUnit in my last project and I must say that I'm pretty excited with it. Besides letting me throw in the "correct place" (ie, no more ExpectedExceptionAttribute!), I'm really enjoying its simplicity. Unfortunately, there are still some bugs that need to be solved. Today I've just tripped on what I think is a bug: NotEqual messes the parameter order.

If you go through the docs, you'll see that it supports the NotEqual supports the following overloads:

NotEqual<T>(T, T)
NotEqual<T>(T, T, IComparer<T>)
NotEqual<T>(T, T, String)
NotEqual<T>(T, T, IComparer<T>, String)

The blame lies on the version that is bolder:

public static void NotEqual<T>(T expected, T actual, IComparer<T> comparer)
{
    NotEqual<T>(actual, expected, comparer, null);
}

As you can see, the method is changing the order of the parameters and this is messing all mye NotEqual tests where I'm not passing a comparer and a string! Lets hope it gets fixed before the next version is released.
by luisabreu | with no comments
Filed under:
To use this...or not to use this
Wed, Jan 2 2008 14:43

I'll just start by wishing you all a great 2008!

Now, to what used to be a somewhat philosophical question: should you use this to reference a member of your class in your code? Ex: should you write this.CallInstanceMethod() ? Ok, in pre-C# 3.0, I'd say NO. With the current release, I'm saying maybe! Why? Simple: extensions methods. To call them, you must always pass a reference to the type, which means that if you're calling an extension method from a class method (which is a scenario that should be very rare, but which is supported!) you must use the this qualifier or you'll get a compiler error.