Problems setting up ASP.NET 4.0 web on IIS 7


.NETASP.NETASP.NETFrameworksLanguagesServers

I was attempting to set up a new ASP.NET 4.0 web on my dev machine, running Windows 7 and IIS 7. I ran into several errors, that I suspect others may encounter, and I had to search all over the web to find all the answers. So I’ve written this post in the hopes it saves some other dev the same headache I had!

So, first I created the new website and app pool identity, but when I hit the site for the first time, I got the following error:
HTTP Error 500.19 – Internal Server Error
The requested page cannot be accessed because the related configuration data for the page is invalid.

After searching for solutions, I found most had to do with permissions to the web.config file or actual locking of sections of the web.config file. I confirmed that the app pool identity had permissions to the file, and there were no locking attributes in the file. So something else had to be the issue. Then I found this post:
http://stackoverflow.com/questions/9216158/the-requested-page-cannot-be-accessed-because-the-related-configuration-data-for
It turns out that ASP.NET had not been configured fully on my machine. So, according to one of the answers on the post, the solution is to do the following steps:
1. Open control panel
2. Click on “Programs and Features”
3. Click on ”Turn windows features on/off”
4. Locate ”Internet Information services IIS” in the pop up window and expand its node
5. Expand the ”World Wide Web Service” node
6. Expand “Application Development Features” node
7. Check the check box of”ASP.NET”
8. Then click ok button
9. You will need to restart your computer (go get a cup of coffee…)

After restarting, and hitting the site again, I got this new error:
HTTP Error 500.21 – Internal Server Error
Handler “PageHandlerFactory-Integrated” has a bad module “ManagedPipelineHandler” in its module list
Another web search revealed that even though the step above enabled ASP.NET, it was not fully installed. This article shows how to finish the installation: http://stackoverflow.com/questions/6846544/how-to-fix-handler-pagehandlerfactory-integrated-has-a-bad-module-managedpip
Basically, just open a command window and enter the command shown below (command is slightly different for 32-bit vs. 64-bit).
64-bit:
%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -i

32 bit:
%windir%\Microsoft.NET\Framework\v4.0.21006\aspnet_regiis.exe -i

If you get a permissions error, you need to run the window as an administrator. To do this, go to start |run, and type ‘cmd’, but hit Ctrl-Shift-Enter, instead of just Enter.
After doing that, I hit the site again, and it worked! Hope this has helped!

ASP.NET Membership.GetUserNameByEmail Error: “The E-mail supplied is invalid.”


.NETASP.NETC#LanguagesTips and Tricks

What the heck does this error message mean?? I had cause to find out when I was getting this error in a method that was simply updating the email address for an existing user. Mind you, I wasn’t creating a new user – I was just updating an existing user.  Since the error message is less than helpful, I thought I’d post this so anyone else getting this error won’t have to search as much as I did to find the solution.

Here’s how it came into play: I had created a secure web page to allow my client to manage some of their user accounts. They often had requests to change the email address for the account, so I created a simple form with a couple of text boxes (tbChangeEmail_Old and tbChangeEmail_New), a label to display the status of the attempt (lblChangeEmail_Status) and a Submit button.

Here’s the code I was using, when the user clicked the Submit button:

try
{
   string username = Membership.GetUserNameByEmail(tbChangeEmail_Old.Text);
   if (!string.IsNullOrEmpty(username))
   {
      MembershipUser user = Membership.GetUser(username, false);
      user.Email = tbChangeEmail_New.Text;
      Membership.UpdateUser(user);
      lblChangeEmail_Status.Text = "Email address successfully changed.";
   }
   else
   {
      lblChangeEmail_Status.Text = "Unable to find user with that email.";
   }
}
catch (Exception ex)
{
   lblChangeEmail_Status.Text = "Error: " + ex.Message;
}

It’s pretty straightforward – attempt to get the username using the ‘old’ email, and if the account isn’t found, display a message to the user. If we do find the username, then use it to get a MembershipUser object, set the Email property to the ‘new’ value, and update the user. Wrap that up in a try/catch block, and we’re good to go.

Everything worked fine, until today, when my client reported she was getting an error message for one user: “The E-Mail is invalid.” Huh. Did that mean the new email address wasn’t a valid email format? No, the new email was fine. Did it mean the old email didn’t work and the user wasn’t found? No, the test for !string.IsNullOrEmpty(username) catches that, and I verified that the account with the old email address was present. So what’s going on?

I did the usual trick of Googling for a solution, and found a lot of forum questions related to creating a new user, but then I finally found something about DUPLICATE emails, which, of course, are not allowed in the Membership database, based on our configuration. Aha! I did a quick SQL query of the DB, and sure enough, there was already an account with the ‘new’ email address, so it was not possible to update the ‘old’ account with the ‘new’ address!

So, since the existing error message is less than helpful in this case, I changed the logic in the catch block, so I could display a more helpful error on the web page:

catch (Exception ex)
{
   if (ex.Message.ToLower() == "the e-mail supplied is invalid.")
      lblChangeEmail_Status.Text = "There is another account with the 'new' email address, so the 'old' email account cannot be updated.";
   else
      lblChangeEmail_Status.Text = "Error: " + ex.Message;
}

Now, if we run across another case like this, my client will know exactly what’s going on. No more ambiguous error messages! J

So, not earth-shattering .NET stuff, but I figure what I learned might help someone else in the same situation. Happy coding!

Repeating a Try-Catch block


.NETC#Tips and Tricks

Here’s a tip for beginners. You know how a try/catch block works: place some code inside a try, and if it fails, catch it with the catch block. But what do you do if you want to try an operation a set number of times, and then throw an exception if it’s still failing? There’s no such animal that is native in C#, but you can quickly implement one yourself. With a counter and a ref parameter, this can be done quite simply. This brief example will show you how.

Suppose we want to do some FooBar operation, but we know it could fail, due to some external circumstance, but we also know could work after the initial attempt or two. Let’s write the code to do 3 tries, and only then throw the error:

int MaxTries = 3;   //this is the limiter value - set this to the no. of tries you want to execute
int NumTries = 0;   //this is our counter that keeps track of how many tries we've executed

//Perform the FooBar operation(we retry 3 times & if we don't succeed, the exception will be caught & handled)
while (NumTries < MaxTries)
               throw (err);


private void FooBar(int foo, int bar, ref int numTries)
        {
            try
            {
                //count the try
                numTries++;

                //set up & and perform your operation
                Foo(bar);
                Bar(foo);
                DoFinalOp();

                //if we got here, there was no error so set counter to kick us out of loop
                numTries = MaxTries;
            }
            catch (Exception err)
            {
                //only throw error if we've tried enough times
                if (numTries >= MaxTries)
                    throw (err);
            }

        }

Note that our FooBar method takes a ref parameter of numTries. When we change this value in the method, and the method returns, the counter will have been changed, for re-testing in the while loop clause.

Let’s walk through this and see how it works:

  • After setting NumTries and MaxTries (to 0 and 3), we hit the while loop. This first time, NumTries is definitely less than MaxTries, so we execute FooBar().
  • When we enter FooBar(), the first thing we do is increment tries, to count the attempt. Since this is a ref parameter, changing this local variable tries also ends up changing the global variable NumTries.
  • Then we start executing whatever we have to do in FooBar(). If an error is encountered at this point, we’ll fall to the catch block.
  • In the catch block, we test whether or not to throw an error, based on the value of tries. Since at this point, tries = 1, we don’t throw the error, FooBar() finishes executing and we return to the while loop.
  • Back in the while loop, we retest NumTries to see if it’s still less than MaxTries. Since we incremented it in the method, NumTries is now equal to 1, but this is still a true condition, so we call FooBar() again.
  • Once again inside FooBar(), we increment tries by 1 and try our operation. Suppose this time, it succeeded. In that case, we will reach the line: tries = MaxTries and then exit the method.
  • Now, back in the while loop, the test (NumTries &lt MaxTries) is false, so we don’t execute FooBar() again, and we’re done.

Voila! We’ve implemented try/catch/repeat functionality, allowing us multiple tries before throwing an error.

ASP.NET – ‘PASSING PARAMETERS’ IN BUTTON CLICK-HANDLER


.NETASP.NETFrameworksLanguages

A recent posting to a technical mailing list I’m on asked how to pass a parameter to a button click-event handler. The programmer wanted to do the equivalent of this:

<asp:button ID="btnSubmit" runat="server" OnClick="Btn_Onclick(PARAM)" />

But, she knew this didn’t work, because the default signature of event handlers in ASP.NET is this:

void myBtn_OnClick(Object sender, EventArgs e)

So, she was stumped on how to pass some sort of argument to the event handler.

Now, there a certainly some kludges that would work, such as having a hidden form field which contains the ‘parameter’ value, and having the event-handler get the value that way. But surely, there’s a better way? Well, yes, of course there is! :)

This better way is to use the “CommandArgument” property on the button control. This property is directly accessable in the event handler. The added bonus is that you can write a single even-handler for all of your button clicks, and use the associated “CommandName” property to know which button fired.

So, now, in your aspx page, your button object will be declared thusly:

<asp:Button ID="test" runat="server" CommandArgument="MyVal" CommandName="ThisBtnClick" OnClick="MyBtnHandler" />

Then, in the OnClick handler, you can cast the sender object to the correct type, and get the values of
CommandName & CommandArgument. (You could make this even more generic and handle the OnClick event for different senders, but we’ll leave that for a later post! :)

void MyBtnHandler(Object sender, EventArgs e)
{
	 Button btn = (Button)sender;
          switch (btn.CommandName)
          {
                case "ThisBtnClick":
                    DoWhatever(btn.CommandArgument.ToString());
                    break;
                case "ThatBtnClick":
                    DoSomethingElse(btn.CommandArgument.ToString());
                    break;
           }
}

You can see that the switch statement uses the CommandName property to determine which button was clicked, and then can use the CommandArgument property passed in by the button click event.

Voila! You’ve “passed a parameter” to a button click-event handler!

[UPDATE] Thanks to Jim for pointing out some confusion in my sample code. I hope that this version is clearer.