Welcome to AspAdvice Sign in | Join | Help

.Net Discoveries

An attempt to pass along some answers I have discovered in my .Net coding.
Filling in the Gaps - Problem Design Solution 3.5 - Part 2

Prologue

In a previous post, I began dissecting the code in my ASP.Net 3.5 Website Programming: Problem - Design - Solution book attempting to fill in gaps that I found (such as where does the code in the book go and adding in code missing from the book). This is a continuation of that post, continuing in Chapter 3.

Problem

In this post, I will attempt to address the missing pieces regarding:

  • The BasePage class.
  • The SiteMap Provider.
  • The SiteMap Handler.
  • A URL Rewrite Class.
  • An addition to our Helper Class.
  • Configuring the ELMAH Error Logging Add-In.

So with no further ado, let's get started.

Solution

The BasePage Class has a fair amount of code presented in the book. Specifically I found the following code pieces in chapter 3:

  • The MoveHiddenFields Property (pg 106)
  • The MoveHiddenFieldsToBottom Function (pg 106)
  • The OverRidden Render Subroutine (pg 107)
  • The PrimaryKeyID Property (pg 107)
  • The CreateMetaControl Subroutine (pg 138)
  • The GetMetaValue Function (pg 139)
  • The PageKeyWords Property (pg 139)

I did find, however, that we should also include a property to add content to the Description META tag. Adding this functionality is mentioned on page 121, however code is not included. It's very similar to your PageKeyWords property. This PageDescription property should be added to your BasePage class as follows *Gap-Filled*:

Protected Property PageDescription() As String
    Get
        Return GetMetaValue("DESCRIPTION")
    End Get
    Set(ByVal value As String)
        CreateMetaControl("DESCRIPTION", value)
    End Set
End Property

I also found, mentioned on page 122, a Robots META tag. I was unable to find any listing of this code in the book or in the downloaded files. So I created my own *Gap-Filled*. The book mentioned that the content section of the tag could contain combinations of action (index, noindex) and directive (follow, nofollow). I created an enumeration of the six valid values (including all and none) and called the CreateMetaControl with the corresponding string values. The code is as follows *Gap-Filled*:

Protected Enum RobotMetaOptions
    IndexFollow
    IndexNoFollow
    NoIndexFollow
    NoIndexNoFollow
    All
    None
End Enum
Protected Property PageRobotMeta() As RobotMetaOptions
    Get
        Return GetMetaValue("ROBOTS")
    End Get
    Set(ByVal value As RobotMetaOptions)
        Select Case value
            Case RobotMetaOptions.IndexFollow, RobotMetaOptions.All
                CreateMetaControl("ROBOTS", "index, follow")
            Case RobotMetaOptions.IndexNoFollow
                CreateMetaControl("ROBOTS", "index, nofollow")
            Case RobotMetaOptions.NoIndexFollow
                CreateMetaControl("ROBOTS", "noindex, follow")
            Case RobotMetaOptions.NoIndexNoFollow, RobotMetaOptions.None
                CreateMetaControl("ROBOTS", "noindex, nofollow")
        End Select
    End Set
End Property

In looking around the web, it seems that really, the index-follow option (or all option) is redundant since that is the default action if there is no Robots META tag. I included the options just for the sake of completeness.

We can also notice that there is reference on page 121 to page title information. I found that again this is added in the code download, but I didn't find reference to it in the book. *Gap-Filled* I added the following property from the code download for PageTitle to my BasePage class:

Protected Property PageTitle() As String
    Get
        If Not IsNothing(Master) Then
            If Master.Page.Title = String.Empty Then
                Return String.Empty
            Else
                Return Master.Page.Title
            End If
        Else
            If Page.Title = String.Empty Then
                Return String.Empty
            Else
                Return Page.Title
            End If
        End If
    End Get
    Set(ByVal value As String)
        If Not IsNothing(Master) Then
            Master.Page.Title = value
        Else
            Page.Title = value
        End If
    End Set
End Property

There are a couple of other methods that I think may come in handy. Since I haven't read past this chapter yet, I'm not sure if they are added later as I can't find them in the index, but they are in the code download. I decided to add them just in case. I added the following to my BasePage class:

Public ReadOnly Property BaseUrl() As String
    Get
        Dim url As String = Me.Request.ApplicationPath
        If url.EndsWith("/") Then
            Return url
        Else
            Return url & "/"
        End If
    End Get
End Property

Public ReadOnly Property FullBaseUrl() As String
    Get
        Return Me.Request.Url.AbsoluteUri.Replace( _
             Me.Request.Url.PathAndQuery, "") & Me.BaseUrl
    End Get
End Property

There were also a couple that I decided NOT to add as I felt it was redundant to add them just to have them call the Helpers class. These include:

  • SEOFriendlyURL
  • ConvertToHTML
  • GetUserProfile
  • FormatPrice

Looking through the rest of the code, I'm thinking that some of that may be added later in the book or at least it may not apply till later so I will move on to the next class that needs work.

A Custom SiteMapProvider

On page 125, we're informed that we should be using a custom SiteMapProvider to generate our site map. Unfortunately, we aren't given ANY code that I find on how this is done with the exception of the settings to register the provider in the web.config file. We'll come back to that piece, but first let's create the provider so we know what to register. We're told that we can get a good primer on doing this from a series of 2006 MSDN articles. I found that some of the code comes across into our code download, and some doesn't. Also the article is in C#, so I relied heavily on the code download. Create a TBHSiteMapProvider.vb class in your 'navigation' folder *Gap-Filled* and add the following to get started:

Public Class TBHSiteMapProvider
    Inherits StaticSiteMapProvider 

    Private Const _errmsg1 As String = "Missing node ID"
    Private Const _errmsg2 As String = "Duplicate node ID"
    Private Const _errmsg3 As String = "Missing parent ID"
    Private Const _errmsg4 As String = "Invalid parent ID"
    Private Const _errmsg5 As String = "Empty or missing connectionStringName"
    Private Const _errmsg6 As String = "Missing connection string"
    Private Const _errmsg7 As String = "Empty connection string"
   Private Const _errmsg8 As String = "Invalid sqlCacheDependency" 

    Const _cacheDependancyName As String = "__SiteMapCacheDependency"
    Private _connect As String
    Private _database, _table As String
    Private _2005dependency As Boolean = False
    Private _indexID, _indexTitle, _indexUrl, _indexDesc, indexRoles, _indexParent As Integer
    Private _nodes As New Dictionary(Of Integer, SiteMapNode)(16)
    Private _root As SiteMapNode
    Public ReadOnly _lock As Object = New Object() 

End Class

This will get our class started, you may need to add import statements as the need arises, but this gets our class going. You'll notice that our class declaration gives us an error. We need to define a number of methods in this class before it will compile. So let's get started, create an Initialize method. The code IS different than on the MSDN article starting from about the half way point. Add the following to your class:

Public Overloads Overrides Sub Initialize(ByVal name As String, _
           ByVal config As NameValueCollection)
    'Verify parameters
    If IsNothing(config) Then Throw New ArgumentNullException("config")
    If String.IsNullOrEmpty(name) Then name = "TBHSiteMapProvider"
    'add default desc to config if empty
    If String.IsNullOrEmpty(config("description")) Then
        config.Remove("description")
        config.Add("description", "SQL site map provider")
    End If
    'call base's initialize
    MyBase.Initialize(name, config)
    If config("securityTrimmingEnabled") Is Nothing Then
        config.Remove("securityTrimmingEnabled")
    End If
    If config.Count > 0 Then
        Dim attr As String = config.GetKey(0)
        If Not String.IsNullOrEmpty(attr) Then
           Throw New ProviderException("Unrecognized attribute: " & attr) 
        End If
    End If
End Sub

We also need to add one of the required methods BuildSiteMap. This method is substantially changed from the one in the MSDN article, so I pulled it from the downloaded code. However, this version used two other methods that haven't been created yet. We'll start with those methods and then come back to the BuildSiteMap. Add the following two methods to your class:

Private Function CreateSiteMapNodeFromSiteMapEntity(ByVal node As _
                                                                    SiteMapInfo) As SiteMapNode
    Dim roles As String = If(node.Roles, Nothing)
    'if roles were specified, turn the list into a string array
    Dim roleList As String() = Nothing
    If Not String.IsNullOrEmpty(roles) Then
        roleList = roles.Split(New Char() {","c, ";"c}, 512)
    End If
    'create SiteMapNode
    Dim _node As New SiteMapNode(Me, node.SiteMapId.ToString(), _
                              node.URL, node.Title, node.Description, _
                              roleList, Nothing, Nothing, Nothing)
    'record node in the _nodes directory
    _nodes.Add(node.SiteMapId, _node)
    Return _node
End Function

Private Sub AddChildNodes(ByVal vParentNode As SiteMapNode, _
                                                                       ByVal SiteMapId As Integer)
    Dim lChildNodes As List(Of SiteMapInfo) = (From lChildren In _
               lSiteMapNodes Where lChildren.Parent = SiteMapId).ToList()
    For Each lChildNode As SiteMapInfo In lChildNodes
        Dim lNode As SiteMapNode = _
                                    CreateSiteMapNodeFromSiteMapEntity(lChildNode)
        AddNode(lNode, vParentNode)
        AddChildNodes(lNode, lChildNode.SiteMapId)
    Next
End Sub

You'll notice if you look at the MSDN article, that they aren't included there so they are newly created for our project from the code download. Now that they're defined, we're ready to add the BuildSiteMap method:

Protected lSiteMapNodes As List(Of SiteMapInfo)
Public Overrides Function BuildSiteMap() As SiteMapNode
    SyncLock _lock
        If _root IsNot Nothing Then Return _root
        Using lSiteMapContext As New SiteMapRepository
            lSiteMapNodes = lSiteMapContext.GetSiteMapNodes()
            If lSiteMapNodes.Count > 0 Then
                Dim node As SiteMapInfo = (From lSiteMapNode In _
                    lSiteMapNodes Where lSiteMapNode.Parent = 0).FirstOrDefault
                If Not IsNothing(node) Then
                    _root = CreateSiteMapNodeFromSiteMapEntity(node)
                    AddNode(_root, Nothing)
                    AddChildNodes(_root, node.SiteMapId)
                End If
            End If
        End Using
        Return _root
    End SyncLock
End Function

If you look at the errors, you'll see that we still have to define another overridden function, GetRootNodeCore. Again, we'll go to the code download since it isn't in the article or the book. Add the following to your class:

Protected Overloads Overrides Function GetRootNodeCore() As SiteMapNode
    SyncLock _lock
        BuildSiteMap()
        Return _root
    End SyncLock
End Function

It's a pretty simple function, but necessary. The provider also needs to be registered in the web.config file. To do this, add the following to your web.config file, it should go somewhere in your <system.web> element:

<siteMap defaultProvider="TBHSiteMapProvider" enabled="true">
    <providers>
        <add name="TBHSiteMapProvider" 
                type="TheBeerHouse.TBHSiteMapProvider"
                securityTrimmingEnabled="true" />
    </providers>
</siteMap>

There are two other methods in the downloaded code, however I'm not sure exactly what they do, I can't that they are called/referenced anywhere else. Since I don't see where they are used (at least at this point), I haven't included them.

A SiteMapHandler Class

This class is a handler that returns the sitemap.xml file used by search engine spiders so that our site can be easily indexed. This class DOES have some code included in the book, specifically it starts on page 126. Before we delve into the code there, let's create our file by adding a new class to the navigation folder and naming it 'SiteMapsHandler.vb' *Gap-Filled*. Following the code in the book starting at the bottom of page 126, we want to make sure that our class implements the iHttpHandler interface (requiring import of System.Web). When you press enter, you'll get stubs for two required elements (IsReusable property and ProcessRequest Method).

The IsReusable property can just return true *Gap-Filled*. ProcessRequest has a few more lines, but only a couple. You can find them at the top of page 127. As we start, your class should look like this:

Imports System.Web

Public Class SiteMapHandler
    Implements IHttpHandler 

    Public ReadOnly Property IsReusable() As Boolean Implements _
             System.Web.IHttpHandler.IsReusable
        Get 
           Return True
        End Get
    End Property 

    Public Sub ProcessRequest(ByVal context As System.Web.HttpContext) _
              Implements System.Web.IHttpHandler.ProcessRequest  
       BaseContext = context
       CreateSiteMap()

       Response.Flush()
       Response.End()
    End Sub

End Class

You'll notice that about every line gives us an error since nearly everything in this method is undefined. Examining the downloaded file, we find that these undefined items are actually properties created in our class (with the exception of CreateSiteMap()) *Gap-Filled*. Add the following properties to your class:

Dim _baseContext As HttpContext
Public Property BaseContext() As HttpContext
    Get
        Return _baseContext
    End Get
    Set(ByVal value As HttpContext)
        _baseContext = value
    End Set
End Property

Public ReadOnly Property Response() As HttpResponse
    Get
        Return BaseContext.Response
    End Get
End Property

Public ReadOnly Property Request() As HttpRequest
    Get
        Return BaseContext.Request
    End Get
End Property

This will take care of all but our CreateSiteMap() method error. So without further ado we'll add our CreateSiteMap method. This can be found on page 128. (Note: if you haven't used XDocument to do XML before, it is very particular about where you put your %> characters so follow the below code exactly so that you don't get errors - I learned by hard experience since I hadn't used it before). Add the following for your CreateSiteMap method:

Private Sub CreateSiteMap()
    Response.ContentType = "application/xml" 

    Dim lSiteMapNodes As List(Of SiteMapInfo)
    Using siteMaprpt As New SiteMapRepository
        lSiteMapNodes = siteMaprpt.GetSiteMapNodes
    End Using 

    Dim xSiteMap As XDocument = <?xml version="1.0" encoding="UTF-8"?> 
               <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> 
                    <%= From lSiteMapNode In lSiteMapNodes.AsEnumerable _ 
                    Select <url> 
                        <loc><%= lSiteMapNode.URL %></loc> 
                        <lastmod><%= lSiteMapNode.DateUpdated %></lastmod> 
                        <changefreq>weekly</changefreq> 
                        <priority>0</priority> 
                     </url> %> 
                  </urlset> 

    Response.Write(xSiteMap.ToString())
End Sub

Now we also need to add our handler to the web.config so that our website knows to use it. Add the following to the httpHandlers section of your web.config:

<add verb="GET" path="sitemap.xml" validate="false" type="TBH.SiteMapHandler, TBHBLL, Version=3.5.0.1, Culture=neutral, PublickeyToken=null" />

A URL Rewrite Class

This I feel is one of the less complete modules in the chapter. Originally when I attempted to create the code from this chapter I was only creating code that I found in the solution section. This meant that a couple critical pieces of this module were left out. By looking through the chapter, there was actually much more available.

First we'll need to create a class for our Rewrite code. This should go in a folder called 'Module' in our BLL. Once the folder is created, add a class file and name it URLRewrite.vb. *Gap-Filled*

We get our first code pieces starting on page 124 in the book. Right off, we should make sure that our class implements the IHttpModule interface, so add that to your class definition. Next, we can the code we need for the Init method. We can add that and you class should look something like this:

Public Class URLRewrite
    Implements IHttpModule

    Public Sub Init(ByVal context As System.Web.HttpApplication) _
                     Implements System.Web.IHttpModule.Init
        AddHandler context.BeginRequest, AddressOf BeginRequest
    End Sub

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

   End Sub

End Class

You'll notice that while the book says we should intercept the AuthorizeRequest event that we're using the BeginRequest event. There is a difference between what we see on page 124 and what we read later on pages 135-6, but I went with the one that matched the code download, BeginRequest. *Gap-Filled*

Next, skip over to page 135 and we'll start adding the rest of the module. We will create a variable to use for Regular Expressions. Add the following to your class:

Private Shared wwwRegex As New Regex("https?://www\.", RegexOptions.IgnoreCase Or RegexOptions.Compiled)

Following along on page 136, we'll also add the BeginRequest event handler that we registered in our Init method. This is defined as follows:

Private Sub BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
    Dim app As HttpApplication = CType(sender, HttpApplication)
    Dim Request As HttpRequest = app.Request
    Dim Response As HttpResponse = app.Response 

    Dim sRequestedURL As String = Request.Url.ToString.ToLower
    Dim redirectURL As String = String.Empty
    Dim bWWW As Boolean = wwwRegex.IsMatch(sRequestedURL)
    If bWWW Then redirectURL = wwwRegex.Replace(sRequestedURL, _
           String.Format("{0}://", Request.Url.Scheme))

   Rewrite(app)
End Sub

The Rewrite method is next, it is found on page 137 towards the bottom. Unfortunately there is a SIGNIFICANT difference between the code in the book and the code in the downloaded version. The book talks about doing a 301 redirect and looking up the information in the sitemap table, however the book doesn't seem to implement this. The downloaded code seems to to this, so I will be including that code rather than just the book's code. *Gap-Filled* To start, let's create a helper function for our Rewrite method. Add the following to your code:

Private Sub Do301Redirect(ByVal response As HttpResponse, _
       ByVal redirectURL As String)
    response.RedirectLocation = redirectURL
    response.StatusCode = 301
    response.End()
End Sub

Now let's create our Rewrite method. Add the following:

Private Sub Rewrite(ByVal app As HttpApplication)
    If app.Context.Request.Path.ToLower.EndsWith(".aspx") Then
        Using lSiteMapRst As New SiteMapRepository_
                     (Globals.Settings.DefaultConnectionStringName)
            Dim lURLFile As String = _
                 Helpers.GetURLPath(app.Context.Request.Url.ToString) 

            Dim lSiteMap As SiteMapInfo = lSiteMapRst.GetSiteMapInfoByURL _
                      (lURLFile.Replace(Globals.Settings.devSiteName, ""))
            If Not IsNothing(lSiteMap) Then
                If lSiteMap.RealURL <> lURLFile Then
                    HttpContext.Current.RewritePath("/" & lSiteMap.RealURL, _
                                      False)
                ElseIf lSiteMap.URL <> lSiteMap.RealURL Then
                    Do301Redirect(app.Response, _
                      Path.Combine(Globals.Settings.SiteDomainName, _
                      lSiteMap.URL))
                End If 

            End If
        End Using
    End If
End Sub

I did make one change from the downloaded code, I removed a settings variable since all we did was get our Globals.Settings object and it wasn't that much more work to add the Globals path to the beginning of the settings object when it was called.

You'll also notice that we created an error with our Helpers.GetURLPath that we haven't defined yet. We'll go define that now so that we can successfully build our application.

Another Method for our Helpers Class

I haven't found where much of the Helper class is defined in the book, so I went to the code download for this method. *Gap-Filled* Go over to your Helpers class and we'll add the following method:

Public Shared Function GetURLPath(ByVal sUrl As String) As String
    Dim _Regex As Regex = New Regex("://[^/]+/(?<path>[^?\s<>#""]+)")
    If _Regex.Matches(sUrl).Count > 0 Then
        Return _Regex.Match(sUrl).Groups(1).ToString()
    End If
    Return sUrl
End Function

Configuring the ELMAH Error Logging Add-In

One of my little pet peeves is when you download something and then have to search all over the internet for specific instructions on how to install and configure it. This was the case for some information for getting ELMAH started in our project. I think I'm going to have to pull from a couple articles, as well as using the book, to get it all 100% happy. *Gap-Filled*

Starting on page 139, it talks about configuring ELMAH, so we can get some of our direction from the book, however before we do that, we'll need to get it installed. I found a short article that I based my installation on, basically you:

  1. Download ELMAH.
  2. Extract the Files.
  3. Copy the Elmah.dll into the BIN directory of your website.
  4. Configure ELMAH in your web.config.

We can now go to the book and do a little bit of configuration. First we need to add a Section definition to our web.config, much like we needed to do for our BeerHouseSection for configuration. Add the following to the ConfigSections element of your web.config:

<sectionGroup name="elmah">
    <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
    <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
    <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
    <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
</sectionGroup>

Now we can add the configuration information into an Elmah section in our web.config. Add the following to the Configuration section in your web.config.

<elmah>
    <security allowRemoteAccess="0" />
    <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="" />
    <errorFilter>
        <test>
            <equal binding="HttpStatusCode" value="404" valueType="Int32" />
        </test>
    </errorFilter>
    <errorMail from="error@thebeerhouse.com" to=dogbert@dogbert.com subject="Exception in the Beerhouse Site." async="true" smptPort="25" smtpServer="mail.thebeerhouse.com" />
</elmah>

You'll notice that I have made a correction in the 'equal' element. The book has incorrectly listed this attribute as valueType *Gap-Filled*, the correct attribute is type. Finally for configuration we need to add handlers so that the modules will actually be used. We need to add the following to our system.web section within the HttpModules subsection:

<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" />

and the following into our system.web's httpHandlers section:

<add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" />

Finally, one last piece that I had a harder time finding, and that is setting up the database. To do this, you need to add the ELMAH table and it's 3 stored procedures (thanks NinethSense). If you downloaded the ELMAH packages, there is a folder in the zip file labeled 'DB'. In this folder, you will find the script to setup your DB. I chose to use SQL server so I loaded the SQLServer.sql file into my SQL Server Management Studio and ran the script. Viola the DB is setup.

Epilogue

Well, there you go, hopefully you'll find this helpful, I certainly would have.

Having finished with this particular chapter, I have started reading further (albeit in pieces here and there) in chapter 5 and I think that actually everything will be much easier to understand in these chapters. If they aren't, then look forward to another post in the series...?

Posted: Friday, March 19, 2010 12:29 PM by Yougotiger
Filed under:

Comments

Kal said:

Hello,

The Beer House is pretty frustrating. Most of your frustration appears to be with the book though, and I bought the MVC book, not the webforms one. MVC seems to work, although I have not tested it extensively. But the functionality is way less.

I have fooled with the Webforms 3.5 source and have it running, but quite a lot of things do not work completely or at all. I have a need for a site with most of these features and if it worked would consider it as a starting point. Have you had any success with the final compiled version?

I work with C#, but presumably the functionality is the same.

Kal

# March 26, 2010 3:05 PM

Lee said:

On start up of TheBeerHouse 3.5, I get this error: The underlying provider failed on Open. when this executes: SiteMapInfo lsmi = (from lSiteMapNode in SiteMapctx.SiteMapInfos where lSiteMapNode.URL == URL select lSiteMapNode).FirstOrDefault(); Does anybody know how to fix it? Thanks in anticipation.
# March 28, 2010 10:41 AM

Yougotiger said:

Kal,

I haven't gotten past the 3rd chapter really I spent a while in my spare time getting chapter 3 all figured out, so I haven't moved on, just haven't had the time...

Honestly I haven't tried to get the downloaded code working, I bought the book hoping to learn some best practices programming so I've been trying to understand what's going on. I've never used Entity Framework or Linq to EF before so that's all very new to me and I've been learning a lot about it.

Also I don't know much about the C# version, I'm a VB'er so I was happy to see it orginally done in VB, however I would have prefered figuring out the translation of C# to VB and had fewer 'gaps' in the book explaining how everything fits together...

I haven't done much with MVC either. I attended a Scott Guthrie event a year or two ago where he did some quite a bit of talking around it. To me, it didn't seem like the way I personally wanted to go with my development so I haven't spent any time with it. If I had more time to mess with all this stuff I might try it jus to see what I like best, but since the programming stuff I do isn't my main job function, it get's shelved alot ;-)

Thanks for your comments.

# March 29, 2010 11:46 AM

Yougotiger said:

Lee,

Funny enough I haven't actually tried to ge the code download to work. I prefer to learn by building my own from the book (thus the frustration of incomplete code).

That said, I'd guess that looking at the error, there may be something wrong with you connection string to your DB. I found that the connection string that get's generated from your EF model in your BLL project that would get saved into the app.config is DIFFERENT a little than the one you put into your web.config. I figured out the difference by creating a test website, creating an EF model there and saving the connectionstring into the web.config. Then look at that connection string and see what's different (the double quotes in the connectionstring have to be translated into &quot; or they cause an error.)

The connection isn't actually opened until you run your linq statement (which it looks like what your doing). So my suggestion is to look at your connectionstring first...

Hope that helps.

# March 29, 2010 11:54 AM

Mike said:

I have found both your articles very useful in trying to understand the book. Have you been able to finish the project with more articles?
# October 27, 2010 10:19 AM

Yougotiger said:

Mike,

Sorry, I haven't gotten to it much I've been running a number of projects at work and all the programming stuff has been on the back burner. I've been working on chapter 4, but I haven't finished it yet. I hope to get back to it in the next week or two.

You can see some of the stuff I have been working on in recent posts, I'm working on a 2 or 3 part series right now that I hope to release in the next week or so and get back to developing from the book.

Sorry it's such slow going... your patience is appreciated ;-)

# October 27, 2010 12:00 PM

Copious-Systems said:

Someone referenced this post to answer question "Rewrite the if statement below using a switch statement. (Note it is not necessary to include the declarations?"...

# December 1, 2010 2:23 PM

.Net Discoveries said:

Prologue In a couple previous posts ( here and&#160; here ), we looked in depth at the code in my ASP.Net

# March 14, 2011 2:53 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

Enter the code you see below

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS