ASP.NET

warning: Creating default object from empty value in /home1/seocactu/public_html/csharptocsharp/modules/taxonomy/taxonomy.module on line 1388.

I work for a fabulous company, I've been with them for about 3 years. They are incredible about making sure developers have what they need to get the job done, whether it's software or hardware (or classes, or books). In fact, I'm on my third development machine! Most software requests are usually also granted.

So what does your gear look like? What development software has your company gotten for you to help better your work?

This is what it looks like for me:(as of posting)

Hardware:

  • Windows XP 64, core 2 quad @ 2.5 GHz, 8 gigs of ram
  • 3 19 inch widescreen monitors
  • microsoft natural ergo keyboard
  • trackball mouse
  • physical server 03 box [for testing]
  • various XP/03 virtual machines [more testing]

Software:

  • Resharper 4
  • dotTrace
  • NDepend
  • NCover complete
  • RegexBuddy
  • BareTail Pro
  • All the microsoft dev. stuff (VS 03,05,08, SQL server 05,08)
  • Snag it
  • ultramon

What about you?

kick it on DotNetKicks.com

You have a data-driven site and you like to keep the number of .aspx files to a minimum, so you opt for UserControls. Ok cool!

user controls are hot!Something you can do to be more dynamic-y is to name a UserControl the same as the requesting url, then check its existence on PageLoad. If it exists, load it into an asp:PlaceHolder control (or some other control). This can help keep your site more modular, and perhaps increase the chances that you'll reuse a UserControl in another project...or not.

Here the UserControls are stored in the /UserControls/dynamic folder on my site.

In your aspx page, we make an asp:PlaceHolder...

<asp:PlaceHolder ID="PHUserControls" runat="server"></asp:PlaceHolder>

And in code behind, on PageLoad... we make the path of the UserControl and see if it exists. If it does, we add it to the placeholder.

string path = AppDomain.CurrentDomain.BaseDirectory + "UserControls\\dynamic\\" + PageUrl + ".ascx";
if (File.Exists(path))
{
Control c = LoadControl("~/UserControls/dynamic/" + PageUrl + ".ascx");
PHUserControls.Controls.Add(c);
}

Tags:

One of the things I learned at DevConnections 08 is the magic behind ASP.NET MVC, and how it actually works. Beside the UrlRouting (which you can do with HttpModule stuff), it's pretty easy and relies a lot on Activator.CreateInstance(). As seen in my post about creating a csv from list, you can read about it here.

The magic is...shhh...

To programmatically create the worker class based on the url.

magic mvc

Yeah, no-DUH you say. Well it took MS this long to come up with it for public consumption when MVC has been around for decades. Anyhooo.

NOTE: I'm more of an MVP guy, so this is geared toward using the MVP's Presenter rather than the MVC's Controller. They're similar patterns, 'cept MVP is a bit more decoupled (and deprecated...), so in my example below, you can replace 'Presenter' with 'Controller' if it makes you fuzzy, because really, that's where all the work gets done.

Here we go.

mvc is on fire!A request comes in for blah.com/hotguitars.aspx. Your UrlRouting can match the url up with the correct view [handler] and rewrite its path to that page handler. In this case, I'd most likely use the DefaultView since the page lives off of the root (/).

On PageLoad the presenter factory is going to take the url and try to figure out which class to instantiate [return] to make the contents for the view. Each of the classes returned implement Presenter, which implements IPresenter... so I can code to the interface, which is nicer. (Notice the interfaces. I'm an interface kinda dude, because they're hot when it comes to testing).

Ok, so here's the little POC for you.

    // Presenter class implements this because all *Presenter
    // classes need to have a DoIt() method
    public interface IPresenter
    {
        void DoIt();
    }
 
    public class Presenter : IPresenter
    {
        public Presenter() { }
        public virtual void DoIt() { }
    }
    public class PresenterFactory
    { 
        //return the url minus hyphens
        private static string GetPresenterName(Regex re, string url)
        {
            return re.Match(url).Groups[1].Value.Replace("-","");
        }
        //get the url
        private static Regex rePage = 
new Regex(@"/(.+?)\.aspx", RegexOptions.IgnoreCase);

This is the sexiness....

        public static Presenter GetPresenter(Page page)
        {
            // this is blah.com/hotguitars.aspx
            string rewrittenUrl = page.Request.RawUrl;
            string presenterName = GetPresenterName(rePage, rewrittenUrl);    
            //here is where you make sure you have a HotGuitarsPresenter
            string className = "BunchaJunk.Presenters." + presenterName + "Presenter";
            // get the type, throw error, and ignore case
            Type type = Type.GetType(className, true, true);
            // create an instance of the correct Presenter/Controller and return it
            return (Presenter)Activator.CreateInstance(type, new object[] { page });
        }
    }
    public interface IBasicPage
    {
        string HtmlTitle { get; set; }
        string HtmlMetaKeywords { get; set; }
        string HtmlMetaDescription { get; set; }
        string MainContent { get; set; }
    }
    public class HotGuitarsPresenter : Presenter
    {
        private IBasicPage ibp;
        public HotGuitarsPresenter(IBasicPage ibp)
        {
            this.ibp = ibp;
        }
        public override void DoIt()
        {
            ibp.HtmlMetaDescription = "Hot stuff!";
            ibp.HtmlMetaKeywords = "jackson, paul reed smith";
            ibp.HtmlTitle = "Here are the hottest guitars at csharptocsharp!";
            ibp.MainContent = "paul reed smith, jackson, gibson";
        }
    }
 
 

Here is how it is called from aspx code behind
    public partial class _Default : Page, IBasicPage
    {  
        protected void Page_Load(object sender, EventArgs e)
        {
            //coding to the interface is the cat's meoooooooooooow
            IPresenter p = PresenterFactory.GetPresenter(this);
            p.DoIt();
        }
        public string HtmlTitle { get; set; }
        public string HtmlMetaKeywords{get;set;}
        public string HtmlMetaDescription { get; set; }
        public string MainContent{get;set;}
    }

Here is how it's used in the aspx
<title><%=HtmlTitle%></title>

That is all!

kick it on DotNetKicks.com

Tags:

Whether you're into test driven development (TDD) or test after development (TAD), or you're into having your code get br0xored by not testing (doh!)... unit testing is all over the development world. You're a silly-goose if you haven't heard about it. In any case, using Visual Studio's post-build event process is a nice way of making sure your tests are always executed after a build. Though this isn't news to most developer 'dudes,' it surely made me all hot and steamy when I did it!

To do it you'll need the following:

  • Visual Studio (no duh)
  • Some sort of command line unit test app... like nunit console
  • A new pair of pants after you see how rad this is.

So, you go here:
Visual Studio -> Project Properties -> Build Events

And add this line, pointing nunit-console to the DLL of your project:

"C:\Program Files\nunit\nunit-console.exe" "C:\SVN\Proj\trunk\ProjTestProj\bin\Release\ProjTestProj.dll"

And that's it! Get ready for the hotness!

But wait! There's more!

As an added bonus... I add this line before the line above...

copy /Y "$(ProjectDir)Web.config" "C:\SVN\Proj\trunk\ProjTestProj\App.config"

This enables "Unit testing" (or more like expectation testing) of the Web.config file by copying it over to the Unit Test project as App.config. When this happens, you would be able to talk to it in your Test project via the ConfigurationManager. For example:

Assert.AreEqual("666", ConfigurationManager.AppSettings["SomeImportantNumber"]);

kick it on DotNetKicks.com

Heavy Metal Rock and Roll.

Tired of seeing 10,343 error emails when your application blows up? So you finally took a hint and got around to logging your web application. Good work, you're another step closer to being a rock and roll geek dude.

Log4Net is a great choice for all of your logging needs. I'll assume that you have log4net correctly installed and it's giving you some sort of output. If not, the mighty Phil Haack has written about configuring log4net numerous times. Rock your Loggin'

I have two Log4Net xml config files that I switch between using debug and release preprocessor directives (Too lazy to change one for releases [They're virtually the same except for priority value]). Having the log4net config outside of web.config won't make the app restart if you need to make a change to it while it's in the wild (hot) (though won't show updates until app restart).

There are a bunch of log4net example configs available for download on the Log4Net website. I have included here the log4net config file that I am using on my latest project.

The Reasons:

Here is why I like the following log4net setup:

  • The current log keeps its static name of "log-file.txt." Paired with something like Log4Net Viewer or baretail (my preference) and the scrolling appender option, it is WICKED easy to watch the logging action as it happens in real time.
  • It will create a new log for each day or if the max size is reached (I have it set to 15mb here and 14 logs).
  • Logs are named in such a way that viewing past logs is easy... log-file.txtYYYYMMDD is what I have here where YYYYMMDD will be replaced by the actual year, month, day. (In the case where you have might have multiple logs per day, a number will be appended to the file name log-file.txtYYYYMMDD.1, log-file.txtYYYYMMDD.2, etc.).
  • What is sexier than logging?

On to the goodies...

The Config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
</configSections>
<log4net>
<root>
<priority value="Info"/>
<appender-ref ref="RollingFileAppender"/>
</root>

<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="C:\\Path\\To\\Your\\log-file.txt" />
<appendToFile value="true" />
<rollingStyle value="Composite" />
<maxSizeRollBackups value="14" />
<maximumFileSize value="15000KB" />
<datePattern value="yyyyMMdd" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="{%level}%date{MM/dd HH:mm:ss} - %message%newline"/>
</layout>
</appender>
</log4net>
</configuration>

The End:

In closing, I hope you have some sort of logging strategy for your application, using my log4net config or not, it will lead you even closer to being rocktaclar, and that is veddie nice.

Thumbs Up!
I like the log! Niiiiice.

kick it on DotNetKicks.com

So you love your multi-keyed keyboard shortcuts in Visual Studio, well I do too. The best part about them is the message that pops up after you eff it up! "(Ctrl+K) was pressed. Waiting for second key of chord." Key of chord? Am I getting ready to modulate?

About Brian


profile for bluevoodoo1 on Stack Exchange, a network of free, community-driven Q&A sites

Brian Canzanella brings you nifty tips and tricks for most things .NET. read more...

Readers / Stuff