Uploading files using ExtJS and ASP.NET MVC

Introduction

Recently I’ve been researching a lot about the use of ExtJS JavaScript framework along with ASP.NET MVC to build very rich Web applications. I’m very comfortable and the more I read, the more I like ExtJS along with ASP.NET MVC, so I’m digging more and more about finding new applications of ExtJS. In this article, I want to talk about uploading files using ExtJS and ASP.NET MVC.

Getting started with the solution

The first step is to create a MVC application in Visual Studio.NET 2008 (see Figure 1).

Figure 1

Next step is to add the ExtJS library files to the ASP.NET MVC project. Let’s add the following files and directories into the Scripts directory: ext-all.js, ext-base.js and resources directory (see Figure 2).

Figure 2

In order to implement the logic to upload files into our site, we’re going to use an extension to the TextField component. This new component is not included in the ExtJS distribution. Let’s create a file named fileuploadfield.js inside the ext directory and a file named fileuploadfield.css inside the ext/resources/css directory (see Figure 3).

Figure 3

Now let’s include the ExtJS library files in our solution by going to the Site.Master page and adding the references to the ExtJS files inside the head element (highlighted in yellow in the Listing 1). As well, we need to add a <asp:ContentPlaceHolder> tag element as container of the customized JavaScript and CSS code for each page (highlighted in green in the Listing 1).

<head runat=”server”>

<title><asp:ContentPlaceHolder ID=”TitleContent” runat=”server” /></title>

<link href=”../../Content/Site.css” rel=”stylesheet” type=”text/css” />

<!– Include the ExtJS framework –>

<link href=”../../Scripts/ext/resources/css/ext-all.css” rel=”stylesheet” type=”text/css” />

<script type=”text/javascript” src=”../../Scripts/ext/ext-base.js”></script>

<script type=”text/javascript” src=”../../Scripts/ext/ext-all.js”></script>

<!– Placeholder to include CSS and JS files customized for each page –>

<asp:ContentPlaceHolder ID=”Scripts” runat=”server” />

</head>

Listing 1

Now we need to add code for the fileuploadfield element. The JavaScript code is shown in the Listing 2.

/*!

* Ext JS Library 3.0+

* Copyright(c) 2006-2009 Ext JS, LLC

* licensing@extjs.com

* http://www.extjs.com/license

*/

Ext.ns(‘Ext.ux.form’);

 

/**

* @class Ext.ux.form.FileUploadField

* @extends Ext.form.TextField

* Creates a file upload field.

* @xtype fileuploadfield

*/

Ext.ux.form.FileUploadField = Ext.extend(Ext.form.TextField,  {

/**

* @cfg {String} buttonText The button text to display on the upload button (defaults to

* ‘Browse…’).  Note that if you supply a value for {@link #buttonCfg}, the buttonCfg.text

* value will be used instead if available.

*/

buttonText: ‘Browse…’,

/**

* @cfg {Boolean} buttonOnly True to display the file upload field as a button with no visible

* text field (defaults to false).  If true, all inherited TextField members will still be available.

*/

buttonOnly: false,

/**

* @cfg {Number} buttonOffset The number of pixels of space reserved between the button and the text field

* (defaults to 3).  Note that this only applies if {@link #buttonOnly} = false.

*/

buttonOffset: 3,

/**

* @cfg {Object} buttonCfg A standard {@link Ext.Button} config object.

*/

 

// private

readOnly: true,

 

/**

* @hide

* @method autoSize

*/

autoSize: Ext.emptyFn,

 

// private

initComponent: function(){

Ext.ux.form.FileUploadField.superclass.initComponent.call(this);

 

this.addEvents(

/**

* @event fileselected

* Fires when the underlying file input field’s value has changed from the user

* selecting a new file from the system file selection dialog.

* @param {Ext.ux.form.FileUploadField} this

* @param {String} value The file value returned by the underlying file input field

*/

‘fileselected’

);

},

 

// private

onRender : function(ct, position){

Ext.ux.form.FileUploadField.superclass.onRender.call(this, ct, position);

 

this.wrap = this.el.wrap({cls:’x-form-field-wrap x-form-file-wrap’});

this.el.addClass(‘x-form-file-text’);

this.el.dom.removeAttribute(‘name’);

 

this.fileInput = this.wrap.createChild({

id: this.getFileInputId(),

name: this.name||this.getId(),

cls: ‘x-form-file’,

tag: ‘input’,

type: ‘file’,

size: 1

});

 

var btnCfg = Ext.applyIf(this.buttonCfg || {}, {

text: this.buttonText

});

this.button = new Ext.Button(Ext.apply(btnCfg, {

renderTo: this.wrap,

cls: ‘x-form-file-btn’ + (btnCfg.iconCls ? ‘ x-btn-icon’ : ”)

}));

 

if(this.buttonOnly){

this.el.hide();

this.wrap.setWidth(this.button.getEl().getWidth());

}

 

this.fileInput.on(‘change’, function(){

var v = this.fileInput.dom.value;

this.setValue(v);

this.fireEvent(‘fileselected’, this, v);

}, this);

},

 

// private

getFileInputId: function(){

return this.id + ‘-file’;

},

 

// private

onResize : function(w, h){

Ext.ux.form.FileUploadField.superclass.onResize.call(this, w, h);

 

this.wrap.setWidth(w);

 

if(!this.buttonOnly){

var w = this.wrap.getWidth() – this.button.getEl().getWidth() – this.buttonOffset;

this.el.setWidth(w);

}

},

 

// private

onDestroy: function(){

Ext.ux.form.FileUploadField.superclass.onDestroy.call(this);

Ext.destroy(this.fileInput, this.button, this.wrap);

},

 

 

// private

preFocus : Ext.emptyFn,

 

// private

getResizeEl : function(){

return this.wrap;

},

 

// private

getPositionEl : function(){

return this.wrap;

},

 

// private

alignErrorIcon : function(){

this.errorIcon.alignTo(this.wrap, ‘tl-tr’, [2, 0]);

}

 

});

 

Ext.reg(‘fileuploadfield’, Ext.ux.form.FileUploadField);

 

// backwards compat

Ext.form.FileUploadField = Ext.ux.form.FileUploadField;

Listing 2. Content of the fileuploadfield.js file

The content of the styles for the uploadfilefield is shown in the Listing 3.

/*!

* Ext JS Library 3.0+

* Copyright(c) 2006-2009 Ext JS, LLC

* licensing@extjs.com

* http://www.extjs.com/license

*/

/*

* FileUploadField component styles

*/

.x-form-file-wrap {

position: relative;

height: 22px;

}

.x-form-file-wrap .x-form-file {

position: absolute;

right: 0;

-moz-opacity: 0;

filter:alpha(opacity: 0);

opacity: 0;

z-index: 2;

height: 22px;

}

.x-form-file-wrap .x-form-file-btn {

position: absolute;

right: 0;

z-index: 1;

}

.x-form-file-wrap .x-form-file-text {

position: absolute;

left: 0;

z-index: 3;

color: #777;

}

Listing 3. Content of the fileuploadfield.cs file

Next step is to add a controller and a default view to the ASP.NET MVC solution (see Figure 4).

Figure 4

 

Right-click on the Index action method of the UploadFileController class and select Add View option from the context menu (see Figure 5).

Figure 5

Now let’s create another JS file in the Scripts directory with necessary JS code to create a form and an uploadfilefield element. The code for the UploadFileFieldFom.js is shown in the Listing 4. In this file, you can see that we are creating a FormPanel object which will be rendered into div element named fileupload. In this case, the fileUpload property is set to true. The items array contains just the fileuploadfile element. The name property in the fileuploadfile element is the parameter with the information of the file to be uploaded to the server. The buttons property contains the buttons of the forms and its underlying action handler. In this code, the most important thing is the url property which points in this case to uploadfile/upload. The waitMsg is the message to be shown to the user. The success property references to a function to be called when then everything is OK while the failure property references a function to be called when an error occurs.

Ext.onReady(function()

{

var form = new Ext.FormPanel({

renderTo: ‘fileupload’,

fileUpload: true,

width: 400,

frame: true,

title: ‘File Upload’,

bodyStyle: ‘padding: 10px 10px 0 10px;’,

labelWidth: 50,

items: [{

xtype: ‘fileuploadfield’,

emptyText: ‘Select a file’,

fieldLabel: ‘File’,

name: ‘file’,

buttonText: ‘Choose a file’

}],

buttons: [{

text: ‘Save’,

handler: function()

{

if (form.getForm().isValid())

{

form.getForm().submit({

url: ‘uploadfile/upload’,

waitMsg: ‘Please, wait while uploading a file…’,

success: function(form, o)

{

Ext.Msg.show({

title: ‘Result’,

msg: o.result.result,

buttons: Ext.Msg.OK,

icon: Ext.Msg.INFO

});

},

failure: function(form, o)

{

Ext.Msg.show({

title: ‘Result’,

msg: o.result.error,

buttons: Ext.Msg.OK,

icon: Ext.Msg.ERROR

});

}

});

}

}

}]

});

});

Listing 4. Content in the UploadFileFieldFom.js file

Let’s include the fileuploadfield.css, fileuploadfield.js and uploadfilefieldfom.js (highlighted in yellow) files as well as the div (highlighted in green) element (where the form will be rendered) into the Index.aspx page (see Listing 5).

<%@ Page Title=”” Language=”C#” MasterPageFile=”~/Views/Shared/Site.Master” Inherits=”System.Web.Mvc.ViewPage” %>

 

<asp:Content ID=”Content1″ ContentPlaceHolderID=”TitleContent” runat=”server”>

Index

</asp:Content>

 

<asp:Content ID=”Content2″ ContentPlaceHolderID=”MainContent” runat=”server”>

 

<h2>Index</h2>

<div id=”fileupload”>

</div>

</asp:Content>

 

<asp:Content ID=”Content3″ ContentPlaceHolderID=”Scripts” runat=”server”>

<link href=”../../Scripts/ext/resources/css/fileuploadfield.css” rel=”stylesheet” type=”text/css” />

<script type=”text/javascript” src=”../../Scripts/ext/fileuploadfield.js”></script>

<script type=”text/javascript” src=”../../Scripts/uploadfilefieldfom.js”></script>

</asp:Content>

Listing 5

As you know from the configuration of the fileuploadfield JS element, we’re going to execute a POST HTTP request to the url uploadfile/upload, so we need to implement the Upload action method on the UploadFileController.css class. This action method must be annotated with AcceptVerbsAttribute attribute HttpVerbs.Post value. Then we need to check if the file was uploaded successfully by checking the Request.Files[“file”] where the file key was setup in the ExtJS fileuploadfield component. Finally, we return a message using JSON format with error or success information (see Listing 6).

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.Mvc;

using System.Web.Mvc.Ajax;

 

namespace UploadFiles_ExtJS_MvcApp.Controllers

{

public class UploadFileController : Controller

{

//

// GET: /UploadFile/

 

public ActionResult Index()

{

return View();

}

 

[AcceptVerbs(HttpVerbs.Post)]

public ActionResult Upload()

{

HttpPostedFileBase postedFile = Request.Files[“file”];

JsonResult objResult = null;

if (postedFile != null)

{

objResult = new JsonResult()

{

ContentType = “text/html”,

Data = new { success = true, result = “File uploaded successfully” }

};

}

else

{

objResult = new JsonResult()

{

ContentType = “text/html”,

Data = new { success = false, error = “File uploaded error” }

};

}

 

return objResult;

}

 

}

}

Listing 6

Let’s run the solution and see the results (see Figure 6).

Figure 6

Conclusion

In this article, I’ve illustrated how to upload files using ExtJS and ASP.NET MVC. Now you can apply this solution to your own business problems.

One thought on “Uploading files using ExtJS and ASP.NET MVC

  1. Pingback: MVP Factor

Leave a comment