November 2007 - Posts

Changes on the authentication service
Sun, Nov 25 2007 22:59

Now that the 3.5 version of the platform is out, it's time to start digging in with Reflector. Since I was experimenting with the authentication service to try to answer a question that was posted on the forums, I couldn't stop noticing that on ASP.NET 3.5 the AuthenticationService is now... a WCF service. Besides that, there are also some other cool things:

This server class has a two static events: Authenticating and CreatingCookie;

  • The first event (Authenticating) is generated during the authentication operation, giving you a chance to perform the authentication yourself (if you do authenticate the user during that event, don't forget to set the AuthenticationIsComplete property of the AuthenticatingEventArgs class that is passed as the EventArgs parameter to the method that is handling the event);
  • The CreatingCookie event is fired when you choose to create a cookie (ie, when you pass true to the client createPersistentCookie - hope I didn't mess up the name of the parameter that the client login method expects :) ). This means that now you can create your own cookie instead of getting the default cookie. As expected, there is a custom property (CookieIsSet)  on the custom EventArgs object (CreatingCookieEventArgs) that gets passed into the  method that handles the event which lets you say if you want the default cookie (or not). Do notice that if you don't handle the event (or don't set the CookieIsSet property) you'll end up getting the default ASP.NET authentication cookie.

So, it seems that there are some new things on the ASP.NET AJAX platform...I'll try to come back with some posts on the next days...

by luisabreu | with no comments
Filed under:
Stop the nonsense: don't put the System.Web.Extensions.dll inside your bin folder
Thu, Nov 22 2007 22:07

First, if you've already installed the last version of the framework, you can relax since it will automatically put the ASP.NET AJAX assembly on the GAC.

Ok, if you're still using ASP.NET 2.0, then keep reading. As we all know, ASP.NET AJAX was introduced as an add-in to the ASP.NET 2.0 platform. During the early CTPs, you used to put the dll inside the bin folder. However, when the 1st beta was released, the behavior changed: the installation package started putting the assembly on the GAC. At the time, many complained since most hosts would only install it after it went RTM.

Since this has happened a long time, I didn't expect to keep seeing people recommending to put the ASP.NET AJAX assembly inside the bin folder of the web app (just to simplify deployment). People, this is not a good idea! If you take a look around, you'll see that many hosting companies will let you run your app in medium trust (which, if you ask me, is a good idea). What this means is that, for instance, you won't get any permissions to use reflection (here's a good reference to see what happens in each trust level). And reflection is needed in certain areas of the ASP.NET AJAX platform. For instance, web service invocation needs reflection to get info about the methods that get added to the JS proxy that is inserted on the page. If you drop the assembly on the GAC (which is done by default by the installation package), the assembly will always run in full trust.

So, if you're putting your ASP.NET AJAX assembly on the bin folder before deploying your app, you're not really simplifying things; instead, you're just being lucky because:

  • your web app hasn't still used any feature that requires reflection. Who knows what will happen in the future when you decide to add a new feature?
  • you're running your web app in full trust. Believe me: this is not also a good idea!

Moral of the story: the next time someone tells you to put the ASP.NET AJAX assembly on the bin folder, just say NO! :)

by luisabreu | with no comments
Filed under:
Making the AuthenticationService.get_isLoggedIn() work correctly
Thu, Nov 22 2007 10:02

[Update: this will only happen if you don't set up the web.config properly. You don't need to do this - ie, call the RegisterStartupScript - if you add the <authenticationService enabled="true" /> to the web.config file]

The ASP.NET AJAX platform has some client services which you can use from your client Javascript code to perform some interesting operations. One of those classes is the Sys.Services._AuthenticationService class. Most guys will use the class to authenticate a user without having to perform a postback (ie, they'll simply call the login method over the "global" Sys.Services. AuthenticationService object that is inserted on the page).

The class has a method (get_isLoggedIn) which should be used for letting you know if the user is authenticated. Unfortunately, the method might not give you the correct answer in all the scenarios because it simply checks the value of the _authenticated field to return a response. Now, If you use the service to login, then everything will work out correctly if you don't navigate to another page. If you do, things won't work as expected because the field isn't updated during page navigation. Here's a small page that reproduces this:

page A:

System.Web.Security.FormsAuthentication.SetAuthCookie("luis", true);
Response.Redirect("Default.aspx" );

The page creates the authentication cookie and performs a response.redirect. If you put the following code on the default.aspx page:

alert( Sys.Services.AuthenticationService.get_isLoggedIn() );
alert("<%= this.User.Identity.IsAuthenticated.ToString() %>") 

You'll get "false, True". What we need to do is to ensure that the _authenticated field is correctly filled during page navigation. Fortunately, we can do that rather easily by injecting a script from the server side, with code that looks like this:

protected override void OnLoad(EventArgs e)
{
     base.OnLoad(e);
     ScriptManager.RegisterStartupScript( this, this.GetType(), "authenticated",
          String.Format("Sys.Services.AuthenticationService._authenticated={0};",
                                      this.User.Identity.IsAuthenticated ? "true" : "false" ),
          true );
}

If your page has UpdatePanels, then don't forget that these rules still apply!

Xaml and Media controls: giving them a new chance
Tue, Nov 20 2007 21:35

A long (long) time ago I've downloaded one of the ASP.NET future CTPS and was really annoyed with the Xaml and Media controls. Why? simple: they injected object tags on the page instead of generating JS code to perform those operations. The problem: you got one of those nasty "click to activate" messages when the page was hosted on IE.

Now that we know that the "click to activate" will be gone, it's time to give these controls a second chance. Dave has already written a cool post on it and he promises to return with more Silverlight posts.

by luisabreu | with no comments
Filed under: ,
Visual Studio 2008 Team Suite is out
Mon, Nov 19 2007 14:51

Go get it while it's hot!

by luisabreu | with no comments
Filed under:
ASP.NET AJAX:Registering your script during a partial postback call
Thu, Nov 15 2007 10:53

By now, everyone knows that you should use the RegisterXXX methods of the ScriptManager class to insert a script block during a partial postback (that is, when you're using ASP.NET AJAX and UpdatePanels). Even though this is "common knowledge", what most don't know is that  using one of those methods and associating  a script block with a page (ie, passing a reference to the page object as the first parameter od a method) might not be enough for inserting the script on the page. Lets run a small example:

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        manager.RegisterAsyncPostBackControl(bt);
    }

    void InsertScript(Object sender, EventArgs e)
    {
        ScriptManager.RegisterStartupScript( this, this.GetType(), "hello", "alert('hello');", true);
    }

</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager runat="server" id="manager" />
        <asp:UpdatePanel runat="server" id="panel" UpdateMode="Conditional">
            <contenttemplate>
                <%= DateTime.Now.ToString() %>
            </contenttemplate>
        </asp:UpdatePanel>       
        <asp:Button runat="server" ID="bt" Text="start partial postback" OnClick="InsertScript"  />
    </form>
</body>
</html>

If you run this code, you won't get the alert message. If you remove the UpdatePanel or if you set its update mode to Always, then it'll start working. Why? well, because in the current version you're only able to insert a script on a page during a partial postback if:

  • there aren't any UpdatePanel controls on a page;
  • you've associated the script with a control placed on an UpdatePanel that is being refreshed;
  • you've associated the control with a page and there exists at least an UpdatePanel that is getting refreshed.

In the previous example, we've associated the script with the page, but notice that the only UpdatePanel that is on the page won't be refreshed since its mode is set to Conditional and the control that started the partial postback isn't registered as trigger nor did we call its Refresh method during the postback. So, if setting the UpdateMode property of the panel to Always is overkill, the only thing I think you can do (that is, if you can't wait for the next version of the platform :) ) is add an empty UpdatePanel to the page and set its Visible property to false (and that should garantee that your scripts are always injected on the page).

by luisabreu | 6 comment(s)
Filed under:
ASPInsider
Tue, Nov 13 2007 23:56

It seems that after a long and "interesting" process :) I've been invited to join the ASPInsider group. It should be lots of fun! Thanks guys.

by luisabreu | 1 comment(s)
Filed under:
Click to activate gone from IE
Mon, Nov 12 2007 23:31

Hurray! Pete has just announced (like in "a few days ago":) )this on his blog. Good news for the SL ASP.NET controls I've kept badmouthing in previous posts...

Changing the contents of the UpdateProgress control
Mon, Nov 12 2007 23:15

Today I've answered a question on the ASP.NET AJAX forums that  asked something like this: how do I get a reference to the controls defined inside an UpdatePanel or UpdateProgress controls? The first part is easy: just use the ID of the control. The second is not as easy as it might seem at first. The problem is associated with the way the control isntantiates the template on the PreRender event.

What this means is that you might have to write code similar to this if you want to get a reference to a control placed inside the UpdateProgress in order to change its properties:

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
    void E(Object sender, EventArgs e)
    {
        System.Threading.Thread.Sleep(2000);
    }

    private Boolean update = false;
    void J(Object sender, EventArgs e)
    {
        update = true;
    }

    protected override void  Render(HtmlTextWriter writer)
    {
        if (update)
        {
            Label lbl = (Label) progress.FindControl("lbl");
            lbl.Text = DateTime.Now.ToString();
        }
        base.Render(writer);
    }

</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
         <asp:ScriptManager ID="ScriptManager1" runat="server" />
         <asp:UpdatePanel runat="server" ID="panel">
            <ContentTemplate>
                <asp:Button runat="server" id="bt" text="partial postback" OnClick="E"/>
            </ContentTemplate>
         </asp:UpdatePanel>
         <asp:Button runat="server" text="full postback" OnClick="J" />
         <asp:UpdateProgress runat="server" ID="progress" AssociatedUpdatePanelID="panel">
            <ProgressTemplate>
                <asp:Label runat="server" id="lbl" />
            </ProgressTemplate>
         </asp:UpdateProgress>
    </form>
</body>
</html>

by luisabreu | with no comments
Filed under:
Getting intellisense in JS code
Sun, Nov 11 2007 22:50

Today, I've noticed an entry on the JScript blog that gave some advice on how to get intellisense for your fields. I just have one thing to say about it: DON'T even think about using it. It's completely wrong. Ok, slowly: it's WRONG. Declaring fields on the prototype object has a different meaning than declaring them on the constructor of the class. This means that I'll have to live without intellisense on my JS classes...

by luisabreu | 2 comment(s)
Filed under:
308 RC Z
Fri, Nov 9 2007 22:26

What do you think about this new concept from Peugeot? I like it (but again, I'm already a fan of the new Audi TT...)

by luisabreu | with no comments
Filed under:
.NET Framework 3.5 namespace poster
Fri, Nov 9 2007 20:34

Brad Abrams has posted a link to a nice looking .NET 3.5 namespace poster.

by luisabreu | with no comments
Filed under:
Where is the Windows Sidebar
Fri, Nov 9 2007 11:24

On the Windows 2008 Server? I've already installed the Desktop Experience pack and I'm able to find the Windows SideShow, but I can't seem to find the Windows Sidebar anywhere...

by luisabreu | with no comments
Filed under:
ASP.NET AJAX forums: reaching the 100 correct answers
Fri, Nov 9 2007 10:59

In these last weeks I've been having some fun on the ASP.NET AJAX forums (don't ask me why but I do really enjoy trying to understand why something doesn't work as expected). Today I've noticed that I've reached the *magical* 100 number and I've decided to put it here to record it for posteriority:) (do notice that there are several guys that have answer many more questions than me, so 100 might seem to be a really small number of answers when you compare that with the other guys)

Untitled

ok, now back to work....

by luisabreu | 1 comment(s)
Filed under:
Making the LinqDataSource control work against an IEnumerable
Wed, Nov 7 2007 22:46

As I've said in previous entries, I'm updating my ASP.NET 2.0 book to the new version. One of the controls that will be added to the platform is the LinqDataSource control. The control will let you perform any LINQ expression against any IEnumerable data source. Scott Guthrie has already a cool post that shows how to use the control over a LINQ to SQL model. What I wanted was to use the control against a collection of objects.

If you've used the control, you know that it requires you to set the ContextTypeName and TableName properties. My initial attempt consisted in building a class which had a method that returned a collection. It didn't work so I tried to get some help from those that know (ie, the ASP.NET team - thanks again for the help guys! You've been amazing in these last months). My mistake was to assume that TableName expected a method (don't ask me why, I just assumed that it had to be a method...). Nop, it really expects a property or field name.

With this new info, I've set up a small test that shows how to use the control without a LINQ to SQL model. Lets start with the simple classes I'm using:

public class Person
{
    private String _name;
    private String _address;

    public string Address
    {
        get { return _address; }
        set { _address = value; }
    }

    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }
}

public class PersonManager
{
    private static readonly List<Person> _people = null;
    static PersonManager ()
    {
        _people = new List<Person>
        {
            new Person{ Name = "Luis", Address="Fx"},
            new Person{ Name = "Luis2", Address="Fx"},
            new Person{ Name = "Luis3", Address="Fx"},
            new Person{ Name = "Luis4", Address="Fx2"}
        };
    }

    public IList<Person> People
    {
        get
        {
            return _people;
        }
    }
}

Now, we'll use the PersonManager class to feed an existing LinqDataSource control:

<asp:LinqDataSource runat="server"
           ID="source"
           ContextTypeName="PersonManager"
           Where="Address==@address"
           TableName="People">
           <WhereParameters>
               <asp:Parameter Name="address" DefaultValue="Fx" />
           </whereParameters>   
</asp:LinqDataSource>

Isn't this cool? I've  even tested the where expression and yes, it's working! Ok, no the "not so cool part": according to the team, insert, update and delete operations require that the ContextTypeName be a LINQ to SQL data context.

Anyway, now I know why this control wasn't called "LinqToSqlDataSource" :)

by luisabreu | 2 comment(s)
Filed under:
PowerShell v2.0 CTP is here
Wed, Nov 7 2007 21:49

When v1.0 was in beta, I used to really love it (and I still do!). The PowerShell blog has just announced that the 2.0 CTP is out. Go get it now :)

by luisabreu | with no comments
Filed under:
Windows Live Writer 2008 available
Wed, Nov 7 2007 21:33

You can find more info about it here.

by luisabreu | with no comments
Filed under:
ListView control: EmptyDataItem vs EmptyItemTemplate
Wed, Nov 7 2007 0:25

The new ListView control has two properties that you might confuse when you start using the control. As you may have guessed by this post, they have different purposes (but they're both templates).

The EmptyDataItem lets you set the aspect of the control when its DataSource property is null )ie, the control will render that template when it has no items to show).

The EmptyItemTemplate is used only when you're using grouping. When you do that, your control will output something like this:

A | B | C
D |E | F

....

In the previous schema, each group has at most 3 elements: each line represents a group and each letter represents an item that the control is showing. Now suppose that in the previous example you only have 5 elements:

A | B | C
D |E | XXX

If you specify a template for the EmptyItemTemplate property, then the control will render the XXX item with the contents you specify in that template.

by luisabreu | with no comments
Filed under:
The var keyword
Mon, Nov 5 2007 12:31

In these last days, I've been looking at LINQ. I'm still not sure if this will help me build applications easily or if the new features introduced on the C# language are making it a lot more complex than it should be (when I make up my mind, I'll let you know :)). Anyway, LINQ brings us some cool things and that's why I'm taking a look at it. before delving into LINQ, we should understand the new features of the C# language that support it. Today I'm going to write about the var keyword (there are already several posts on this, so I'm only writing this to use as a future reference).

Basically, the var keyword was introduced to let you declare a variable without defining its type explicitly. The C# 3.0 specification states that this type of declaration is known as implicitly typed local variables. Lets take a look at a quick example:

var myInt = 10;
Console.WriteLine(myInt.GetType().FullName);

If you run the previous sample, you should see System.Int32. So, what's happening here? Well, when you build your app, the C# compiler will infer the type of the variable from the initialization expression you're written. It's really important to keep this in mind: the type of the variable depends on how the initialization expression is parsed by the compiler. Here's another example:

var myInt = 10.4;
Console.WriteLine(myInt.GetType().FullName);

What do you expect to see when you run this program? will you get a Single (float) or a Double (double)? You'll get a double because that's what the literal 10.4 is. If you want to get a single you need to use the f prefix (var myInt = 10.4f;).

From these examples you can already deduce that you cannot use the var keyword without an initialization expression (if you do that, how will the compiler infer the type of the variable?). Other things to keep in mind are (taken from the C# specs):

  • the initializer must be an expression and cannot be an object or collection initializer;
  • cannot use the null value;
  • if the initialization expression contains multiple declarators, they must all be of the same type.

Lets look at same examples:

var myInt = null;

This won't compile because the compiler cannot infer the type of a variable from null.

var myIntArray = {1, 2,3 };

This goes against point 1 of the previous list. you need to indicate the type of array like this:

var myIntArray = new Int32[] {1, 2,3 };

Not really that complicated, right?

A couple more of observations:

  • I've been saying that var is keyword, but it's nor really a keyword in the traditional sense (when you think about keywords, you normally think about terms with predefined meaning that cannot be reused in a program - for instance, you can not create a variable named class). You can, for instance, introduce a new class called var . If you do that, when you write var myVariable you're really creating a new variable of type var  (not an implicitly typed local variable);
  • you can use var in foreach cicles and using instructions since the compiler will be able to infer the type of the variable you're creating.

Well, as you can see from this short presentation, implicitly typed local variables are simple and they really depend on the compiler (not on the CLR). I still haven't used this new feature on my C# 3.0 projects. But again, I still haven't written any LINQ aware application...

by luisabreu | 2 comment(s)
Filed under:
Failed requests tracing in IIS 7
Fri, Nov 2 2007 14:01

In these last days I've been rather busy porting my old ASP.NET 2.0 samples to the new version of the platform. Until now, I believe that the greatest things that we will have in the new version are IIS related! Today I was playing with the Failed Request Tracing service of IIS 7. It's a really cool new service which will really help you if you like to use tracing to see what's going on your pages or site. There's already a good article on how to enable and configure this new service, so I won't really go into it here.

What I've also found is that there is a new health monitoring provider which will automatically convert an event into a tracing message that is going to be sent to this new IIS service. I'm talking about the IisTraceWebEventProvider class. Using it is really simple: you just need to add it to the providers section in your config file and create a rule that uses it. Here's what I did to test this new health monitoring provider:

<healthMonitoring enabled="true">
  <rules>               
    <add name="My rule" eventName="All Errors" provider="IISProvider" profile="Critical" />
  </rules>
  <providers>
    <add name="IISProvider" type="System.Web.Management.IisTraceWebEventProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
  </providers>
</healthMonitoring>
<authentication mode="Windows" />

What I'm saying here is that I've got a new provider (which I've named IISProvider) and I've create a new rule (called My rule) which  ties the "All Errors" events (events of type WebBaseErrorEvent) to IISProvider provider (you can think of rules as being the "glue" that associates an event with a provider - btw, you can associate an even with several providers by adding a new rule for each provider).

Then, to see if everything was working out smoothly, I've set up a page which generates an error. The simplest thing I could think of was this:

<%@ Page Language="C#" %>
<%@ Import namespace="System.Reflection"%>
<%@ Import namespace="System.Web.Management"%>
<%@ Import Namespace="LivroASP" %>
<script runat="server">
    void ProcessClick( object sender, EventArgs args )
    {

        Int32 a = 0;
        Int32 b = 10/a; //generates exception
    }
</script>
<html>
<head id="Head1" runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
        <h3>Utilização de um evento personalizado</h3>   
        <small>Esta página demonstra a utilização de um evento personalizado (necessário remover comentários da secção
        healthMonitoring do web.config</small><br />
        <asp:Button runat="server" id="bt" Text="Evento" OnClick="ProcessClick" />
    </form>
</body>
</html>

 

If you run this page (and you have enabled Failed Request Tracing in IIS), then you should see the a warning entry with the error exception on the log file for the Failed Request Tracing service (notice that if you disable Health Monitoring, you'll still get the MODULE_SET_RESPONSE_ERROR_STATUS entry, but you won't get the RequestErrorEvent entry associated with the Health Monitoring service).

by luisabreu | with no comments
Filed under: