Aug 19

Uploading Multiple Files in ASP.NET MVC 5

So as I was working on the Direct Sales CRM application, I came to the part where I needed to upload CSV files to be imported / processed.

From the early days of webforms, I recalled this being quite a pain in the neck.

And, honestly, I wasn’t looking forward to figuring out how to make it work in MVC.

But, boy was I worrying about nothing. NOTHING.

It was so stupid simple, I had it completely implemented, including saving a reference record of the file to the database, in a matter of a few hours.

The following code is a verbatim copy from http://www.aspdotnet-pools.com/. Not that anything will happen to it, but I’m a digital hoarder and would also like a place for me to reference in the event something changes on their end.

Here is the code for the View:

@{
ViewBag.Title = "Multiple file upload with asp.net mvc and HTML5";
}

@using (Html.BeginForm("Index", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<h3>Multiple file upload with asp.net MVCc/MVC3/MVC4/MVC5, C# and HTML5</h3>
<input multiple="multiple" name="files" type="file" value="" />
<input title="Uplad" type="submit" value="Upload You Image" />
<div style="color: red; font-size: 14px;">@ViewBag.Message</div>
}

And here is the code for the Controller

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace ProjectDemo_MVC.Controllers
{
    public class HomeController : Controller
    {
        /// <summary>
        /// Multiple file upload with asp.net mvc and HTML5
        /// </summary>
        /// <returns></returns>
        public ActionResult Index()
        {
            return View();
        }
        /// <summary>
        /// Post method for uploading files
        /// </summary>
        /// <param name="files"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Index(HttpPostedFileBase[] files)
        {
            try
            {
                /*Lopp for multiple files*/
                foreach (HttpPostedFileBase file in files)
                {
                    /*Geting the file name*/
                    string filename = System.IO.Path.GetFileName(file.FileName);
                    /*Saving the file in server folder*/
                    file.SaveAs(Server.MapPath("~/Images/" + filename));
                    string filepathtosave = "Images/" + filename;
                    /*HERE WILL BE YOUR CODE TO SAVE THE FILE DETAIL IN DATA BASE*/
                }

                ViewBag.Message = "File Uploaded successfully.";
            }
            catch
            {
                ViewBag.Message = "Error while uploading the files.";
            }
            return View();
        }

    }
}

I hope it’s as easy for you to implement as it was for me.

I look forward to these other little gems that I’ll find.

Code On!
RJ

Jun 11

My Ventures Into ASP.NET MVC 5, Identity 2, Entity Framework 6, WebAPI 2 and a Chrome Extension

So my wife works as a direct sales consultant.

She just quit her job this morning due to an issue with “The Customer is Always Right” policy.

She feels bad about it, but I kind of encouraged it. And I digress.

Back in late December of 2014, she decided to finally follow up with a friends request to join a network marketing company.

Who hasn’t, right?

Well, it turns out, she’s pretty darn good at it.

If you haven’t already, I would recommend you checking out the Marc Accetta Personality Test. It’s free, and from what I can tell, I haven’t received any followups since I took the test a few weeks ago.

Anyway, my stats are: Green, Yellow, Blue, Red.

Hers? Red, Green and then who cares about the rest.

Her Red makes her a prime candidate for this type of position; but I must be honest and say that it really clashes with the yellow that is inside of me.

None of these characteristics are necessarily bad, but they do give you an idea of how you deal with situations day to day, as well as with other people of different color profiles.

Anyway, since her business has been growing, I told her she needed to get herself a CRM (Customer Relationship Management) system.

She scoffed.

Until she heard someone else mention it at a business networking event; and then it was better than sliced bread.

So annoying.

Being a developer, I then set out on an adventure to find a reasonably priced solution that had a developers API.

The company that was recommended at the meeting had a link that said “Developer Access”. So I signed up to check it out.

Not sure what they meant by “developer access”, but it was nothing like what I had in mind. They emailed me shortly after I signed up trying to get me to sign up for their training classes in order to utilize the system.

When I inquired about an API (Application Programming Interface), they said that if I provided them with a Quickbooks file, they could load it into their system once.

Um, no. That’s not what I thought “Developer Access” meant.

Well, I was now out of options for a reasonably priced CRM solution for my wife that would “automatically” import her customer’s information into her own CRM to allow her to run better automation amongst her customers.

Or was I?

Using the model of “find customers who have a problem and would use your system”, I decided to post to one of her private groups.

And boy did I get some feedback.

I’m only opening up the group to a handful of people who are actually interested, by asking them for a small and nominal monthly fee; mostly to cover hosting expenses during the alpha phase.

And as early adopters, they’ll probably keep the benefits of this system for the same price, but maybe a little more. I’m still debating it at the moment.

Anyway, I’ve had quite an adventurous journey over the last week and a half when I decided to start this.

I will literally have to look up the various things from my browser history and type up a brand new post that will be all “I ran into this problem, and these links helped me figure it out… Then I ran into this problem…”

A week and a half of that. And keep in mind, it wasn’t always the first link that fixed it, and it was often multiple searches with tweaks in the terms that led me to my ultimate solution; only to be beaten down with the next arising issue.

Well, I’m feeling quite motivated in continuing down my path.

Finally, I have a product in the works that people are willing to pay money for, and I’m super stoked to write it that I’m almost developing a case of insomnia.

I hope that my next post will be a digest of what I’ve hunted for thus far, as I haven’t been good about keeping a programming journal up to date.

Until next time…

Happy Coding,
RJ

Dec 11

Some Developer Podcasts and Video Resources

So on my commute in this morning I was just listening to a .NET Rocks episode, where a comment came in about a previous episode. I do listen to the comments that other listeners have, but usually have no point of reference as I only started listening to this podcast.

This time, however, they mentioned one of my new favorite developers John Sonmez at SimpleProgrammer.com and creator of the How To Market Yourself as a Software Developer.

I haven’t purchased his course yet, since I have other large things on my plate that I’m trying to take care of first, but it is on my list as soon as I finish working on/sell a rental I own in another town… Which is inspiration for another topic I have about hiring professionals and using the right tools to get the job done. But I digress.

Anyway, I was excited to get to a computer where I could download the episode they mentioned (It’s episode 980, for those of you who are interested).

Right at the beginning of the episode, Carl talks about tuning in to the New Developers Conference (AKA NDC) on Vimeo.

Which lead me to also see if Oredev (AKA Øredev) had a Vimeo stream. They Do!

It’s not even 9 AM, and the value bombs that I’ve been given have been extremely mind blowing.

Well, I only have a few more weeks at my current job before I move on to my next opportunity, so I’ll try to save watching these for another time.

But until then, I wanted to also share them with you.

So, here they are, in no particular order:

What resources do you use as a developer? Please let me know in the comments below, or via my Contact form.

Nov 11

Moving Multiple Files to Restructure TFS

So today I was tasked with restructuring one of our projects in TFS. It was a standalone web application that was now needing to have a console application added to handle automated invoicing.

I had already moved several folders by hand one by one, I realized there has to be a better way.

And, of course, this problem was answered for me several years ago by the wonderful stackoverflow community.

Well, not really knowing how the wildcard would work with my already moved files, and not really wanting to mess things up, I decided that I would do things a little more explicitly.

So I used the following command in my Visual Studio Command Prompt (VSCP) to get all of the files in the directory:

tf dir "$/Project/dev"

This output a bunch of folders and files, as such:

$/Project/dev:
$App_Code
$Bin
$Folder01
$Folder02
$Folder03
About.aspx
About.aspx.cs
Project.sln
Contact.aspx
Contact.aspx.cs
Default.aspx
Default.aspx.cs
Default_original.aspx.exclude
Disclaimer.aspx
Disclaimer.aspx.cs
FAQ.aspx
FAQ.aspx.cs
Global.asax
Glossary.aspx
Login.aspx.cs.exclude
Login.aspx.exclude
LogOut.aspx
LogOut.aspx.cs
PrivacyPolicy.aspx
PrivacyPolicy.aspx.cs
Registration.aspx
Registration.aspx.cs
Resources.aspx
Resources.aspx.cs
Robots.txt
Site.master
Site.master.cs
Web.config

I then pasted that into one of my favorite text editors (Notepad++), and ran the following Find/Replace regular expression command

Find what: ^(.*)$
Replace with: tf rename "$/Project/dev/\1" "$/Project/dev/Web/\1"

This then gave me the following as output:

tf rename "$/Project/dev/About.aspx" "$/Project/dev/Web/About.aspx"
tf rename "$/Project/dev/About.aspx.cs" "$/Project/dev/Web/About.aspx.cs"
tf rename "$/Project/dev/Contact.aspx" "$/Project/dev/Web/Contact.aspx"
tf rename "$/Project/dev/Contact.aspx.cs" "$/Project/dev/Web/Contact.aspx.cs"
tf rename "$/Project/dev/Default.aspx" "$/Project/dev/Web/Default.aspx"
tf rename "$/Project/dev/Default.aspx.cs" "$/Project/dev/Web/Default.aspx.cs"
tf rename "$/Project/dev/Default_original.aspx.exclude" "$/Project/dev/Web/Default_original.aspx.exclude"
tf rename "$/Project/dev/Disclaimer.aspx" "$/Project/dev/Web/Disclaimer.aspx"
tf rename "$/Project/dev/Disclaimer.aspx.cs" "$/Project/dev/Web/Disclaimer.aspx.cs"
tf rename "$/Project/dev/FAQ.aspx" "$/Project/dev/Web/FAQ.aspx"
tf rename "$/Project/dev/FAQ.aspx.cs" "$/Project/dev/Web/FAQ.aspx.cs"
tf rename "$/Project/dev/Global.asax" "$/Project/dev/Web/Global.asax"
tf rename "$/Project/dev/Glossary.aspx" "$/Project/dev/Web/Glossary.aspx"
tf rename "$/Project/dev/Login.aspx.cs.exclude" "$/Project/dev/Web/Login.aspx.cs.exclude"
tf rename "$/Project/dev/Login.aspx.exclude" "$/Project/dev/Web/Login.aspx.exclude"
tf rename "$/Project/dev/LogOut.aspx" "$/Project/dev/Web/LogOut.aspx"
tf rename "$/Project/dev/LogOut.aspx.cs" "$/Project/dev/Web/LogOut.aspx.cs"
tf rename "$/Project/dev/PrivacyPolicy.aspx" "$/Project/dev/Web/PrivacyPolicy.aspx"
tf rename "$/Project/dev/PrivacyPolicy.aspx.cs" "$/Project/dev/Web/PrivacyPolicy.aspx.cs"
tf rename "$/Project/dev/Registration.aspx" "$/Project/dev/Web/Registration.aspx"
tf rename "$/Project/dev/Registration.aspx.cs" "$/Project/dev/Web/Registration.aspx.cs"
tf rename "$/Project/dev/Resources.aspx" "$/Project/dev/Web/Resources.aspx"
tf rename "$/Project/dev/Resources.aspx.cs" "$/Project/dev/Web/Resources.aspx.cs"
tf rename "$/Project/dev/Robots.txt" "$/Project/dev/Web/Robots.txt"
tf rename "$/Project/dev/Site.master" "$/Project/dev/Web/Site.master"
tf rename "$/Project/dev/Site.master.cs" "$/Project/dev/Web/Site.master.cs"
tf rename "$/Project/dev/Web.config" "$/Project/dev/Web/Web.config"

As you may have noticed, I took out the solution file for this project, since it should reside outside of the project file.

I ran the rename commands in my VSCP, and voila. Files were moved.

Now that the files were moved, I had to update the solution file to accommodate for the newly moved folder. Hopefully you’ve had some experience in doing this, but it’s really not that hard if you haven’t before.

Simply locate the “Project” line, as well as any “PhysicalPath” properties for the web application directory, and update them to be “Web\”. Save the file, and then open it as usual.

I hope this has helped you.

Thanks and code on!
RJ

Oct 16

Oracle Certifications Are Going To Expire

Certification Expired

Today I read an interesting article regarding the soon to be expiration of Oracle Database Certifications.

Now, Oracle in itself doesn’t affect me, but you should always be aware of what’s happening in the industry.

I’m not sure how Oracle operates their certifications, and I don’t really have too much time to dive into them, however, Microsoft offers very specific certifications.

I am certified with test 70-515, which is a somewhat generic certification about Web Applications. However, it is framework specific.

I like that.

I like that a lot.

I like it because it ties me to a particular scope of accomplishment. Yes, it’s broad in the sense that it’s “web application”, but there are way more things that can go into building web applications.

And guess what?

They have certifications for those too!

A certification on Web Services (now commonly referred to as Windows Communications Foundation or WCF), Data Access (which is my next planned certification to be taken in December 2014), and even Windows Forms certifications.

And that’s just the development certs.

There are certifications on server administration, application administration and application usage as well.

So if your company is looking at maintaining an old system, it would be nice to find a professional who knew .NET in it’s 1.0 or 1.1 stages. Or even classic asp / vbscript.

I look forward to attaining my future Microsoft certifications; I hope that they don’t “expire”, but as I’m a lifetime learner, it won’t matter much to me.

Which one would be next?

What are your thoughts on certifications expiring?

Leave a comment below, or shoot me a message through my contact form.

Until next time,
RJCertification Expired

Oct 15

Top Spot Designs WordPress Contact Form Spam

Top Spot Designs Spam

So, it’s always interesting to me when I see some emails be caught by the spam filter, while others aren’t.

Especially when the contents are identical, but the recipient is different.

I run 99% of all of my email addresses (which I have many) by forwarding them to gmail, and sort them out by labels.

Several of my blogs have contact forms.

All of them will attract comment and contact form spam in varying degrees.

I’ve tried to limit these guys based on .htaccess rules, but have only started to thump those who are trying to gain administrative access.

You Shall Not Pass!

It’s a never ending battle.

But, instead of just thumping contact form spam, I’m hoping that maybe some people will start to google these guys who are also getting it, with the shred of hope that people won’t continue doing business with these spammers.

It’s one thing to cold call. It’s another to set up a script and spam the inter-webs.

This is one of those.

From: Jonathan Moore <jmooretopspot@gmail.com>
Subject: Design Question

Message Body:
My name is Jonathan and I’m a website designer. I’m reaching out to see if you’re satisfied with your current website. Are there any changes or improvements that you’d like to make? We’re always looking to help quality businesses such as yourself. I look forward to hearing back from you!

Best Regards,
Jonathan Moore
Top Spot Designs

So, if you happen to get an email from Top Spot Designs, just know that they have spammed several of my blogs. A reputable company will have clients busting down their doors, not the other way around.

Until the next piece of spam,
RJ

Oct 14

How to Spot Spam or Phishing

How To Spot Spam Or Phishing

A few years ago, my wife and I were visiting her grandmother. While there, her aunt started to tell me about a recent incident that involved “hackers” gaining access to her email account.

The conversation was brutal, and it went something like this:

Her: So I got an email that said my password was invalid, and that I had to confirm it.
Me: Um… I hope you didn…
Her: So I clicked the link, and typed in my password
Me: Oh dear God, why did you…
Her: And then that night I got a call from [relative], asking if I was OK, and where I was at.
Me: Yeah, you were…
Her: Of course I’m OK, why wouldn’t I be? Well, [relative] said they got an email stating I was traveling abroad, got injured, and was now stranded in a hotel and needed some money western unioned.
Me: Ok, so how can I help?
Her: So I called the police, since I was hacked
Me: Um, what did the police…
Her: They said they couldn’t help me, and I’d have to contact my mail provider
Me: Ok…
Her: So I called up [Internet Service Provider], and spent two hours on the phone with them, just for them to tell me that they don’t host [Free Email Provider].
Me: Yeah…
Her: Why don’t they host [Free Email Provider]?
Me: They’re two different…
Her: Well anyway, I can’t believe my account got hacked, and [Internet Service Provider] isn’t willing to do anything about it. This is just ridiculous. And the police didn’t even want to help either.
Me: …
Her: So my question is how could these guys hack my account? Is [Internet Service Provider] / [Free Email Provider] not safe anymore?
Me: No, they’re fine. You gave them your password when you clicked on the link.
Her: Well, I thought something was funny, since it didn’t ask me to change my password. But how did they hack my account?
Me: You gave it to them.
Her: How?
Me: You typed it into their webpage.
Her: But that was [Free Email Provider]’s page.
Me: No, you were “phished”
Her: What is fishing?
Me: They sent out some bait through email, and you bit… Hook, line and sinker. You gave them your account information.
Her: But how?

It was at this point that I realized I probably wasn’t getting anywhere, but being appealing to my wife’s aunt was probably better than being an arrogant and pompous jerk-face. So I did the best I could to leave.

The point of this whole post is to help show you ways in which you should probably have your spidey-senses going off and use a little bit of caution when confronted with the situation.

So as I was clearing out my spam folder from one of my own [Free Email Providers], I saw the above pictured email from “Facebook”. I usually stop to take a pause, as my facebook account is connected to this account. Usually, whenever I see something from banks that I don’t do business with, I KNOW that it’s not for me. But in this scenario I have to take a second.

The big thing that popped up right away was the grammar. Notice that no where in the subject line was there a capital letter. None.

Then, the big “lol” give away. Now, I know that Mark Zuckerburg is a young entrepreneur, but I still doubt that he would be fine with something from his security team having the phrase “did you forget your password or something lol”.

So tip number one. Whenever you see bad grammar and internet lingo, you’re probably in for a ride at your expense.

Let’s suppose that you happened to open the email. There are usually one of two scenarios that can happen.

The first scenario is something that is off-topic from the subject line, and a reason why I will always either change the subject, or start a new thread when I feel that the contents of the email has changed from it’s original purpose.

This one happened to be an ad for webcam chats by being a “person” that accentuated a set of large breasts, a large butt, and an itty bitty waist. Sorry spammers, but I’m married and aren’t interested.

So the next tip is to see if the subject and message body coincide. They don’t have to, but it’s generally a good rule of thumb.

The related tip is also “If it’s too good to be true, it probably is.”

There are a handful of good dating websites out there. If you’re in the market, you should do your research and find one that’s best for you. It’s highly unlikely that some random “good looking” stranger is going to email you, and you’ll hit it off. It’s a spammer, and they want your credit card info.

If it’s a pill being advertised, maybe you should take a closer look at your health. I’m a big proponent of homeopathic remedies, and often times it can come down to diet, exercise and sleep. Now, I don’t do this well, but I’m not blaming the snack food industry for me putting a family size bag of deliciousness into my shopping cart. I know it’s not good for me to consume it in one sitting, but I do it anyway. That’s my issue, not theirs. But I digress. You can usually find a way to “cure” your symptom by getting rid of the toxins in your life. So just do it, and be happier and healthier for it. Your wife and waist line will love you for it.

The second scenario is usually an email with an image only. If you have the ability to do disable images from un-verified senders, you should do so. A reputable email will have text based contents in the message, whereas a spam message will have the text embedded on an image. It’s much more difficult for the spam filters to catch these.

So the next tip is to be wary of image only emails.

Many major providers are being targeted recently, so if you bank, shop or use a popular service, just know that you’ll probably see some phishing attempts around these guys. Many of them will say on their official sites that they will never ask you for your password. So, any time you give it, have your spidey senses alert, and be sure it’s appropriate.

And finally, I highly recommend having a few email accounts. One for personal, one for professional, and one for newsletters / spam catching. This will help flag any unwarranted emails from entering where you know you shouldn’t be getting any. This goes against an Inbox Zero approach, but using some gmail features, it can essentially accomplish the same basic thing.

I hope this has helped you out. I’ve been using these methods for over 12 years, and it has served me well. I hope you can do the same starting now.

RJ

Oct 09

What Do You Do When Your Payment Gateway Goes Down?

Edit: 2014/10/10 7:35 – I saw a slew of error messages again, and sure enough they went down last night. That makes it 11 times in 8 months.

So yesterday has marked the 10th time in 8 months that the payment gateway Authorize.NET has gone down.

They are (gathered from the Authorize.net twitter page)

  • 02/26/2014
  • 03/03/2014 (Test environment)
  • 03/05/2014
  • 04/04/2014 (Test environment)
  • 04/30/2014 – 5/1
  • 06/02/2014 – 6/3
  • 07/22/2014
  • 08/19/2014
  • 09/19/2014 (CIM only?)
  • 10/08/2014
  • 10/09/2014

We have 4 large products, and 1 “lemonade stand” (It generates revenue and serves a very niche purpose, but it’s just not at the same level).

Well, at roughly 3:21PM Mountain, we received our first error message of not being able to contact the payment gateway, and have been getting an average of 1-2 per minute.

When you can't accept payment, you're losing money.

When you can’t accept payments, you’re losing money.

This is becoming such a habit, that the URL I used to check twitter was still easily accessible. I just did a search for anyone who was tweeting Authorize.net. I have to admit, that even though I don’t fully condone the use of foul language, this one by Zachary Parton was one of my favorites.

Unfortunately, there isn’t much we can do about it, other than ride out the storm.

When this happened back in June, I wanted to write some code that could flip a switch that would do one or more of the following:

  • On the payment page, let the user know that our credit card gateway is currently down, and disable the button
  • Offer another way to pay
  • Capture the details and batch them when they are back up

However, that is our busy season, and were guided into thinking that it’s not a consistent enough problem to solve as there were other priorities.

4 months later, and this seems to be “a consistent enough problem” that we should at least attempt to mitigate.

Are you affected by the Authorize.net outages?

What do you do when it goes down?

Let me know in the comments below, or by my contact form.

Code On,
RJ

Oct 03

How to Version Control Your Database Using Powershell

I just saw this post regarding why you should put your database into source control.

Unfortunately, it doesn’t get into much of the how, a question many project managers would love to point their developers to.

I’ll remedy that for you.

Since 2004, I have been using this practice. Ok, so I was first forced to, but it really helped pave the way for some really good developer habits (even if it meant doing something the company didn’t want to do… more on that later).

The first program I used was a windows application with a very simple screen configuration. It was the details needed to connect to a SQL Server (server, username, password, catalog), and an additional field for an XML configuration file.

This file essentially looked like this:

<configuration>
    <Schemas>
        <File>Schemas\File01.sql</File>
        <File>Schemas\File02.sql</File>
    </Schemas>
    <Packages>
        <File>Packages\File01.sql</File>
        <File>Packages\File02.sql</File>
    </Packages>
</configuration>

Again, this is a basic concept.

A “Schema” file was to only be run once. So things like table structures, indexes, constraints, etc, would go into this file. After the program ran, it would save the file path into a database table (that it created if it didn’t exist), and would check before running each time so as to not run more than once.

A “Package” file would be run every time. This covers Stored Procedures, Views, Functions, etc. At the beginning of the file, it contained a conditional drop statement if it already existed. This is probably the most controversial part of the program, since the stored procedures will lose it’s compiled run status each time you run a deployment. To that I say: “So?”.

I have taken the concept and written it as a C# windows app, updating it as time went on, and giving it to the companies I worked at. This has drastically changed how development goes. It makes finding differences in updates easier, makes searching for certain table calls faster, and puts you in the right direction for automating your deployments.

The updates I have given it were to rename the “Schemas” to “RunOnce”, “Packages” to “RunAlways”, and given it the concept of folders, in addition to files. This makes one of our multi-tenant projects with our Indian off-shore team development efforts go by much faster. It’s easier to update my software to accomodate their years of developer patterns, than to have them change their entire paradigm to fit my one small feature. I personally think it’s better this way, as the software now fits multiple programming styles, not just the one.

The new XML looks more like this:

<Database>
    <RunOnce>
        <File>Schemas\File01.sql</File>
        <File>Schemas\File02.sql</File>
        <!-- OR -->
        <Directory>Schemas</Directory>
    </RunOnce>
    <RunAlways>
        <File>Packages\File01.sql</File>
        <Directory>Packages\Views</Directory>
        <Directory>Packages\Functions</Directory>
        <Directory>Packages\StoredProcedures</Directory>
    </RunAlways>
</Database>

Anyway, I’ll share some of the pseudo code in how to get this to work properly, so you can get this going in your environment.

function SQL-Create-Connection($connectionstring)
{
# This will return a new System.Data.SqlClient.SqlConnection object based on the connection string
}

function SQL-Get-Connection($server, $catalog, $username, $password, $windows)
{
# This will return a new System.Data.SqlClient.SqlConnection object based on the individual parameters
}

function SQL-Check-Or-Create-DB-Version-Table($connection)
{
# This will create the following database table if it doesn't already exist
# db_version
#   filename VARCHAR(512) NOT NULL
}

function SQL-Execute-NonVersion-File($connection, $fullPath)
{
# This will open a file, split the contents based on "GO" statements, and execute the individual parts.
}

function SQL-Execute-Version-File($connection, $path, $fullPath)
{
    SQL-Check-Or-Create-DB-Version-Table -connection $connection
    
    # Now find out if the $path (relative to the XML configuration file) already exists
    # if ($Record -eq $null)
    # {
    #     try
    #     {
    #         SQL-Execute-NonVersion-File -connection $connection -fullPath $fullPath
    #         # Now insert the file into the version table
    #     }
    #     catch [Exception]
    #     {
    #         WRITE-WARNING "Problem processing file $fullPath"
    #         WRITE-WARNING $_.Exception.Message
    #         Throw
    #     }
    # }
}

function SQL-Execute-Table($connection, $commandText)
{
    # This will take the $commandText and create a table result for it
}

function SQL-Execute-NonQuery($connection, $commandText)
{
    # This will take the $commandText and just execute it
}

function SQL-Execute-Scalar($connection, $commandText)
{
    # This will take the $commandText and return the scalar after execution
}

function DB-Parse-Deployment-XML($XmlDocumentPath, $connection)
{
    # Open the XML Document, and get its directory to handle the relative paths
    $db_directory = $(Get-Item -path "$XmlDocumentPath").Directory.FullName
    $db_directory_regex = $("$($db_directory)\" -replace "\\", "\\")
    1$db_xml = Get-Content $XmlDocumentPath

    try
    {
        # Loop through all of the RunOnce's...
        foreach ($runonce in $db_xml.Database.RunOnce)
        {
            foreach ($ro_file in $runonce.File)
            {
                $ro_file = $ro_file -replace "/", "\"
                $ro_file_full = "$db_directory\$ro_file"
                if (Test-Path $ro_file_full)
                {
                    $results = SQL-Execute-Version-File -connection $connection -path $ro_file -fullPath $ro_file_full
                    # Write-Host "RunOnce Relative File $ro_file"
                    # Write-Host "RunOnce Full File $ro_file_full"
                }
                else
                {
                    Write-Warning "RunOnce file was not found: $ro_file_full" 
                }
            }
            
            foreach ($ro_directory in $runonce.Directory)
            {
                $ro_directory = $ro_directory -replace "/", "\"
                $ro_directory_full = "$db_directory\$ro_directory"
                if (Test-Path $ro_directory_full)
                {
                    $scripts = Get-ChildItem "$ro_directory_full\*" -include *.sql -recurse
                    foreach ($script in $scripts)
                    {
                        $Relative_Script = $script -replace $db_directory_regex, ""
                        $results = SQL-Execute-Version-File -connection $connection -path $Relative_Script -fullPath $script
                    }
                }
                else
                {
                    Write-Warning "RunOnce Directory was not found: $ro_directory_full"
                }
            }
        }
        
        # Loop through all of the RunAlways'...
        foreach ($runalways in $db_xml.Database.RunAlways)
        {
            foreach ($ra_file in $runalways.File)
            {
                $ra_file = $ra_file -replace "/", "\"
                $ra_file_full = "$db_directory\$ra_file"
                if (Test-Path $ra_file_full)
                {
                    $results = SQL-Execute-NonVersion-File -connection $connection -fullPath $ra_file_full
                }
                else
                {
                    Write-Warning "RunAlways file was not found: $ra_file_full"
                }
            }
            
            foreach ($ro_directory in $runalways.Directory)
            {
                $ro_directory = $ro_directory -replace "/", "\"
                $ro_directory_full = "$db_directory\$ro_directory"
                if (Test-Path $ro_directory_full)
                {
                    $scripts = Get-ChildItem "$ro_directory_full\*" -include *.sql -recurse
                    foreach ($script in $scripts)
                    {
                        $results = SQL-Execute-NonVersion-File -connection $connection -fullPath $script
                    }
                }
                else
                {
                    Write-Warning "RunAlways directory was not found: $ro_directory_full"
                }
            }
        }
    }
    catch
    {
        Write-Error "Error in DB-Parse-Deployment-XML..."
    }
}

It took me a few hours to figure out what the contents of the first few methods were, but I think some of the fun as a developer is figuring out what those are. Since you have a very basic roadmap, it shouldn’t take too long to get this going all on your own.

Please feel free to let me know what you think in either the comments, or by shooting me an email from my contact page.

Thanks, and happy coding!

RJ

Sep 22

My S.M.A.R.T. 70-516 Certification Goal

So I’ve been reading a lot and listening to a ton of success and business podcasts, and have decided I would like to set a S.M.A.R.T. goal. For those of you who don’t know, it’s an amazing thing to use when making goals.

Below is my breakdown of my goal.

Specific – The 70-516 exam
Measurable – I will take the test
Achievable – This should be achievable given the 11 or so week time frame
Relevant – This is in line with my current career path (and ultimate MCPD goal)
Time-Bound – I will take the test on Saturday December 13, 2014

Why 11 weeks? Well, I currently have a few things that are a bit more pressing:

  • Fixing up and then selling my house in Cheyenne (nearly there)
  • Expecting a new addition to our family (End of November)
  • Have a few quick (hopefully) side projects I would like to complete

I ordered the self-paced study guides from Amazon (at $4-$5 each, how could you go wrong?), as well as ordered a practice exam for my phone.

So my spare time will be taking short practice exams, or studying/implementing the study guide. Either way, my time will no longer consist of playing solitaire or browsing the community shopping pages on Facebook.

Just think: Using your spare minutes during the day and a few hours a week, you too could have yourself a certification in your desired field. Will you commit to yourself to bettering your career? Let me know in the comments below, or shoot me an email via my contact page. Maybe we can hold each other accountable for our next tests.

Wish me luck,
RJ