Friday, May 31, 2013

Adding items to a drop down list in a ListView (or a GridView for that matter)

I’m in the process of creating a simple “product listing” in an ASP.NET website, just to show some products.. like t-shirts.. display a drop down list with the available sizes, and provide an “Add” button to add to a cart, much like this:


Even though it’s possible this application will barely get any usage within the next 6 months, and will probably display no more than 5 items at a time (it’s for internal company usage), I nonetheless decided I must make my code as efficient as possible.  I took to using a repeater control to iterate through an XmlDataSource and display my product data.  Within an hour, I had this working (hooray!).  Then, I added some form controls (buttons and drop down lists) with dummy data and quickly found that a repeater was a poor choice, as EVERY form control was submitted when the page performed a POST to the server (boo!). [Note: I really don’t understand why this happened.. I didn’t really find anything on this, or research it much, I just tried using a different control on a hunch, and it worked..]

Learning my lesson, I switched over to using a ListView control to instead display my data.  I was still able to use an XmlDataSource for my product info, and now clicking an “Add” button for a product added only that product, not submitting for every form control.  Now, all that was left to do was to bind actual data to my form controls, rather than use the pre-existing dummy data.  This was surprisingly difficult to do.

The task at hand was to edit the “product sizes” drop down list and provide appropriate values based as a comma delimited value in my XML file.  Namely, if the product was “Shirt 1”, and the sizes were “S,M,L”, then S, M and L should all be separate items in the drop down list.  The problem was, it was hard to find out *what* data was binding at any given time.

Fortunately, the solution was simple, I really think I was just not Googling properly.  To add items to the drop down list, I had to use the ItemDataBound event on my ListView control.  At that time, I had to check for my drop down list using the FindControls method, and then use the DataBinder.Eval Function to pull the data for that current row.  As I said, very simple, just not well documented (for the terms I was searching for at least ;)

Anywho, you read this far, the least I can do is give you a code sample as well.  Hope this helps!

            If e.Item.FindControl("ddlSize") IsNot Nothing Then
            'Get our dropdownlist
            Dim ddl As DropDownList = CType(e.Item.FindControl _
            ("ddlSize"), DropDownList)
            'Make sure we didn't already add items to this ctrl
            If ddl.Items.Count = 0 Then

                'get our sizes, which are stored in comma delimited format
                Dim sizes() As String = DataBinder.Eval _
                (e.Item.DataItem, "Sizes").ToString.Split(",")
                'add our items
                For Each s As String In sizes
                    ddl.Items.Add(New ListItem(s, s))

            End If
     End If

Thursday, May 30, 2013

Hikin’ (Ricketts Glen, PA)

The backstory: during the Winter of 2012, I followed a series of posts called “Offline”, in which a writer named Paul Miller from left the Internet for a year and documented his life and times in the real world without having access to any resources or amenities provided by the cyberworld.  Late in 2012, Paul wrote a story about going hiking, and it struck a chord with me.  Paul and his buddy had to take a train, rent a car, and do all this crap just to get to the wilderness.  I can see mountains outside my window at home… I can be on that mountain in 15 minutes flat!  Paul’s article inspired me, and I decided that this Spring\Summer\Fall, I would start to enjoy the outdoors more.  This post is one such chronicle of this proposed adventure.

This past Monday was Memorial Day.  It was a beautiful mid-70’s day with a light, cool breeze.. a perfect day to have off of work.  What better way to honor those who served our country than to enjoy the land they worked so hard to protect.  As such, my cousin (Nick, an experienced hiker and all around learned man) and I made plans to visit a state park, Ricketts Glen.  I had heard how nice the park is, but had never visited it before.  The ride, in total, was about 50-60 minutes, including a visit to the local park office to acquire a trail map.

The trail map indicates that there are several trails available, but the most popular, as well as the most difficult, is the “Falls Trail”.  The trail is names such due to it’s number of waterfalls that you meander around.. 14 in total I believe.  Armed with this knowledge, our backpack full of hikin’ stuff, and ample quantities of water, we set foot.

(Photo courtesy of WikiPedia)

As you can see in the image, the trail is one large loop.  The southern-most point (indicated by the Shingle Cabin) contains the primary parking section to access the Falls trail, and you can visit either side of the trail first – at the Waters Meet mark to be particular about it.  Along the starting trail you are greeted with 3 separate waterfalls (Murray Reynolds, Sheldon Reynolds and Harrison Wright), just to “wet” your appetite (pun intended ;)

Arriving from this point, either side of the trail begins with an ascension up the various hills and rugged terrain, which at some points is rather steep.  Many stones are inlaid to provide as “steps” to go around the waterfalls, which is helpful, but there are many sections that are only 3 ft. wide or so, and stepping over that boundary will most certainly lead to injury due to the fall.  I mention this because I was shocked at how many children I saw attending the park later in the day.  It’s not that kid’s can’t walk this trail, but in all honesty, any parent looking to take their children should be aware.

For me, the highlight of the trip was the Ganoga waterfall.  While other waterfalls on the trail tend to average around 35 feet or so, this waterfall stands tall at 94 feet!  The hike to this waterfall makes the trip worthwhile, but the beauty of each waterfall is incredible.

In any case, Nick and myself actually entered from a different trail-point, and made the trek in roughly 2 hours.  As you can see below, the scenery is WELL worth it.  After our trip, I researched our park more and consistently saw it ranked as one of the top parks to visit in all of the Northeast!  I am not surprised however, having just visited the park, the views are breathtaking, and the trails are groomed considerably well.  In any case, if you haven’t yet visited the park and have the means to do so, I highly recommend you do.  And if you have visited the park before… well.. then I’m sure you understand :)

Finally, for more details on this park, check out

Enjoy the view!

PS - Incase you were curious on how to embed images like this in a blog post, I use SkyDrive, a FREE Microsoft Cloud product, and am also a member of the SkyDrive Insider's program. Should you be interested in becoming an insider, learn more about it here:

Monday, May 20, 2013

Automatic Picture Backup on SkyDrive (subheading iCloud gets all the press)

Incase you didn't know, I'm a huge fan of SkyDrive, a Microsoft based product that let's you store and share document's in the cloud, giving you access to your files no matter where you are.  As such, I have been deemed a member of the SkyDrive Insider's program.  Should you be interested in becoming an insider, learn more about it here:

Purchasing my Windows Phone

I took the leap a few weeks ago and switched my smart phone to a different model.  For several years now, I always used an iPhone.  In the beginning, it’s because it truly was the most innovative phone on the market, but in recent years it’s little more than average.  Meanwhile, I had often thought of getting a Windows Phone.. they do look sharp (note: as if that counts for anything?  Just last night some guy saw my phone and said “wow that’s a nice phone.”  The human in me said “thanks man” trying to sound cool and relaxed, the geek in me internally screamed thinking that I could have been holding a bright shiny yellow cardboard box, and the stranger wouldn’t know any different.  It’s just like buying wine because it has a pretty label, argh!), the OS is presumably polished, and to be honest, nary a negative word is ever said about the Windows Phone.  Therefore, this past week I went out and bought myself a Nokia Lumia 920. 

Of course, what makes a phone a good phone are the features, and in particular the features that set it apart – something that Michael E. Porter would refer to as a Competitive Advantage.  The phone is exactly as advertised… the camera is very nice – they even expose the lens to developer API’s, giving a lot of “app” functionality and option’s, to the point that you can find a number of apps that are specific to taking pictures and video.. pretty cool.  The OS is polished (as referenced above in my presumptions), it flows really really nicely, and the live tiles feature is very cool.  I do have 2 minor complaints however.  1, I wish you could change “some” of the tiles, more-so than just the size of the tile.  I wish I could make my “phone” tile small, but make it a different color, so it would still jump out at me when scrolling through my home screen.  The other feature I’d like to see is some sort of “lock” on the tiles.  As you constantly re-tool and swap live tiles with the phone, all tiles slide up and down, meaning you have to constantly re-learn where some tiles are as you edit your home screen.  These features are nit-picky and wouldn’t prevent me from purchasing this phone, but they are something I’d be excited to see.

Social Media and SkyDrive Integration

Now, there are 2 features that I absolutely love about my phone: it’s integration with social media and with SkyDrive cloud storage.  Windows Phone has a settings section called “Email + Accounts”, where you can input your account information for FaceBook, LinkedIn and Twitter (for more details, check out  Once inserted, all your friends\contacts\followers data is imported into your “People” (generic term for contacts, just didn’t want to re-use that term here).  When browsing People, it provides a one-stop-shop to send someone an email, SMS message, FaceBook chat, write on their wall, or even tweet them.  FaceBook notifications are shared seamlessly, and all new posted images on Twitter show in a social “camera roll” within your Photo’s section.  It really is a novel concept, as the phone almost “updates” itself.  Soon you’ll see yourself checking your phone for social updates in the same fashion as you would find yourself checking your phone for email.

And last, but certainly not least, is my other favorite setting, the integrated storage with SkyDrive.  I know I put a “disclaimer” up above about my SkyDrive Insider status.. trust me.. this feature is great because of how well it works.  In your “Email + Accounts” section, you can provide a Windows Live ID and password.  Once done, it will sync any “” email that you have through that service, but it will also “silently” integrate with your SkyDrive storage.  In doing so, all photo’s and video’s you take with your phone are automatically backed up on SkyDrive.  These aren’t stored in some proprietary backup file like some “other iService”, instead each individual file is available like a normal “jpeg” or video file.  You can download the images one\some\all when necessary from any PC whenever you have Internet access.  Additionally, when you store Office documents in your SkyDrive (Word, Excel, OneNote, or PowerPoint in particular), those files also appear for edit\review in the “Office” Hub, where you have native file support for Office files.  There isn’t any special downloading, it just sync’s on the fly because of how you added your account in the “Email + Accounts” setting.  It works as quietly and “seamlessly” (not to overuse that term..) as you would hope it would.  It doesn’t prompt you, or scream about how or what it’s doing, it just writes and syncs files, waiting for that time that you decide to drop your phone in the toilet, voiding your warranty and causing you to get a new phone.. but at least you won’t have to resync all your data on your new Windows Phone (because I guarantee you go and get another one), since all that data is in the Cloud!

Some Synced Pictures from SkyDrive

Thursday, May 2, 2013

An Introduction to Querying and Creating Report Subscriptions using the ReportingService2010 Web Service and SharePoint

I recently found the need to create a custom reporting service subscription manager for my workplace.  We currently employ SQL Server Reporting Services to generate and maintain our reports for our end users, and after a little digging around I uncovered the ReportingService2010 web services exposed by SQL SSRS -  I wasn't aware of it at the time, but the way Microsoft SharePoint and so many of these other Microsoft Services interact is all via web services.  When SharePoint provides links to manage shared schedules or generate reports, many of the functions they provide access to are just web services enabled by the service you are interacting with.  This means that you can access the same data and functions that is provided "out of the box" by many software packages, if you're willing to slap on your own UI and learn how to interact with the appropriate API's.  This post is to discuss the latter half of that statement and introduce you to working with the ReportingService2010 SOAP enabled web services.

Let's start here, the ReportingService2010 Class embodies many of the methods and properties used to work with both Reporting Services Native Mode as well as SharePoint Integrated Mode.  The examples I'll provide below will be aimed towards a SharePoint Implementation, but in browsing the MSDN documentation, you'll see that many of the methods are the same, the differences are typically in what parameter data you may be passing back and forth.

So let's get started.  Before you do anything else to work with your Reporting Service API's, in your Visual Studio Solution generate a web service reference to your SSRS server.  The format to connect to your service should be along the lines of: http://_Server_Name_/ReportServer/ReportService2010.asmx?wsdl.  Once created, add your namespace to your Using\Imports statement on your class files.

Now that that's done, let's look at some of the common methods you may need to use.  Anytime you need to interact with your reporting server, you'll need to authenticate.  An easy way to do so is by using the following:

Dim rs As New ReportingService2010
rs.Credentials = System.Net.CredentialCache.DefaultCredentials

What will this do?  At runtime, the credentials will take on the credentials of the user running the application.  If this is a website for example, this will be the service account assigned to the application pool in IIS.  However, if you enable identity impersonation (, then the DefaultCredentials will be of the user accessing the website.

This can be a very handy feature, but in my implementation, I also found the need to create new subscriptions, or edit\delete existing subscriptions.  For something like this, unless all of your users are "power" users in SharePoint (which I assume they're not), you can also specify a particular user account to run under.  You can do so by creating a new NetworkCredential object, like so:

rs.Credentials = New System.Net.NetworkCredential("<UserName>", "<Password>", "<DOMAIN>")

This feature was the most important feature I had worked with, because there are times that you *need* to perform actions under a higher privileged account (like create or delete subscriptions), and there are times that you just need to read data for the current user.  Keep this concept in mind as you begin to interact with your SSRS implementation.

Note: Herein, any reference to the ReportService2010 object will be referenced as if it has been “defined” as rs.

SSRS - Working with Reports, Subscriptions and Schedules

Let's start simple.  Let's say you want to programmatically access a report.  Each Report is referred to as a "CatalogItem" object (  To get your reports, just call the ListChildren method of your ReportingService2010 object, providing the URL to the SharePoint library that contains your items.  Here's such an example:
Dim r As List(Of CatalogItem) = rs.ListChildren(" Library", False).ToList()

The first parameter is the URL where your RDL reports are located, the second boolean parameter defines whether or not the result set should return recursive items.  Otherwise, it's as simple as that.  Now you'll have a List of reports where you can determine when the item was created, it's name, description.. all that good stuff. 

Chances are you grabbed that line of code, pasted it into your IDE and ran it, and hopefully it worked just fine for you.  However, I want to make sure you are aware that the ListChildren method will return results based on the context of the Credentials in your ReportService2010 object.  So if user's don't have permissions to an Library, or an object in that Library, they will not receive results for the ListChildren call.

Let's say you want to have access to what Shared Schedules you created on your site, here you can receive a List of all Schedules currently stored using the ListSchedules method:

Dim schedules As List(Of Schedule) = rs.ListSchedules("").ToList()

Notice I didn't specify a particular report library or anything like that.  Since schedules are stored at the site level, and not within a particular library or anything like that, you only need to specify the location of your SharePoint site where you defined your schedules. 

ListSchedules returns Schedule objects, defined here: The Schedule object offer's a number of very helpful properties including the Last Run Time, the Next Run Time and the Description of the schedule.  However, the most important property exposed here is the ScheduleID, a GUID based value that allows you to reuse the schedule at a later date.  More on this value later.

Let's say for a moment that we want to determine what parameters a report can accept.  This is done with the GetItemParameters( method, as shown below.  This method will return an array of ItemParameter objects ( and contains pertinent information including the display text for the parameter, the prompt text for the parameter, default values (if any) and *acceptable values* (if any)... which is very important when creating new subscriptions using parameters, as the SOAP API's will thrown an exception if a parameter is used with a value that is not within this list of values.  To call this method, you just need to pass the report path for your report, including the file name with the rdl extension.  You also have the option to specify a "historical" report (incase you want to check a report snapshot), a boolean based "ForRendering" parameter, an array of ParameterValues that can be validated against the report upon calling the method, and a DataSourceCredentials object that can be used to validate any query based parameters.  However, if you simply wanted to just get the Parameters for a report, the following code will do so for you:

Dim reportPath As String = " Library/SomeReport.rdl"
Dim forRendering As Boolean = True
Dim historyID As String = Nothing
Dim values As ParameterValue() = Nothing
Dim credentials As DataSourceCredentials() = Nothing
Dim parameters As ItemParameter() = rs.GetItemParameters(reportPath, historyID, forRendering, values, credentials)

OK, we can call SharePoint and return some report names and shared schedule information, which is cool, but let's take it a step further.  My need to work with these API's was to enable some usability with creating and editing subscriptions.  We can access subscriptions using the ListSubscriptions method, which only requires the path to your report library, along with the name of the report you are requesting access for.  ListSubscriptions returns a dataset of Subscription objects, which is defined in detail here -  The most important property exposed here is the SubscriptionID.  Querying your SSRS server using the SOAP API's will require a subscriptionID in most cases, and further down in this post you'll see where\when this comes in handy. If you perform the following, you'll get a List of all subscriptions for the report *based on the user context* - so if you want all subscriptions, use a priveleged account.  Otherwise, the subscriptions will be based on who is running the command:

Dim subs As List(Of Subscription) = rs.ListSubscriptions(" Library/SomeReport.rdl").ToList()

At this point, our List will contain Subscription objects, but what about the data they contain?  The Subscription object contains data about who the Owner is, or the Path of where the Report file is located, but that isn't too insightful.  If we want to learn more about the specifics of a Subscription, such as who is receiving report data, what its current state is, or who the owner is, among a plethora of other details, we use the GetSubscriptionProperties method.  Let's start simple, I'll give you some code to look at, and then explain what this all is.

Dim subID As String = "<Some Sub ID>"
Dim subExtensionSettings As ExtensionSettings
Dim subDescription As String = ""
Dim subActiveState As ActiveState
Dim subStatus As String = ""
Dim subEventType As String = ""
Dim subMatchData As String = ""
Dim subParams() As ParameterValue

Dim subscriptionOwner as String = rs.GetSubscriptionProperties(subID, subExtensionSettings, subDescription, subActiveState, subStatus, subEventType, subMatchData, subParams)
The GetSubscriptionProperties method, which is defined here, returns a string value indicating who the current *owner* is for the provided Subscription.  Consider the owner as who the report runs "as" (which was a handy concept for me, as many of my subscriptions do take into consideration who the user is to provide certain data).  As far as the other parameters are concerned, these are all output parameters populated based on the result of the API call.  So in reality, all you need to retrieve information here is just the SubscriptionID, the rest gets populated.

The true knowledge of the Subscription information is contained within these returned values, of course, so let's walk through them.

subExtentionSettings is an ExtensionSettings object (, which is rather boring as it only contains an array of ParameterValues and an Extension string property that defines what the report subscription is.  As an example, for email based reports, Extension is set to "Report Server Email".  ParameterValues is a collection of key\value items that contains the basic information about a subscription, including the following:

- TO
- CC
- ReplyTo
- Subject
- Comment
- Priority (Low, Normal, High)
- IncludeLink (Boolean)
- IncludeReport (Boolean)
- RenderFormat (The report file type that is attached to the email.   Possible values are WORD, PDF, ATOM, RPL, IMAGE, CSV, EXCELOPENXML, HTML4.0, WORKOPENXML, MHTML, EXCEL, and XML)

subDescription is just a string typed description of the subscription, such as "Send e-mail to".

subActiveState is an ActiveState object(  As indicated in MSDN, this object "Represents information about the active state of a subscription. An ActiveState object is returned by methods that query subscription properties.  The active state of a subscription indicates whether a subscription is currently active and valid. If there is a problem with the subscription, the active state of a subscription can be queried programmatically to determine the cause of the problem. More than one error condition can cause a subscription to be inactive. Subscriptions that are inactive are not processed by the report server until the cause of the error is resolved.".  When creating a new subscription, an object of this type needs to be passed, but it really is to determine the current "state" of a subscription when a subscription fails for some reason, not so much to provide input parameters.

subStatus represents the most recent status of the subscription.  For example, a successful emailed subscription will read "Mail sent to".

subEventType represents the type of subscription you are querying. There are 2 main types, a Timed Subscription, and a Data Driven Subscription.  The EventType parameter will indicate what type of subscription this is.

subMatchData is a string based parameter, but it will provide 2 different types of values, either a GUID or an XML string.  The difference here is whether or not you are using a shared schedule for this subscription.  If you are, then the GUID value provided is the ScheduleID of the Shared Schedule (meaning you can use this to match up with a ScheduleID from the ListSchedules method discussed earlier).  If you receive XML, it is because the subscription is using a "custom" schedule, and the XML defines what days of the week the report "event" should occur, along with what time.

subParams is an array of ParameterValues (much like those defined above in our ActiveState object).  These values however are the input values that are used to generate a report.  So when you are interacting with a report, and you are requested for a start date, or an end date, or a user ID, or a customer number, etc. these values are all found here.  There is one exception to this rule, and that is default values.  If a report can accept "default" values, and the value for the parameter was chosen as default when the report is created, then this value will not exist in the ParameterValues array, as it is simply not stored.  Let me repeat this, the value isnt stored as "NULL" or "BLANK" or "DEFAULT", it is simply *not there*.  If you want to retrieve a list of available parameters for a report, you would use the GetItemParameters method (discussed above).

Creating A New Subscription

OK, with all of the knowledge attained above, the last item I'll cover is creating a new subscription, which basically uses a combination of the properties and objects defined above.

First, your ReportingService2010 credentials object must be a privileged account to create a subscription.  In my case, I defined a "service account" on my domain to perform such actions, and allow this service account to create subscriptions on behalf of a user.  However, the creator of a subscription is also the default *owner* of the subscription, and as we discussed earlier, the owner is who the report runs *as*.  Keep this in mind, as you may want to alter who the owner is after creating the subscription (which is simple!).

Creating a subscription is simple, all you need is the correct data to generate the subscription in your system, namely the report your creating a subscription for, who it's to be emailed to, the attachment type, a description, an event type, the schedule to send the report, and the parameters for the report (all this sound familiar from above?)

My code to generate a new subscription is similar to the following...

'DONT COPY AND PASTE THIS CODE, IT WONT WORK!  Keep reading below to understand why and what you need to do..
Dim reportPath As String = " Library/SomeReport.rdl"
Dim newSubExtensionSettings As ExtensionSettings = GetEmailSettings()
Dim newSubDescription As String = "Send e-mail to"
Dim subActiveState As New ActiveState
Dim subStatus As String = "New Subscription"
Dim newSubEventType As String = "TimedSubscription"
Dim newSubMatchData As String = "<Some Shared ScheduleID>"
Dim newSubParams() As ParameterValue = GetReportParameters()

Dim subscriptionID As String = rs.CreateSubscription(reportPath, newSubExtensionSettings, newSubDescription, newSubEventType, newSubMatchData, newSubParams)

As you can see in the comment, that code wont work above for 2 reasons, and it's really because I'm avoiding code bloat here.  newSubExtensions is looking to call a custom method called GetEmailSettings.  All this does is create a new ExtensionSettings object, and populate the ParameterValue array with the appropriate data.  What is the *appropriate* data?  Scroll up above, it's a list of TO, CC, Subject, etc. as defined above.  These are just key\value pairs for the subscription, nothing more.

newSubMatchData should pass either formatted XML or a ScheduleID of a shared schedule on your SharePoint site.  For my application, I just created shared schedules and ensured that all users only had the ability to use a shared schedule and NOT any custom subscription times, just to make maintenance periods that much easier.

Finally, newSubParams calls GetReportParameters, returning an array of ParameterValues.  Much like the ExtensionSettings, you just need to generate some key\value data that aligns with the acceptable parameters of your report (found by using the GetItemParameters method, described above.)  So my custom GetReportParameters method simply has some logic to iterate through my form, grab the appropriate data, and generate this array of values.

Once you have all this data populated, and you call the CreateSubscription method, SSRS will attempt to generate a subscription.  If any parameter values are incorrect, or if any other data seems invalid, you'll get an Exception.  If it works, a string is returned, which is your SubscriptionID, and it'll look like a GUID.

The last thing you may want to do (I did it, but it's theoretically optional) is to update the subscription owner, for reasons defined above.  Doing so is very simple, just call the ChangeSubscriptionOwner method, like shown here:

Dim subID As String
Dim ownerName as String

rs.ChangeSubscriptionOwner(subID, ownerName)
Told you it was simple!

Updating An Existing Subscription

At the present time, you can't update a subscription (unless I missed it somewhere in the documentation -  So, when I need to update a subscription, I just delete the current subscription, and then recreate a new one.  Deleting a subscription is as simple as executing the line below:

That's everything in a nutshell, hopefully this gives you a solid anchor point to develop your own custom report subscription application... hope this helps!