Welcome

You have reached the blog of Keith Elder. Thank you for visiting! Feel free to click the twitter icon to the right and follow me on twitter.

CodeMash: Asp.Net Tips And Tricks

Posted by Keith Elder | Posted in Asp.Net, Programming | Posted on 19-01-2007

0

I’m sitting in the Asp.Net tips and tricks sessions given by Scott Guthrie at the CodeMash conference.  Below are some of the items Scott covered.

Visual Studio Tips and Tricks

First up is the web site project model and the web application project model.  Essentially there are two types of web solutions.  One is a web site project which is the default in Visual Studio 2005.  It essentially allows you to store your web site in a folder0. For most content driven sites this is fine but this isn’t what we were use to in VS2003.  The other solution type is a download that was provided after VS2005 was launched.  Those of us that were using VS2003 didn’t like the new way with the App_Code folder and so on.  The web application project download provides developers the ability to get back to the way we were used to in VS2003.  Typically enterprise customers building large scale applications will utilize the web application project model and content sites use the built-in web site project.   There are also tools to migrate between the two projects if you decide to change your solution later on.  Here are the main things the web application project provides:

  • All files contained within the project are defined within a project file (as well as the assembly references and other project meta-data settings). Files under the web’s file-system root that are not defined in the project file are not considered part of the web project.
  • All code files within the project are compiled into a single assembly that is built and persisted in the \bin directory on each compile.
  • The compilation system uses a standard MSBuild based compilation process. This can be extended and customized using standard MSBuild extensibility rules. You can control the build through the property pages, for example, name the output assembly or add pre- and post-build actions.

Optimizing VS 2005 Web Site Build Performance

If you’ve had build performance issues with Asp.Net there are some tricks and reasons why sometimes when you make a small change the entire solution rebuilds.  Instead of me getting into this to deep, Scott already has a lengthy blog article with screen shots that outlines what is happening under-the-hood and how to speed up build times.

Default Button

Since I write mostly in Windows Forms within .Net, this is something I knew but just forgot from lack of using it.  There are times when you have a web page that has multiple buttons on it.  By setting the defaultbutton property of the form tag you can declare which button will have its click event when the user presses the enter button.  This enables developers to identify the default button behavior when the enter key is hit.  It is cross browser and works on all modern browsers.  Without this feature you would have to write the JavaScript on your own.  The <asp:panel> control also supports this.  Here is an example:

<form defaultbutton=”button1″ runat=”server>

<asp:button id=”button1″ runat=”server” />

<asp:panel defaultbutton=”button2″ runat=”server>

<asp:button id=”button2″ runat=”server”/>

</asp:panel>

</form>

How to shift focus

You can write java script to shift focus to a certain input control but in .Net 2.0 you don’t have to.  In .Net 2.0 there is an attribute called defaultfocus which you can set on your form control to automatically shift the focus to the input control.  To take this a step further you can also do this in code: Page.SetFocus(control).

Another way shift focus comes into play is on validation errors.  When you are using the validation controls set the property SetFocusOnError=”true”.  By default it is false for backwards compatibility so it is something you have to set.  Setting it to true it will auto shift to the control throwing the error validation.  Very nice!

Using CSS Adapters

In Asp.net 2.0 the Control Adapter API was introduced which provides alternative rendering of controls.  What this gives you is a hook to modify or override a control’s rendering output.  All events and other things stay the same, but the output of HTML can be altered.  The CSS Adapter Toolkit, which can be downloaded from http://www.asp.net, makes this possible.  For example instead of the menu control outputting tables, it can output a div tag with ul and li tags.  This of course allows a designer to then style the menu as they would want. 

I asked the question if this is going to be baked into the next release of Visual Studio and Scott said it would be, but to what extent he wasn’t sure.  It is an interesting problem to discuss because you have an interesting design experience to overcome in Visual Studio.   While they could change the output of the menu control to display div tags by default it wouldn’t render properly without a style sheet.  While it is a little more work, I think the solution would be for the Asp.Net team to provide a configuration wizard to configure the control, or maybe extend the smart tag.  I would like to see the default option that is rendered from the controls to be all compliant HTML and then just simply switch a property to change the style to A, B, C, D, or Custom.  This is just an initial quick thought but hopefully you see where I am going. 

Register User Controls in web.config

 If you use user controls in your pages you typically have to add the user controls in the top of each page.  If you add this following code below into your web.config file, these controls will be automatically loaded for you and save you this step.  And for the record there is no performance penalty in taking this approach.

      <pages>

        <controls>

          <add tagPrefix=theelder src=~/controls/header.ascx tagName=tag />

        </controls>

      </pages>

 Server Side Comments

If you have ever had a time when you wanted to not render a control in a page you may have just done this:

<!–  <asp:Button runat=”server” id=”button1″ /> –>

Taking this approach is still going to render the button and fire events it is just going to be hidden in the browser.  However, if you really want to remove the control from the page see the sample below.  Doing it this way will just skip this button all together. 

    <form id=”form1″ runat=”server”>

    <div>

    <%–<asp:Button runat=”server” ID=”button1″ />–%>

    </div>

    </form>

 Other Tips and Javascript Intellisense in Next Version of Visual Studio

 Scott also showed a lot of Ajax tips.  The one take away he mentioned that I didn’t know was the javascript debugger trick.  And while I am thinking about it he also noted that in the next version of Visual Studio code named Orcas, we were going to have full blow javascript intellisense and debugging capability.  No other IDE provides this right now (at least that I am aware of) so this is going to great for those doing lots of Ajax.  Folks, this is HUGE!  

About the debugger trick.  Essentially place this line in your javascript:  debugger;

When you do this the Visual Studio debugger will open to allow you to start a new instance of Visual Studio so you can step into the javascript and also view the contents of variables.

Technorati tags:

CodeMash: Scott Guthrie Keynote on LINQ

Posted by Keith Elder | Posted in Asp.Net, Programming | Posted on 19-01-2007

0

Scott Guthrie opened up CodeMash day 2 today with the keynote this morning and covered LINQ (Language Integrated Query).   I first saw LINQ over a year ago and it is just as exciting today to see it again as it was then.

 

I’m sitting at a table with some of my fellow team members and other conference attendees.  Most of them haven’t seen a LINQ demo and it was interesting to watch their reactions to LINQ for the first time.  As Scott showed different examples you could tell he had their attention as their heads turned around to each other nodding with approval.  Since we only had an hour the time went by fast and I was left wanting more LINQ goodness.  If you haven’t seen LINQ in action, check out this screen shot.

 

WinForm Programming: Send Email Using Outlook Interop or System.Diagnostics.Process

Posted by Keith Elder | Posted in .Net, Programming, Smart Clients | Posted on 11-01-2007

14

A lot of applications generate emails to alert users or send out notifications.  If you do WinForm programming the need to generate email from your application is something you will probably come across at one point or another.  There are essentially two ways I use to generate emails from WinForms or Smart Clients.  One is using the Outlook Interop and the other is simply starting a process using the System.Diagnostics.Process class.  Each has their own merits.  Depending on why you are generating an email from your application will ultimately determine which method you should use.  For starters, let’s take the easy road and start with the Process class.

Using System.Diagnostics.Process To Generate Emails

If you aren’t familiar with this namespace the purpose of it is to provide the .Net developer with a means to access processes running on the local computer.  It can also be used to start processes as well. 

Using this class we are going to borrower something from our HTML friends.  The “mailto” tag has been around forever and we can utilize this tag to start a new process.  The idea is that whichever mail client is setup as the default mail client, a process will be started to create a new email message.  The result is no different than clicking a mailto tag in a web browser.  The code for this is simple, only a few lines.  Since the process class implements IDisposable we are going to use the using construct to assist in disposing of the process once it is done.  Here’s the code.

            using (Process process = new Process())

            {

                process.StartInfo.FileName = “mailto:me@foo.com&subject=Hello”;

                process.Start();

            }

As you see in the above example, the “mailto” tag is used as the FileName property.  A new process is going to start and launch a new email message screen for the user with the email address of me@foo.com already entered and the subject “Hello”.    Here is the sample application running:

When the LinkLabel named “Send Email Without Outlook API” is clicked, it launches the default email client on our computer and enters a To and a Subject for us automatically.  Nothing fancy or ground breaking but it works.

System.Diagnostics.Process vs Outlook Interop

As we see above sending emails from our WinForm application with the Process class is very simple.  Why would we want to go through the trouble of using the Outlook Interop to send emails?  Won’t the above example work for any Windows computer no matter which email client the user has running, so isn’t that more flexible?   The answer is yes.  This solution will work on any Windows computer launching whatever the configured default email client is.  However, what if you need to log what the user wrote in the email?  This is where System.Diagnostics.Process falls down.

Let me expand on this.  Say for example you have a CRM application that needs to log emails sent by users to your clients or contacts or customers (whatever acronym you adopt).  Even though your user’s will have the message saved in their Sent folder in Outlook having it just in their email client doesn’t easily give the users of your CRM a quick view of activity.  You may also have auditing rules in your business requirements whereby you need to save the first 500 characters of each correspondence sent to client.  Using the Process example above doesn’t allow us to intercept the message so we have access to the complete message being sent.  However, using the Outlook Interop API we can keep track of everything as well as log the email to suite our business requirements. 

Let me go ahead and get this out of the way.  Yes this does require you to be in a controlled environment.  Most corporate and enterprise networks are controlled and you’ll know if this approach will work for you in your business. 

Using Outlook Interop To Generate Emails

To get started using the Outlook Interop we first need to add the required DLL to our solution. In order to do this, right click on Add References in your solution and select the COM tab.  Scroll down about half way and select the Microsoft Outlook 11.0 Object Library.  Add this as a reference to your project. 

Once you add the required DLL to your project you are ready to start coding for the API.  One of the things I like to do is create wrapper classes for these interop classes that allow me to call them when I need them with just a few lines of code.  Here is an example of a wrapper class. 

using System;

using System.Collections.Generic;

using System.Text;

using OutlookApp = Microsoft.Office.Interop.Outlook;

 

namespace Common.Outlook

{

    /// <summary>

    /// Provides functionality so Outlook can be used to generate Emails.  Use the

    /// write event to log the email.

    /// <example>

    /// Email outlookMsg = new Email();

    /// outlookMsg.Message.Subject = “Foo bar”;

    /// outlookMsg.Show();

    /// </example>

    /// </summary>

    public class Email

    {

        /// <summary>

        /// Gets the current instance of Outlook

        /// </summary>

        OutlookApp.Application _outlookInstance = new Microsoft.Office.Interop.Outlook.Application();

 

        private OutlookApp.MailItem _message;

        public OutlookApp.MailItem Message

        {

            get

            {

                return this._message;

            }

            set

            {

                this._message = value;

            }

 

        }

 

 

        /// <summary>

        /// Constructor, gets current outlook instance

        /// and creates a blank email message

        /// </summary>

        public Email()

        {

            Initialize();

        }

 

        private void Initialize()

        {

            // create a blank email

            _message = (OutlookApp.MailItem)_outlookInstance.CreateItem(OutlookApp.OlItemType.olMailItem);

 

            // wire up the write event for logging

            _message.Write += new Microsoft.Office.Interop.Outlook.ItemEvents_10_WriteEventHandler(Message_Write);

        }

 

        /// <summary>

        ///  Used for logging after the end user presses the send

        ///  button in Outlook.  If you need to log the email that was

        ///  sent to a web service or something else, fill this in.  This is

        ///  called after the email is sent via Outlook.

        /// </summary>

        /// <param name=”Cancel”></param>

        void Message_Write(ref bool Cancel)

        {

          // ADD LOGGING HERE IF YOU NEED IT

        }

 

        /// <summary>

        /// Displays the outlook screen and shows the email message.

        /// </summary>

        public void Show()

        {

            _message.Display(false);

        }

    }

}

 Using the code above we can now enable the first link in our sample Email form above.  To create an email with Outlook it is now a few lines of code.

Common.Outlook.Email msg = new Common.Outlook.Email();

msg.Show();

Since we have access to the Outlook message we can set the Subject, To, CC, BCC, Format and other options.  We get a lot more control over our email message than with just by starting a process.  Here is a more fleshed out example.

            Common.Outlook.Email outlookEmail = new Common.Outlook.Email();

            outlookEmail.Message.To = “me@foo.com”;

            outlookEmail.Message.CC = “me2@foo.com”;

            outlookEmail.Message.BodyFormat = Microsoft.Office.Interop.Outlook.OlBodyFormat.olFormatPlain;

            outlookEmail.Message.Importance = Microsoft.Office.Interop.Outlook.OlImportance.olImportanceHigh;

            outlookEmail.Message.Body = “I love cookies!”;

            outlookEmail.Show();

 Will create the following:

The other thing using the Outlook Interop allows us to do is log the messages as noted earlier.  To do this we would add our business requirements into the Message_Write event.   In this event we have access to lots of information including a real sent time, the complete body, what importance was set, the subject and so on.  Obviously any property exposed in the API we can still reference.  This gives us a way to log the information via a database, web service or other means.

Like this story?  Then kick it on DotNetKicks.com

Take Securing Web Services With Username and Password One Step Further With a Custom SoapExtension

Posted by Keith Elder | Posted in Asp.Net, Programming | Posted on 09-01-2007

22

In a previous posts I showed how to secure your web services with a username and a password.  One of the readers added a comment and mentioned using an extension to provide authentication so I thought I would expand on how that is done.  If you haven’t read the previous posts do that first, then pickup with this.  And before we get started, thanks for the idea Kevin!

Have you ever wanted to intercept a web service method because you wanted to maybe log it or even as we are about to do authenticate a user?  Did you know you can intercept any incoming SoapMessage that is sent to your web service?  This is all possible because of the SoapExtension class in .Net. Not only can you intercept the incoming message but you can do it within one of four stages:

  1. AfterDeserialize
  2. AfterSerialize
  3. BeforeDeserialize
  4. BeforeSerialize

This allows us a lot of flexibility obviously.  In our example we are going to work with the AfterDeserialize stage which is after the message has been sent across the wire and serialized into a SoapMessage object.  Since we will have a full blown SoapMessage object, we can inspect the headers of the SoapMessage and take care of authentication then.  Our end goal with taking this approach is to allow us to authenticate a user with a WebMethod simply by adding an authentication attribute to the WebMethod like this highlighted in bold.

    1     [WebMethod]

    2     [SoapHeader(“CustomSoapHeader”)]

    3     [AuthenticatonSoapExtensionAttribute] (magic here)

    4     public int AddTwoNumbers(int x, int y)

    5     {

    6         return x + y;

    7     }

You’ll notice in this example we do not have to remember to call the code to authenticate the user manually as we saw in the previous article.  Instead by adding the attribute to the method it knows to call the authentication method.  To do this we need to first create a custom object that extends SoapExtensionAttribute and then another that extends SoapExtension.

Create a Custom SoapExtensionAttribute

In order to have the method call our custom SoapExtension we need to create an object that extends SoapExtensionAttribute.  It is a farily simple class with two overridden properties.  Here’s the code:

    1     [AttributeUsage(AttributeTargets.Method)]

    2     public class AuthenticatonSoapExtensionAttribute : SoapExtensionAttribute

    3     {

    4         private int _priority;

    5 

    6         public override int Priority

    7         {  

    8             get { return _priority; }

    9             set { _priority = value; }

   10         }

   11 

   12         public override Type ExtensionType

   13         {

   14             get { return typeof(AuthenticatonSoapExtension); }

   15         }

   16     }

You’ll notice about the only thing of real substance is the Extension type property which simply returns to us our custom extension.

Create a Custom SoapExtension

The last piece to pull this all together is a custom class which extends the SoapExtension class.  In this class we are going to write the code that does the actual authentication.  We are going to check for the AfterDeserialize stage and then first make sure we have a valid SoapHeader.   Once we do that we are going to call the static validation method and pass in the SoapHeader as we did above. 

    1 /// <summary>

    2     /// Custom SoapExtension that authenticates the method being called.

    3     /// </summary>

    4     public class AuthenticatonSoapExtension : SoapExtension

    5     {

    6 

    7         /// <summary>

    8         /// When overridden in a derived class, allows a SOAP extension to initialize data specific to an XML Web service method using an attribute applied to the XML Web service method at a one time performance cost.

    9         /// </summary>

   10         /// <param name=”methodInfo”></param>

   11         /// <param name=”attrib”></param>

   12         public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attrib)

   13         {

   14             return null;

   15         }

   16 

   17         /// <summary>

   18         /// When overridden in a derived class, allows a SOAP extension to initialize data specific to a class implementing an XML Web service at a one time performance cost.

   19         /// </summary>

   20         /// <param name=”WebServiceType”></param>

   21         public override object GetInitializer(Type WebServiceType)

   22         {

   23             return null;

   24         }

   25 

   26         /// <summary>

   27         /// When overridden in a derived class, allows a SOAP extension to initialize itself using the data cached in the GetInitializer method.

   28         /// </summary>

   29         /// <param name=”initializer”></param>

   30         public override void Initialize(object initializer)

   31         {

   32 

   33         }

   34 

   35         /// <summary>

   36         /// After the message is deserialized we authenticate it.

   37         /// </summary>

   38         /// <param name=”message”></param>

   39         public override void ProcessMessage(SoapMessage message)

   40         {

   41            

   42             if (message.Stage == SoapMessageStage.AfterDeserialize)

   43             {

   44                 Authenticate(message);

   45             }

   46         }

   47 

   48         public void Authenticate(SoapMessage message)

   49         {

   50             ServiceAuthHeader header = message.Headers[0] as ServiceAuthHeader;

   51             if (header != null)

   52             {

   53                 ServiceAuthHeaderValidation.Validate(header);

   54             }

   55             else

   56             {

   57                 throw new ArgumentNullException(“No ServiceAuthHeader was specified in SoapMessage.”);

   58             }

   59         }

   60     }

The method that we are really concerned with is the ProcessMessage which checks for the stage and then calls the Authenticate method.  This in turn calls our static validation method which checks for authentication.  At this point light bulbs should be going off!   Since we have a SoapMessage object do we not know which method is being called?  Yes!  Could we modify the ServiceAuthHeaderValidation to check for a database instead of hard coding things?  Yes!  Now you are starting to see where this could really go.   SoapExtensions are powerful and only limited to your imagination. 

When I Test It, It Doesn’t Work, Why?

Once you get your SoapExtension in your solution setup and press F5 to debug it within Visual Studio  it will launch a new web server on a random port and bring you to your service.  You enter the parameters and submit the form and it by passes your validation.  Why!? 

This is suppose to happen and here is why. If you go to the service invoked from VS through the browser interface it will not invoke the authentication and it isn’t suppose to either. The reason is you are not invoking the service via SOAP but rather just a standard POST from a form. Therefore, the SOAP extension is never going to fire. This should be disabled when you publish your web service to production as only SOAP messages should be allowed. If you have a case where you need to allow GET and POST calls then the method of a custom SoapExtension isn’t going to work. Go back to the previous way outlined that I talked about.

As a benefit, Visual Studio builds the form for you automatically when you press F5 and allows you to pass parameters to the web method, but it does it via POST. If you invoke the web method from a console application or a real client making a SOAP call, you have to pass in the username and password.  I actually consider this behavior a feature.  If we didn’t use the SoapExtension to secure the method, we’d be forced to pass in username and password all the time which would mean we’d have to always call the secured web method from a test client.   Speaking from experience this isn’t fun.  Of course you should have Unit Tests for each web method anyway but it is really easy to pass in the params to a web form while debugging.

I hope you find this useful and now don’t feel so daunted because your team leader asked you how you were going to authenticate web service methods via a database.  The only thing left is for you to implement your required features.  Of course, if you are on an Intranet, instead of using username and password as we did in the previous post you could at the point of Authenticate(SoapMessage message) use the user’s integrated credentials and check for various groups in Active Directory or even using Enterprise Library Security Block. 

Like this article?  Then kick it on DotNetKicks.com

How To Add Feedburner FeedFlare to Your SubText Blog

Posted by Keith Elder | Posted in .Net, Blog Updates, Programming | Posted on 07-01-2007

13

I started using FeedBurner.Com to power the RSS feeds for my blog and I am quite happy in doing so.  I like the stats they provide and the guidance they provide on various tweaks to the feed without having to re-code anything.  One of the items I added to the RSS feed and to the site is FeedFlare.  FeedFlare places a simple footer at the bottom of each entry which allows people to distribute the entry to other sites or to inform other users of an entry.

Step 1:  Configure your FeedBurner account for your blog

This may seem pretty obvious, but at the risk of someone being confused in order to do this, you have to create a FeedBurner account.  The cost is free.  Once you create an account and link up your feed which points to your real RSS feed on your site, configure it.   Select your blog via the control panel and click on the Optimize tab.  In the left menu select “FeedFlare” and configure the options you want.

There are two options:  Feed and Site.  By placing a check in one column or another will determine where the FeedFlare shows up.    By choosing the “Feed” option, it will place the particular flare chosen at the bottom of your feed as seen here from RSS Bandit.

Choosing the “Site” option will display the chosen flares in your web site next to each item as seen here:

Step 2:  Add any custom flares to FeedBurner

Once you are done configuring which built-in flare options you may want to add other flares.  In the FeedBurner FeedFlare section there is documentation on how to add additional flare items so I will not cover it in detail but I will give you a quick sample on how to add a flare for http://www.dotnetkicks.com.  Essentially you create an XML file which is uploaded to a web server.  Here is the XML to add the flare as seen above for Kick It!

    1 <FeedFlareUnit>

    2     <Catalog>

    3         <Title>Kick It!</Title>

    4         <Description>Submit this post to DotNetKicks.Com</Description>

    5     </Catalog>

    6     <FeedFlare>

    7         <Text>Kick It!</Text>

    8         <Link href=”http://www.dotnetkicks.com/submit/?url=${link}”/>

    9     </FeedFlare>

   10 </FeedFlareUnit>

If you would like to use this particular one it is available here:  http://keithelder.net/feedflare/KickIt.xml

Step 3:  Modify SubText.Web.Skins.YourSkinName.Controls.Day.ascx control

I did some searching and couldn’t find any examples on where to place the script needed to insert the feed flare under each entry.  I had to dig into the code a bit to find which variable was needed to get access to the URL of each entry from within the template.  And I had to find the template.

The control we are going to modify is the Day.ascx control which is located in the Skins/YourSkinName/Controls directory.  The variable that we need to place in our user control is “FullQualifiedUrl”.  Since each item on the home page is printed using a Repeater we have to use the DataBinder.Eval to get each item’s FullyQualifiedUrl property.  Here is the sample code you need to place in your Day.ascx user control.  Don’t forget to modify the one associated with your skin and replace the word “yourname” with your appropriate FeedBurner name.

            <div>

                <script src=”http://feeds.feedburner.com/~s/yourname?i=<%# DataBinder.Eval(Container.DataItem, “FullyQualifiedUrl”) %> type=”text/javascript” charset=”utf-8″></script>

            </div>

Once you have this placed in your template where you want it, upload your newly modified template to your web site overwriting the existing one.  You only need to copy this one file.  Reload your home page and your new flare should appear.