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

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

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

Apr 15

Why I love .NET – Reason 314 – Config Files

While working the day job, I am porting over some sites from one virtual site to another.

Our clients will typically have their own external domain, which will get http redirected to a client specific sub-domain. Unfortunately, each external website has pretty much the exact same redirect page, under construction page, landing page, etc. The only difference is the redirect URL. Which, luckily in our case, can be found in the database (though, not really used).

During a deployment, we must manually turn each of the default pages to use the Under Construction page in IIS. This will prevent the redirect from occurring. However, you can see how the success of our company could lead to 4 hour long deployments, just in switching the default page.

“Why not script it?” you might be asking… That’s really the equivalent of saying “buy a nail gun if you’re nailing things” and not asking the question “is this implementation the right implementation?” In this case, it’s not.

I wrote an app that will determine the exact same thing, and do it in a fraction of the footprint, and will let us grow with little production deployment pains.

Unfortunately, we will still need to implement the updates in the production environment to make this a reality. No small task if you’re looking at doing this through the IIS manager.

But, let’s not forget that this is a server application, and therefore, should have itself a command line interface. IT DOES! It’s called appcmd, and is found in the %windows%\System32\inetsrv directory. But after doing some research, it looks like it may have some limitations when retrieving the data.

Fortunately, there is another way, and it’s found in the %windows%\System32\inetsrv\config\applicationHost.config file. I will be playing with this more in the next few hours, and so I hope to report some success.

Apr 14

New Web-based SQL Query Tool

I had an idea at work a while ago that would allow an authorized user (based on the Intranet) to dynamically execute a stored procedure in a designated schema.

The need arose when I discovered that our network/system administrator was searching for saved queries, changing some variables, connecting to the production server, and then executing them.

I thought it would be nice to put these into their own schema that a page could find these, and prepare a nice and easy way for them to be executed.

Development is still in process, and I’m hoping to have version 1 released in the next few weeks.

If you or your company would like to stay up to date on this, or if you have any questions or input, please ship me an email in the form below.

What will come in these versions:

Free Paid Ultimate
Get a list of procedures based on a schema X X X
Display meta-data about procedure X X X
Display meta-data about parameters X X X
Data input – Textbox X X X
Data input – Checkboxes X X
Data input – Radio Buttons X X
Data input – Drop Down List X X
Populate input with Data (SQL) X X
Populate input with Data (String) X X
Populate cascading input with Data (SQL) X
Data Validation – More Than/Equal X X
Data Validation – Less Than/Equal X X
Data Validation – Required X X
Data Validation – Is Date X X
Data Validation – Is Numeric X X
Data Validation – Regular Expression X X
Visual way to manage Proc X

[contact-form-7 id=”204″ title=”SQL Tool”]

Sep 17

Connection Strings

Every time I want to create a new project, I either have to look into previous projects, or go to ConnectionStrings.com. It’s a wonderful site that you can use to find the specific connection string that you may ever need.

For me, however, I typically use 1 of 2 connection strings. It either has a username/password, or it uses integrated security (currently logged in user).

SQL Server 2008 Connection String with User name and Password:

Data Source=myServerAddress;Initial Catalog=myDataBase;User Id=myUsername;Password=myPassword;

SQL Server 2008 Connection String with Integrated Security:

Data Source=myServerAddress;Initial Catalog=myDataBase;Integrated Security=SSPI;

Jul 11

.NET Connection Strings – To Encrypt or Not to Encrypt

Recently I was tasked with researching connection string best practices, and employing them at the day job. We want a better way to manage all of the connection strings.

I suggested moving the connection strings into the machine.config unencrypted. This will accomplish multiple things.

  • Centralizes connection strings to one area for all projects residing on that server
  • Easy to search, maintain, and update since no encryption/decryption is required
  • “Set it and Forget it” – Deployments to the various environments (DEV, STG, TRN, PRD) won’t need to update connection string after every deployment cycle

But there are some downsides

  • Need to save across multiple .NET machine.config sources
    The simple workaround is to keep a configSource file in the root, and utilize a batch file to copy into each frameworks config directory (except 1.1 and below)
  • Unencrypted connection strings means an intruder has easier access to information (more info below)
  • Updating a connection string for one project has the potential of disrupting every project on that server
    But I hope you are doing these updates during off hours, so the impact will be minimal.

I will make some mentions of things in this blog that I really hope is not news to anyone. Having your own 2-way hashing/encrypting algorithm will only slow down a hacker. My experience has been that you must “hide” the key, but still reference it. A good file search tool can quickly point to this unlock key to get your connection string. By my estimation, the tool I use can sift through 80 megabytes of data (including text files, images, and binary documents such as PDFs, Word and Excel documents) in less than 8 minutes. Then using a decompiler they can easily get your information.

I was once tasked to take over a project where the previous developer was holding the source code ransom for a bigger bonus. With the awesome experience in programming I had developed over the years, it took me about 45 minutes to get everything I needed into a nice small package. And that was just so I had something pretty to work with, not just mining for anything specific.

I’m sure that if a somewhat experience hacker ever got into your machine, an encrypted connection string is only going to slow him down by maybe 15 minutes, assuming he already has the tools necessary to do his digging. After all, it’s all about the time. If he’s already gained access, knows what he’s looking for, and wasn’t taught the Boy Scout model of “Be Prepared” (even if it’s to be used for evil), the chances of him being caught will be much higher as he’s doing some Google research while breaking into your system.

So, my recommendation is to just keep unencrypted connection strings in the machine.config file(s), as it will save your Operations department many compounding hours in maintenance over the lifetime of the servers.

Mar 23

Why You Need a DLL Page For Your .NET Projects

This post is all about User Acceptance Testing, and why you’ll want a DLL page.

In any good development environment, you’ll want to make sure you have some things covered.
1. Source Control (Source Safe, Vault, Subversion, etc)
2. Documentation Tools
3. Test Plan

With the test plan, you’ll want to mark which DLL you are testing against. That way, you can tell if a release has been updated, or if deployment procedures haven’t been strictly adhered to. Of course, without automatic DLL versioning in the latter part of Visual Studio releases (more on this later), you as the developer will need to make these part of your deployment habits.

In your project, create a DLL.aspx page, and drop the following Grid View source where necessary

<asp:GridView ID="gvDLL" runat="server" AutoGenerateColumns="false">
	<Columns>
		<asp:BoundField HeaderText="File Name" DataField="FileName" />
		<asp:BoundField HeaderText="Version" DataField="FileVersion" />
	</Columns>
</asp:GridView>

And finally, put this in your DLL.aspx.vb page.

Imports System.IO

Public Class DLL
	Inherits System.Web.UI.Page

	Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
		BindDlls()
	End Sub

	Protected Sub BindDlls()
		gvDLL.DataSource = GetDllInformation(Server.MapPath(".") + "bin")
		gvDLL.DataBind()
	End Sub

	Protected Function GetDllInformation(ByVal psFolder As String) As DataSet
		'Create the (empty) DataSet object...
		Dim dt As New DataTable("DLLInformation")
		dt.Columns.Add("FileName")
		dt.Columns.Add("FileVersion")
		Dim ds As New DataSet()
		ds.Tables.Add(dt)

		'Now gather all of the DLLs
		If Directory.Exists(psFolder) Then
			Dim sFiles As String() = Directory.GetFiles(psFolder, "*.dll", SearchOption.TopDirectoryOnly)
			For Each sFile In sFiles
				Dim fvi As FileVersionInfo = FileVersionInfo.GetVersionInfo(sFile)
				Dim dr As DataRow = ds.Tables(0).NewRow()
				Dim fi As New FileInfo(sFile)
				dr("FileName") = fi.Name
				dr("FileVersion") = fvi.FileVersion
				ds.Tables(0).Rows.Add(dr)
			Next
		End If

		Return ds
	End Function
End Class

To use it, simply send your testers to http://domain/DLL.aspx.

Enjoy!

Mar 17

Why hardcoding is bad, especially in .NET

So, I had a habit of doing inline navigation by doing the following “Lazy Loading” method (code from administration navigation that handles look up tables):

Private Sub ChangeNavigation(ByVal pLinkButton As LinkButton)
	lnkUsers.CssClass = ""
	pLinkButton.CssClass = "selected"
	Select Case pLinkButton.ID
		Case "lnkUsers"
			mvData.SetActiveView(vwUsers)
			BindUsers()

		Case "lnkDivisions"
			mvData.SetActiveView(vwDivisions)
			BindDivisions()

		Case "lnkWithdrawalTypes"
			mvData.SetActiveView(vwWithdrawalType)
			BindWithdrawalTypes()

		Case "lnkMemoTypes"
			mvData.SetActiveView(vwMemoType)
			BindMemoTypes()

		Case "lnkWithdrawalTypePrefix"
			mvData.SetActiveView(vwWithdrawalTypePrefix)
			BindWithdrawalTypePrefix()

	End Select
End Sub

Somewhere down the line, a new request was made to make a certain item “plural”. This then caused some unintended consequences of having run-time issues because the string didn’t compare. And let’s not get started on the fact that it’s case sensitive. It’s actually one of the main reasons why I try to utilize enumerations whenever possible… They’re short, simple, and will break if you type it wrong.

Well, due to the issue, I realized I should utilize .NET’s compiler and properties to my advantage. With that, I turned

Case "lnkDivisions"

to

Case lnkDivisions.ID

VOILA. It slices! It dices! It compiles! Make an update to the text and it will still work. Rename the control without updating the case statement, and it will not compile. You are forced to fix it without stumbling across it during User Acceptance Testing.

Happy Coding!