Visual Studio support under Vista

by Sander Gerz September 27, 2006 15:32

So the word is out: Visual Studio 2003 wil not be supported with Windows Vista. The community screams uproar! (e.g. here, here and here)

Soma is specifically talking about Visual Studio 2005 Service Pack 1 as the IDE that will be supported, albeit with some issues. But what about Visual Studio 2003 Service Pack 1? In fact, if we take a look at the release notes for Visual Studio 2003's SP1 (yes, I do that sometimes), it clearly states:

Visual Studio .NET 2003 Service Pack 1 Requirements and Specifications
Download size:

160 MB
Available languages

English, Simplified Chinese, Traditional Chinese, Japanese, Korean, French, Italian, German, Spanish, Russian

Supported Operating Systems:

Windows NT 4
Windows 2000
Windows XP
Windows Server 2003
Vista

Supported Framework
.NET Framework 1.1
.NET Framework 1.1 SP1 (recommended Framework level)

See, Vista is supported! So, all we developers need to do is install Service Pack 1 for Visual Studio 2003 and we should be fine under Vista... Right? 

Currently rated 1.5 by 10 people

  • Currently 1.5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET | .NET | .NET | .NET | .NET | .NET | .NET | .NET | .NET | .NET | .NET | .NET

Visual Studio .NET 2003 SP1 Available

by Sander Gerz August 17, 2006 10:14

It took quite a while, but it's there. See: http://blogs.msdn.com/robcaron/archive/2006/08/16/702177.aspx

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET

Get GoogleBot to crash your .NET 2.0 site - update

by Sander Gerz July 11, 2006 09:36

Good news... I hope.

A few days ago, I posted a story on a bug that Nix found in ASP.NET 2.0. According to this thread, the bug was confirmed and they're working on a solution.

Currently rated 2.0 by 3 people

  • Currently 2/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET

Tip/Trick: List Running ASP.NET Worker Processes and Kill/Restart them from the command-line [a better way]

by Sander Gerz July 02, 2006 19:37

Scott Guthrie posts a trick on a quick way to kill a process on your system, or kill and restart an ASP.NET or IIS worker process.  I tried to post a comment on his trick, but the commenting system is not working. So I'll give my opinion here, leaving me with a bit more room to elaborate.

Scott's suggesting that you use taskkill to kill a process running the application pool. That's all nice and neat, but how do you know what process to kill? If you have multiple application pools, you might just kill the wrong one. A much better solution is to use the little known iisapp command. In fact, iisapp is a vb-script located in %winnt%\system32. Run it from the command prompt without parameters, and you get a list of application pools with their associated process ids.

C:\WINDOWS\system32>iisapp
W3WP.exe PID: 3328   AppPoolId: DefaultAppPool
W3WP.exe PID: 232   AppPoolId: AppPool ASPNET2.0

The command IIsApp /a DefaultAppPool /r will recycle the specified application pool. Not only is this a lot easier, it's less error prone, thus safer to use. What if you kill the wrong process? I.e. by mistyping or by the fact that after you listed your processes, the application pool has recycled already.

There are a few other commands that few are aware of. E.g.

issweb /query

This will give you a list of configured websites, their status, port number and hostheader. You can also use iisweb to create, pause, stop, start and delete websites. iisvdir will do something similar for virtual folders.

With iisback you can backup and restore the IIS configuration. In fact, if you do a listing of .vbs-files from within %winnt%\system32 you may find some other hidden gems.

Hope this helps... too.

Sander

Currently rated 2.9 by 10 people

  • Currently 2.9/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET

Get GoogleBot to crash your .NET 2.0 site

by Sander Gerz July 01, 2006 21:31

If you’re developing in ASP.NET 2.0 and you’re using url rewriting, you should proceed with caution. Especially if you value your ranking in search engines. I’m posting this as a follow up and with reference to the original find on this post.  The issue came about in a thread on the Community Server 2.0 forums. I was fast to post a solution to the problem, but obviously, it’s more about working around the issue than actually solving the root cause.

Url rewriting is mostly used to make URL’s more friendly to read. Also, if you have migrated from one site to another and you want accommodate people still linking to old urls, rewriting is a common practice. Nonetheless, if you use this on a public internet website, it won’t be long until you see the following exceptions listed in your Event Log:

   Exception type: HttpException
   Exception message: Cannot use a leading .. to exit above the top directory.
...
   Stack trace:    at System.Web.Util.UrlPath.ReduceVirtualPath(String path)
...

For any site of significance, and www.codes-sources.com is most certainly one of them, this exception was logged more than 2000 times … every hour. Now, that’s something to notice, right? And the effect on your ranking in the search engines? Well, within a few days, your site is either kicked out completely from the index or the index contains nothing more than the url of your site without content. Nobody looking for content you may have on your site will be directed to it. Worried? Read on.

My personal instinct would be: it’s something I did wrong. So one takes a long time trying to figure out what that is. But in fact, it’s a bug in a .NET component that’s not easy to trace and reproduce. If you don’t check the event logs every once in a while, it can surely be missed. Let’s take a look at what’s going on:

A first note to people trying to reproduce the issue, the bug does not appear using Cassini (the built-in web server in Visual Studio 2005). You need to have a running IIS 6 web server on Windows 2003. Doesn’t matter if it’s in a VPC or on an actual server.

If you’re using url rewriting in .NET 2.0, you have the Context.RewritePath method at your disposal. Here’s a sample project for testing.

1.       First you create a page, say page.aspx

2.       In this page, you can put whatever you want; it doesn’t really matter. For example:

<%=Request("ID")%>

3.       Then you add your rewriting HttpModule, with the following implementation:

Public Class Rewriter

    Implements System.Web.IHttpModule

     Public Sub Dispose() Implements System.Web.IHttpModule.Dispose

     End Sub

     Public Sub Init(ByVal context As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init

        AddHandler context.BeginRequest, AddressOf Me.HandleBeginRequest

    End Sub

     Private Sub HandleBeginRequest(ByVal [source] As [Object], ByVal e As EventArgs)

        Dim app As System.Web.HttpApplication = CType([source], System.Web.HttpApplication)

        app.Context.RewritePath(“~/page.aspx?ID=1”, False) ' sidenote, same effect when using “/page.aspx?ID=1”

    End Sub

End Class

As you can see, it’s a simple example rewriting all urls to page.aspx?ID=1. It’s does not serve a specific function, other than show the problem at hand. Now, add the HttpModule in the Web.Config file.

With Fiddler (available at www.fiddlertool.com), you can create web requests and analyze the result in very good detail. It’s especially useful in this case, as you can create a request specific for certain user-agents. So download the tool and setup your ASP.NET 2.0 site on an IIS 6.0 environment. One thing to note as well, is that this site needs to be running under its own hostheader, not as a virtual directory.
Once installed, you take your web browser and go to

http://localsitename/default.aspx

The page default.aspx will be rewritten as page.aspx?ID=1 and everything works just fine.

Now, open up Fiddler and create the following request:

Accept: */*
Accept-Encoding: gzip, x-gzip
User-Agent: Mozilla/4.0

Set the url to

http://localsitename/default.aspx

and hit Execute. You should get status code 200, meaning OK. Now set the url to

http://localsitename/justafolder/default.aspx

and after you hit OK, again, you will get a 200 code. No problems so far.

Now, change the request to

User-Agent: Mozilla/5.0
instead of
User-Agent: Mozilla/4.0

Hit Execute and bang… error 500, indicating an application error.
Here’s a list of user-agent entries that will result in an error:

Mozilla/1.0
Mozilla/2.0
Mozilla/5.0
Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)
Yahoo-Blogs/v3.9 (compatible; Mozilla 4.0; MSIE 5.5; http://help.yahoo.com/help/us/ysearch/crawling/crawling-02.html )
Mozilla/2.0 (compatible; Ask Jeeves/Teoma; +http://sp.ask.com/docs/about/tech_crawling.html)
Mozilla/5.0 (compatible; BecomeBot/3.0; MSIE 6.0 compatible; +http://www.become.com/site_owners.html)
Mozilla/5.0 (compatible; Konqueror/.... (Tous les users agent de Konqueror que j'ai testés plantent)
Etc...

Some funny details:
Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1 <= no error
Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.1) <= error 500!

Ok, so let’s try to explain what happens. If you call RewritePath with the rebaseClientPath parameter set to “True”, the virtual path is reset. So why set it to False? Well, the setting of rebaseClientPath affects the action-tag of a form.

If I have an url http://mysite/myfolder/mypage.aspx which is rewritten to http://mysite/page.aspx?id=mypage, the form tag will we set as follows.

With rebaseClientPath set to true:

<form name="form1" method="post" action="page.aspx?ID=mapage" id="form1">

But with rebaseClientPath set to false:

<form name="form1" method="post" action="../page.aspx?ID=mapage" id="form1">

In case of a postback, the action in the latter situation (with rebaseClientPath set to false) is correct. Not in the first instance, because there is no page.aspx in the subfolder /myfolder.

Now, a workaround would be to manually set the UrlPostback to the correct location, but the ramafications are significant, and may affect the execution of the javascript manipulation the UrlPostback on a number of browsers.

What’s really troublesome is that it affects only the production version of a website. It’s not visible during development (usually you don’t let searchengines index your development and test environment, right?). Also, it happens only under IIS 6.0, using ASP.NET 2.0. And the only variable in this case is the user agent with which the site is accessed.

Now we know what the issue is, how do we resolve it? Well, doing it yourself is not easy and without risk, but here goes.

It has to do with the capabilities of the user-agent. When the site is hit by a user-agent having Mozilla/5.0 in the string, ASP.NET will be using System.Web.UI.Html32TextWriter. I’ve traced the bug with Intercept Studio and can confirm this. If you use another user-agent, for example Mozilla/4.0, System.Web.UI.HtmlTextWriter will be used. This is called adaptive rendering, which can lead to weird behavior.

So the problem lies in Html32TextWriter, but it’s unclear where this goes wrong exactly. The exception is thrown in System.Web.Util.UrlPath.ReduceVirtualPath(), but by the time the stack reaches this method, we’re already six method calls away from the last usage of Html32TextWriter (being used in System.Web.UI.HtmlControls.HtmlForm.RenderAttributes). If you have time to walk the stack with Reflector, go ahead. There are about 23 method calls in all.

You may want to wait for a fix to come from Microsoft, but if you can’t wait that long, there’s a hack solution to try for yourself. Say for instance you want to fix the issue with the Yahoo searchbot, Yahoo! Slurp (you would need to apply this to all user-agents in a similar fashion.)

Since Visual Studio 2005 we have the capability to create .browser files. These .browser files contain a definition of the capabilities of browsers. In your web project, add a folder called “App_Browser” and create a new file (i.e.: yahooslurp.browser). In this file, you put

<!--

Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)

-->

<browsers>
<
browser id="Slurp" parentID="Mozilla">
<
identification>
<
userAgent match="Slurp" />
</
identification>
<
capabilities>
<
capability name="browser" value="Yahoo!Slurp" />
<
capability name="Version" value="4.0" />
<
capability name="MajorVersion" value="4" />
<
capability name="MinorVersionString" value="" />
<
capability name="MinorVersion" value=".0" />
<
capability name="activexcontrols" value="true" />
<
capability name="backgroundsounds" value="true" />
<
capability name="cookies" value="true" />
<
capability name="css1" value="true" />
<
capability name="css2" value="true" />
<
capability name="ecmascriptversion" value="1.2" />
<
capability name="frames" value="true" />
<
capability name="javaapplets" value="true" />
<
capability name="javascript" value="true" />
<
capability name="jscriptversion" value="5.0" />
<
capability name="supportsCallback" value="true" />
<
capability name="supportsFileUpload" value="true" />
<
capability name="supportsMultilineTextBoxDisplay" value="true" />
<
capability name="supportsMaintainScrollPositionOnPostback" value="true" />
<
capability name="supportsVCard" value="true" />
<
capability name="supportsXmlHttp" value="true" />
<
capability name="tables" value="true" />
<
capability name="vbscript" value="true" />
<
capability name="w3cdomversion" value="1.0" />
<
capability name="xml" value="true" />
<
capability name="tagwriter" value="System.Web.UI.HtmlTextWriter" />
</
capabilities>
</
browser>
</
browsers>

Now, restart your website and redo the tests with Fiddler, setting the user-agent to

Mozilla/5.0 (compatible; Yahoo! Slurp; http://help.yahoo.com/help/us/ysearch/slurp)

Voilà, no more 500 error message. Repeat the steps for the different user-agents out there.

There may be other possibilities to fix this problem, but this one seems to be the most straightforward to implement and doesn’t require you to recompile the code. With solutions like CommunityServer, you simply don’t have this option anyway. It will suffice to add the App_Browser folder and the various .browser files to the root folder of the website and it will work.

At the end of the original post by Nix, there are some closing remarks. For example, if you create the site as a virtual directory under a website root, the problem does not appear. Changing the user-agent in a header, as suggested by Poppyto, might work, but the consequences are uncertain. Also, you would need to recompile.

Now, you might think, oh well, just add the appropriate .browser files and we're done. But that’s a bit short sighted. You never know when Google or any other search-engine decides to change the user-agent string. Your first notification would come from the exception messages in your event log. I manage about 7 big Windows 2003 servers in our datacenter. Perhaps not much, but I know what issues can come along every once in a while). Both as a developer and a system administrator, I would rather prevent issues, than handle them afterwards.

If you want to debate the issue, please go to the thread at the Community Server forums.

PS: Why did I write this post? Well, the entire explanation is written in French, and not everyone can read this. Also, Nix and I know each other and he’s been helpful on a number of occasions, so if there’s anything I can do in return, like explaining the issue in English, I’m more than happy to help. Finally, this problem needs a proper solution, and the sites and servers I host can be just as much affected. I was fortunate not to have too much url rewriting in my sites, but that doesn’t affect the scope of the issue.

 PS: sorry if this post is popping up in your rss-reader again, but the text-editor in .Text keeps mangling my writing.

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET

Atlas: Setting the ServiceMethod of an AutoCompleteExtender

by Sander Gerz June 26, 2006 13:39

Recently we had a usergroup meeting on the subject of ASP.NET “Atlas” . In my current project, in which I'm rewriting a number of applications from Notes 6.5 to .NET 1.1 and 2.0, I took the liberty of using Atlas on a couple of webpages. When trying to implement a search feature, I obviously looked at the AutoCompleteExtender. Users needed to be able to search on one of four columns in a table. The ServiceMethod property is pointing to a webservice. This webservice needs to have the exact signature of (string  prefixText, int count). No room for any other parameters. Not to worry though, just create four webmethods and have these call the method doing the actual work.

Setting the ServiceMethod at runtime, e.g. in the DropDownListSearchParam_SelectedIndexChanged event handler, did not work. The changed ServiceMethod-name is not rendered in the resulting xml-script (just check your html). Another option is to insert some scripting in the page, like this:

    <atlas:AutoCompleteExtender runat="server" ID="autoCompleteSearch">

        <atlas:AutoCompleteProperties TargetControlID="TextBoxSearch"

              Enabled="True"

              ServicePath="~/services/WebServiceSearch.asmx"              

              ServiceMethod='<% GetServiceMethod() %>'

              minimumprefixlength="1"  />

    atlas:AutoCompleteExtender>

But no. If you do this, the xml-script that is rendered simply contains &lt;% GetServiceMethod() %&gt;

However, if you set the ServiceMethod-property like this on the atlas:AutoCompleteExtender-element... bingo!

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET

This is the French way of talking to developers

by Sander Gerz May 15, 2006 19:36

Ever wondered how Microsoft France wants to get developers coming to their MSDN-site? Well, they are using Alexia:

Alexia

Check out the site at: http://www.microsoft.com/france/msdn/alexia/default.mspx for a chat with this ehmm....

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET

Not required: an understanding of cryptography or security-related subjects

by Sander Gerz April 20, 2006 07:48

Here's an interesting page. Microsoft is publishing a new API for cryptography for Windows Vista. It's called Cryptography API: Next Generation (CNG) API and is the long-term replacement for the CryptoAPI. It allows developers to securely convey information over non-secure media. The sentence that struck as a bit of a surprise is “Although not required, an understanding of cryptography or security-related subjects is advised.”

Okay, so you're going to use an API to give you various cryptographic en security features, but you don't need to understand any of the underlying concepts. How's that for encapsulation, eh?

Can anyone explain to me why all the 26 CNG primitive functions start with BCrypt?

 

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET

Bitwise operators makes us storagewise

by Sander Gerz March 17, 2006 10:36

Not having a computer science or mathematical background, I had a vague idea of bitwise operators, but never needed them for anything practical. Until now that is. I'm building a form with a CheckedListBox. This listbox contains items that can be checked or unchecked. The items themselves are added from an enumeration, say TestOptions. The user can check multiple items but I only have one variable to store the selection. Ok, I could have more, but figured it to be a waste to check the state of each item and store that in a seperate variable. There should be something more efficient to do this. So here goes:

First here's the enum type:

        public enum TestOptions {

            OptionA = 1,

            OptionB = 2,

            OptionC = 4,

            OptionD = 8

        }

It's important to give each enumvalue an explicit integer value. These values need to be incremented by a multiple of 2 (so: 1, 2, 4, 8, 16, 32, etc). This enables us to make unique combinations of a set of enum values. I.e. the setvalue of 5 can only be attributed to a selection of 1 and 4. The value of 7 can only come from a selection of 1, 2 and 4.

To fill the listbox with items and set their checked state, this method is called:

        private void SetCheckedListBoxItems(int value) {

            foreach (int enumValue in Enum.GetValues(typeof(TestOptions)) ) {

                CheckState state = CheckState.Unchecked;

                if((value & enumValue) == enumValue) {

                    value ^= enumValue;

                    state = CheckState.Checked;                     

                }               

                checkedListBox1.Items.Add(Enum.GetName(typeof(TestOptions), enumValue), state);               

            }

        }

The value that is passed to this method is the sum of the items from the enum that are checked. For example: SetCheckedListBoxItems(9). The method will loop through each enum value. The default state is unchecked. Then we check to see if the submitted value is contained in a bitfield. For integral types like we have here, & computes the bitwise AND of its operands. What this means is that it returns the bits that are common between the two operands. Wait a minute, we went from integer to bit, what, how, when? Well, an integer is composed of 32 bits in the .NET Framework, which means that 32 zeros and ones represent the actual integer value. To clarify, take the value of 9 which can be represented as: 1001. For brevity, let's omit the 28 zeros preceding 1001.

Suppose this value of 9 is submitted to the method shown above. Once in the loop it checks against the value of 2, being one of the enum values. The number 2 in bits is: 0010. The outcome of (1001 & 0010) = 0000, effectively zero, so there's no match and we don't check the item. Further in the loop we get the enumvalue of 8, representable as: 1000. We check which bits are the same (1001 & 1000) and the result is ... 1000, which is 8 in integer terms.

So we know that the item representing the enumvalue of 8 needs to be checked. We then combine the bits such that if exactly one is 1, the result is 1, else the result is 0. For this, we use the ^= operator also known as the exclusive-OR assignment operator. Performing the operation 1001 ^= 1000 sets the value to 0001, which is 1 as an integer. So when the loop encounters the enumvalue of 1, the evaluation will give the proper result, and make sure we also check the listitem for the enumvalue representing 1. You would assume we encounter the value of 1 before we see 8 in our loop through the enumtype and while this is true, it doesn't matter. Try this for yourself.

After a new selection is made, we want to save the new value. This is very simple.

        private void SaveSelection() {

            int newvalue = 0;

            foreach (string item in checkedListBox1.CheckedItems) {

                newvalue += (int)Enum.Parse(typeof(TestOptions), item);

            }

            // show the value, or persist somewhere, whatever...

            MessageBox.Show("value: " + newvalue);

        }

The concept allows for very efficient storage of selections. Looking back on previous apps, I could have used this more in my applications. How about you?

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET

Testing exams 70-553 and 70-554

by Sander Gerz March 06, 2006 13:57

This morning I took the beta exams for 70-553 and 70-554 (71-* when they're in beta). Both exams are pretty big, but I took it as the challenge to take both at the same time. Well, not exactly of course, first 553 and then 554, but on the same day. I had not anticipated the total number of questions though, about 150!

553 dealt more with C# (in my case, you can also pick VB.NET) language constructs, a bit of Windows Forms. I should have taken more interest in the BackgroundWorker component, but in all the questions were not extremely difficult. That's no guarantee for success on my part. After about 70 questions, I experienced a lapse of concentration.

The 554 is more focused on 'enterprise' development. That's probably why about every question in the first part of the exam starts with 'you are an enterprise developer...'. The second part was very much on Web Services Enhancements 3.0 and bit of .NET remoting. These were some tough questions. Partly due to my lack of experience with WSE 3.0.

The lack of experience is mostly what makes the exams difficult. Since both exams are targeted at .NET certified developers, the focus is primarily on new features. And given the limited time .NET 2.0 has really been on the market, only few of us really have indepth experience with WSE 3.0, ClickOnce deployment, Providers, mobile devices, new asynchronous capabilities. At the same time and on the same level, that is.

The exams themselves are divided in three and two parts respectively, so don't be fooled when you enter the exam and see 30 questions and 1 hour remaining when you start. If I remember correctly when upgrading my MCSE on NT4 to Win2000 certification, that was a question marathon as well.

I'll get the result in a couple of weeks, but I'm not keeping my fingers crossed until then. I have some preparing to do for my session at the Dutch DevDays tomorrow.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET

Powered by BlogEngine.NET 1.4.5.0
Theme by Mads Kristensen | Modified by Mooglegiant