Pages

Thursday, April 7, 2011

Implement File upload using ASP.NET MVC2,0 and AjaxFileUploader

This blog explains implemention of file upload using ASP.NET MVC2.0

In MVC, generally to retrieve the controlls value in th post method we either use form collection or pass a parameter in the post mehtod with the name of the control. Now this parameter will have the value of the control. But this is slightly different while using file uploader expecially for mapping to virtual path.

Concept:
  1. Create the html code for uplaoder and display tje list of file.
  2. Define the javascript to be called on upload click. Which helps to read the uploaded file. And finally display in the list.

To implement, here we use ajax file uploader. Thus in aspx give the following.

For file upload control : 
< input type="file" id="document" name="document" />
The above code renders the uploader control.

input type="submit" name="Submit" id="Submit" value="Upload" onclick="UploadFile()" />
 The above code renders a button, which calls the javascript UploadFile on the button click.


table id="tblAttachments" cellpadding="3" cellspacing="0"
  tr
     td   /td
  /tr
/table
The above code is used to list the uploaded file names in a table formate.

In javascript the UploadFile() is defined as below:
 function UploadFile() {      
    if ($("#document").val() == '') {   //this is called when no file is been selected          
           alert('Please select a valid document.');
           return false;
     }
     $.ajaxFileUpload({
          
          url: "< % = Url.Content("~/Sample/CreateAttachment_Post") %  >;", // For any parameters use - + "?param1=" + document.getElementById('id').value, 
          data: { val: 'aaa' },
          secureuri: false,
          fileElementId: 'document',
          dataType: 'xlm',
          
          success: function (data, status) { //On success append the data to the table. This avoid the DB interaction once again for retrival after the upload.
               //The following code helps to add the uploaded file to the list display using the table tblAttachments.
              
               var appendString = "tr";
               appendString += ' td class="attach" id="ttt' + data + '" style="text-align:left;"> /td /tr';
               $("#tblAttachments tr:last").after(appendString);
               $("#tblAttachments tr:last").children(".attach").text(data);
           },
          
           error: function (data, status, e) { // For any errors or exceptions.               alert(e);
           }
    });
    return false;
}

This ajaxFileUpload is used to retrieve the virtual file path of the uploaded file. to use this method, need to include ajaxFileUpload.js.
      The above ajax code helps to call a method from controller by using the URL property. in URL we define the controller name and the method to be called.
      Any parameters could be passed using the querystring logic or by usig the data property.
      Here the fileElementId property defines the fileUpload control name which would be retrieved in the method called from URL.
      The Success is called on successfull execution of the method called by URL and the returned values of the method can be retrieved here using function (data, status) . wherein the data contains the returned value.
      In the above example, on successfull execution of the method we add the uploaded file name to the list displayed in the table format.
    Any exceptions could be caught with the help of error property.

Now in the controlelr part we need to define the
CreateAttachment_Post method which is called by the ajaxFileUpload.
The following code defines the CreateAttachment_Post

public void CreateAttachment_Post()
{       
        try
       {
              string fileName = string.Empty;
              foreach (string upload in Request.Files)  // all those file uplod controls defined in fielElementId property will get included in the Request.Files.             {
                   string mimeType = Request.Files[upload].ContentType;
                   Stream fileStream = Request.Files[upload].InputStream;
                   int fileLength = Request.Files[upload].ContentLength;
                   byte[] fileData = new byte[fileLength];
                   fileStream.Read(fileData, 0, fileLength);
                   fileStream.Close();
                   fileName = Request.Files[upload].FileName.Substring(Request.Files[upload].FileName.LastIndexOf(@"\") + 1, Request.Files[upload].FileName.Length - (Request.Files[upload].FileName.LastIndexOf(@"\") + 1));
                   Response.Write(fileName);                
           }
      }
      catch (Exception ex)
      {
                 throw ex;
      }
}

Handling multiple button clicks in same View using ASP.NET MVC2,0

This post explains, how to handle multiple button click events in the same page using ASP.NET MVC.

One basic thing to remember is, when ever you have any post methods to be performed, you need to have all your controls within the begin form.

The following methods explains to implement multiple buttons

Method 1:
        Each button should be defined within its own begin form. So on click, post method would be called only for the form which caused the post action. Thus in the post ActionResult method - the form collection would contain only the respective button which we clicked.
And in action result method, we coud have a if condition with the button name, and inside the if we could have the respective click functionality to be performed

Drawback: In post method we can retrieve only those controls within the begin form where the button is defined. Thus this method will not be appt when we want to access the controls by different buttons.

Method 2:
       In all the input tags, specify the same name field and different value field. By doing this, in the post method, with what ever the button is clicked, we would have the same name for all the buttons. Thus this button could be retrieved by using form collection or by having button name as one of the parameter in the post method.
Once the method is posted, in the post action result, can have multiple if conditions with input tag's value check, and for the corresponding value - can call the button click funtionality to be performed.

Example:
in aspx page:


input type="submit" name ="ButtonClick" value="Button1" title="Click Button1"
input type="submit" name ="ButtonClick" value="Button2" title="Click Button2"
input type="submit" name ="ButtonClick" value="Button3" title="Click Button3"


public ActionResult MultipleButtonsInSamePage(string ButtonClick)
{
       if (ButtonClick.Equals("Button1"))
      {
           //Perform function for button1 click
      }
      else if (ButtonClick.Equals("Button2"))
     {
          //Perform function for button2 click
     }
     else if (ButtonClick.Equals("Button3"))
     {
         //Perform function for button2 click
     }
     return View();
}

Handling Custom Errors in ASP.NET MVC2.0

When an error occurs in your ASP.NET application you are given a nice browser yellow screen of death. To fix this ASP.NET provides a method to redirect to a common page with user friendly message.

This can be achieved using ASP.NET MVC2.0 by the following steps.

1. Include the following in the web.config under System.Web tag

< customErrors mode="On" redirectMode="ResponseRedirect" defaultRedirect="~/Sample/ErrorPage" >
< error statusCode="404" redirect="~/Sample/PageNotFound"/>
< /customErrors >

This helps to dedirect a default page. Here for the 404 errors the page is redirected to PageNotFound and for any unhandled status code errors the page is redirected to ResponseRedirect.

Here the page redirect syntax is Controller/Action

2. To retrieve the stack trace error message, use Application_Error method in Global.ascx

The following code snipet helps to retrive the stack trace message and finally redirect to a error page with user friendly error message.

protected void Application_Error(object sender, EventArgs e)
{
       HttpContext ctx = System.Web.HttpContext.Current;
       Exception exception = ctx.Server.GetLastError();
       Response.Clear();
       Context.ClearError();
       var routeData = new RouteData();
       routeData.Values["controller"] = "Sample";
       routeData.Values["action"] = "ErrorPage";
       routeData.Values["ex"] = exception;
      Object obj = new object();
      if (exception != null)
     {
           string exMsg = "User: '" + User.Identity.Name + "' DateTime: '" + DateTime.Now.ToString("yyyy-MMM-dd HH:mm:ss") + "'" + Environment.NewLine +
"Source: " + exception.Source + Environment.NewLine +
"Message: " + exception.Message + Environment.NewLine +
"Inner Exception: " + exception.InnerException + Environment.NewLine +
"Stack trace: " + exception.StackTrace;
          WriteToLogFile(exMsg);
    }
    IController sample = new SampleController();
    sample.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
}

When "Application_Error" method is used, the custom redirect page specified in the WebConfig doesnt work. We need to give redirect from the "Application_Error" method by creating an object of controller and calling the specific ActionResult.

Implement Page Redirect methods in ASP.NET MVC2.0

This blog explains the different methods that could be used for page redirection.

Method 1:
Using ActionLink. By using the Html.ActionLink, can specify the link name, the action name to be called and the controller name where the action is defined. Also can specify any arugements/parameters if exist. Thus, here on clicking the link - the controller will be moved to the action method which is defined and its respective return view() will be returned.

Method 2:
By using return View(). Any action method should return a View. Thus, for page navigation one can use this method by specifying the View name and the parameters if any. But, the control will not be moved to the navigated get Mehtod. All the required initial values has to be again defined in the existing action method, this makes the view to be reurned from the existing action method.
The main drawback of this method is - code duplication.

Method 3:
By using RedirectToAction(). Control can be passed from one Action method to another Action method using RedirectToAction(). So, in the current Action method - when we want to navigate to another page we give return RedirectToAction("action name"). Thus, this would call up the action method specified and its respective return View() is been rendered. Using this method one can pass the action name, controller name and the parameters if any.
Advantage: Avoid code duplication
example :
return RedirectToAction("DestinationPage", new { page = 1 });
where page is the parameter name.

In all the three methods the parameter name to be specified are case sensitive.

Passing value from Controller to HTML controls in Views in ASP.NET MVC2,0

This blog explains how to pass a value from Controller to the html controls used in Views.

For temporary storage we use ViewData["name"] or TempData["name"]. In controller the values are stored in one of these temporary storages, and the views could read the values and finally typecasted to the html control's value type and then binded to the control.

Example:
Consider we need to pass value to an textbox.

in controller we give
ViewData["TextBox"] = "Textbox value";
in View we give :
< %= Html.TextBox("txtBox", ViewData["TextBox"].ToString())% >

In case of dropdowlist or listbox - need to typecast as (IEnumerable)ViewData["name"] .. and while storing to the view data - need to store a list of values.