Sending Multipart- Form Using AJAX

As part of the continued articles on submitting Multi-part Form using Jquery and AJAX. I have attached the JavaScript part and the web.api part to a project that I have created. As I stated in the earlier articles on this subject. You can accomplish AJAX submission a lot easier if it wasn’t for the need to send a file. Assuming that you are targeting an audience that is using the latest browsers this will work. View the in-line comments for a better understanding. (If you need to target browsers that do not have FormData then check my other article out. (Using Non FormData browsers)

These two sections of code will bind your JavaScript to your web.api form. When you submit a multipart form all of the form elements along with the file gets sent to the web.api. You have to be able to parse the file from the elements in order to further process. There are additional articles that supports this article.

* How to access multipart form values using multipartmemorystreamprovider (coming soon)
* assigning Multipart Data elements to a strongly typed class (Coming soon)
* Having to use support IE 9 browsers on Multipart Data AJAX Calls


	//Create an instance of the FormData object
	var jMyForm = new FormData();

	//You can use this or just add the whole form objects using this.
	//var formData = new FormData([formName]);

	//The problem with the item above is that there might be elements
	//that you do not need to go.  That is why I build it manually as below.
	jMyForm.append("FirstName", $('#FirstName').val());
	jMyForm.append("LastName", $('#LastName').val());
	jMyForm.append("Address1", $('#Address1').val());
	jMyForm.append("Address2", $('#Address2').val());
	jMyForm.append("City", $('#City').val());
	jMyForm.append("State", $('#State').val());
	jMyForm.append("ZipCode", $('#ZipCode').val());
	jMyForm.append("Email", $('#Email').val());
	jMyForm.append("PhoneHome", $('#PhoneHome').val());
	jMyForm.append("PhoneCell", $('#PhoneCell').val());
	jMyForm.append("Available", $('#Available').val());
	jMyForm.append("Salary", $('#Salary').val());
	jMyForm.append("chkEmployeed", $('#chkEmployeed').val());
	jMyForm.append("HighSchool", $('#HighSchool').val());
	jMyForm.append("College", $('#College').val());
	jMyForm.append("Training", $('#Training').val());

	//Add File Object
	jMyForm.append("file", $('#file').get(0).files[0]);

	//Standard AJAX JQuery Call.  **Pay attention to the options.
	$.ajax({
		url: /api/SendEmail,
		type: "POST",
		data: jMyForm,
		mimeType: "multipart/form-data",
		contentType: false,
		cache: false,
		processData: false,
		dataType: "text",
		success: function (data, textStatus, jqXHR) {
			//There is other ways of parsing the object.
			//But you get the idea of the things you could do.
			var myObject = eval('(' + data + ')');
			$('#status').show().html(myObject.Message)
			//Hides the button after it when successfully
			if (myObject.Status == 'Success') {
				$('#submit').hide()
			}
		},
		error: function (jqXHR, textStatus, errorThrown) {
			var myObject = eval('(' + jqXHR + ')');
			$('#status').show().html(myObject.Message)
			//Place to do additional operations for a failed save.

		}
	});

There are a lot of sites that have pieces of this code but nowhere is there a complete code examples for web.api and vb.net. I am also not saving the actual file but attaching it to an email. See comments in code for better explanations. Some key points to remember is that I am sending an AJAX Call to send an email with an attached file.

Imports System.Net
Imports System.Web.Http
Imports System.Net.Mail
Imports System.Net.Http
Imports System.IO
Imports System.Threading.Tasks
Imports System.Net.Mime
Imports InMemoryMultipartFormDataStreamProvider

Public Class ApplicantController
    Inherits ApiController

    <HttpPost> _
    <ActionName("SendEmail")>
    Public Function PostValue() As Task(Of HttpResponseMessage)

        ' Check if the request contains multipart/form-data.
        If Not Request.Content.IsMimeMultipartContent() Then
            Throw New HttpResponseException(HttpStatusCode.UnsupportedMediaType)
        End If

		'Helper class that helps with accessing the form data and FILE
		'See article called (How to access multipart form values using multipartmemorystreamprovider)
		'for detailed discussion on this.

        Dim provider = New InMemoryMultipartFormDataStreamProvider()
        Dim finalfile As System.IO.Stream
        Dim task1 = Request.Content.ReadAsMultipartAsync(provider).ContinueWith(Of HttpResponseMessage) _
                  (Function(t)
                       Try
                           Dim cp = New Applications.General

                           'Reads each property and tries to assign a the value to it
                           'From the HttpContent.
						   'There might be an easier way to bind the form data values to a class but this makes prevents thrown errors.
						   'See article called (assigning Multi-part Data elements to a strongly typed class)
                           For Each prop In GetType(Applications.General).GetProperties()
                               Dim queryParam = provider.FormData.GetValues(prop.Name)
                               If queryParam IsNot Nothing Then
                                   prop.SetValue(cp, queryParam(0), Nothing)
                               End If
                           Next

						   'If you want to save the memory stream to a file then just capture the
						   'filefile and save the system.io.stream to where ever you want.  This could be file
						   'database, or in my case to email attachment. (Not shown)
                           'Add all Files to IList Collection
                           Dim files As IList(Of HttpContent) = provider.Files
                           For Each item In files
                               If Not IsNothing(item.Headers.ContentDisposition.FileName) Then
                                   Dim mFileName As String = item.Headers.ContentDisposition.FileName.Replace("""", "")
                                   Dim ext As String = Path.GetExtension(mFileName)
                                   Dim filename As String = Path.GetFileNameWithoutExtension(mFileName)
                                   finalfile = item.ReadAsStreamAsync.Result
                               End If
                           Next

						   ' Do anything else you want to do with data.  You can then call the General class
						   ' cp.Address2
						   '*******************************Anything else*******************************************

						   'You could send back a pure JSON response IF YOU ARE TARGETING only browsers that can handle FormData.
						   'Since I have to allow IE 9 users then implementing this method handles using an iFrame.
						   ' See article (Having to use support IE 9 browsers on Multi-part Data AJAX Calls )
                           Dim jsons As String = "{""Status"": ""Success"",""Message"": ""Email Sent Successfully.""}"
                           Dim response = New HttpResponseMessage(HttpStatusCode.OK)
                           response.Content = New StringContent(jsons, Encoding.UTF8, "text/plain")
                           Return response

                       Catch ex As Exception
						' Not completed coded out.  But you get the idea.
                           Dim tr As String = ex.Message

                       End Try

                       Dim json As String = "{""Status"": ""Error"",""Message"": ""Must use a valid document""}"
                       Dim resp = New HttpResponseMessage(HttpStatusCode.OK)
                       resp.Content = New StringContent(json, Encoding.ASCII, "text/plain")
                       Return resp
                   End Function)

        Return task1
    End Function

	Namespace Applications
	'This is the class that I want all of the form data elements bound to.
    Public Class General
        Public Property FirstName As String
        Public Property LastName As String
        Public Property Address1 As String
        Public Property Address2 As String
        Public Property City As String
        Public Property State As String
        Public Property ZipCode As String
        Public Property PhoneCell As String
        Public Property PhoneHome As String
        Public Property Email As String
        Public Property Available As String
        Public Property Salary As String
        Public Property CurrentEmployed As Boolean
        Public Property HighSchool As String
        Public Property College As String
        Public Property Training As String
        Public Property ResumeDoc As String
    End Class
End Namespace

Looking for quality web hosting? Look no further than Arvixe Web Hosting!

Tags: , , , , , , , , , , | Posted under ASP .NET 4.0, Programming/Coding | RSS 2.0

Author Spotlight

David Bauernschmidt

David Bauernschmidt

I live in the historical triangle of Virginia where I am married with two daughters. I have spent over 13 years working for a Fortune 500 company in the computer area. I started in VB 6.0 and by the time I ended my employment I was supervising a development team where we built many web applications. When my first daughter was born I wanted to spend more time with her so I left and became a programmer analyst for local government as well as launch my own company. Since then I have grown James River Webs into a profitable web design and application company helping small businesses create a big presence on the internet. As an employee I have created web application used by citizens and other companies. I enjoy fly fishing, and spending time with my family. I also enjoy learning new approaches and development tools when it comes to developing applications.

Leave a Reply

Your email address will not be published. Required fields are marked *


+ 1 = 7

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>