European ASP.NET MVC Hosting

BLOG about Latest ASP.NET MVC Hosting and Its Technology - Dedicated to European Windows Hosting Customer

European ASP.NET MVC 4 Hosting - Amsterdam :: How to upload a file in MVC4

clock February 27, 2013 05:38 by author Scott

Uploading a file in Asp.Net MVC application is very easy. The posted file is automatically available as a HttpPostedFileBase parameters in the action of the controler. For uploading a file on the server you required to have a file input control with in html form having encoding type set to multipart/form-data. The default encoding type of a form is application/x-www-form-urlencoded and this is no sufficient for posting a large amount of data to server.

1. Form for uploading the file

@using (Html.BeginForm("FileUpload", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
 @Html.ValidationSummary();
 <ol>
 <li class="lifile">
 <input type="file" id="fileToUpload" name="file" />
 <span class="field-validation-error" id="spanfile"></span>
 </li>
 </ol>
 <input type="submit" id="btnSubmit" value="Upload" />
}

2. Validating the file on client side

<script type="text/jscript">
//get file size
function GetFileSize(fileid) {
 try
 {
 var fileSize = 0;
 //for IE
 if ($.browser.msie)
 {
 //before making an object of ActiveXObject,
 //please make sure ActiveX is enabled in your IE browser
 var objFSO = new ActiveXObject("Scripting.FileSystemObject"); var filePath = $("#" + fileid)[0].value;
 var objFile = objFSO.getFile(filePath);
 var fileSize = objFile.size; //size in kb
 fileSize = fileSize / 1048576; //size in mb
 }
 //for FF, Safari, Opeara and Others
 else
 {
 fileSize = $("#" + fileid)[0].files[0].size //size in kb
 fileSize = fileSize / 1048576; //size in mb
 }
 return fileSize;
 }
 catch (e)
 {
 alert("Error is :" + e);
 }
} 

//get file path from client system
function getNameFromPath(strFilepath)
{
 var objRE = new RegExp(/([^\/\\]+)$/);
 var strName = objRE.exec(strFilepath);

 if (strName == null)
 {
 return null;
 }
 else
 {
 return strName[0];
 }
} 

$("#btnSubmit").live("click", function ()
{
 if ($('#fileToUpload').val() == "")
 {
 $("#spanfile").html("Please upload file");
 return false;
 }
 else
 {
 return checkfile();
 }
}); 

function checkfile()
{
 var file = getNameFromPath($("#fileToUpload").val());
 if (file != null)
 {
 var extension = file.substr((file.lastIndexOf('.') + 1));
 // alert(extension);
 switch (extension) {
 case 'jpg':
 case 'png':
 case 'gif':
 case 'pdf':
 flag = true;
 break;
 default:
 flag = false;
 }
 }
 if (flag == false)
 {
 $("#spanfile").text("You can upload only jpg,png,gif,pdf extension file");
 return false;
 }
 else
 {
 var size = GetFileSize('fileToUpload');
 if (size > 3)
 {
 $("#spanfile").text("You can upload file up to 3 MB");
 return false;
 }
 else
 {
 $("#spanfile").text("");
 }
 }
} 

$(function ()
{
 $("#fileToUpload").change(function () {
 checkfile();});
});
</script>

3. Controller's action for receiving the posted file

[HttpPost]
public ActionResult FileUpload(HttpPostedFileBase file)
{
 if (ModelState.IsValid)
 {
 if (file == null)
 {
 ModelState.AddModelError("File", "Please Upload Your file");
 }
 else if (file.ContentLength > 0)
 {
 int MaxContentLength = 1024 * 1024 * 3; //3 MB
 string[] AllowedFileExtensions = new string[] { ".jpg", ".gif", ".png", ".pdf" };

 if (!AllowedFileExtensions.Contains(file.FileName.Substring(file.FileName.LastIndexOf('.'))))
 {
 ModelState.AddModelError("File", "Please file of type: " + string.Join(", ",
AllowedFileExtensions));
 }

 else if (file.ContentLength > MaxContentLength)
 {
 ModelState.AddModelError("File", "Your file is too large, maximum allowed size is: " + MaxContentLength + " MB");
 }
 else
 {
 //TO:DO
 var fileName = Path.GetFileName(file.FileName);
 var path = Path.Combine(Server.MapPath("~/Content/Upload"), fileName);
 file.SaveAs(path);
 ModelState.Clear();
 ViewBag.Message = "File uploaded successfully";
 }
 }
 }
 return View();
}

How it Works

 



European ASP.NET MVC 4 Hosting - Amsterdam :: Simple Wizard Form in ASP.NET MVC 4

clock February 21, 2013 05:53 by author Scott

For small MVC sample application I’m fiddling with on my spare time, I wanted to be able to split my form up in smaller parts, much like the ASP.NET Wizard Control that is available to you when you are using Web Forms.

Basically I wanted a pretty simple Wizard, where I break up the input fields in a form in two or more steps, and display a summary at the end. I wanted the users to be able to step through the wizard without filling in required fields (just so they can get a grasp of the amount of info they would need to fill in), but of course they should be stopped when trying to submit it if anything is missing. I also wanted to avoid going to the server to retrieve a partial view for the summary.

The model I will use is pretty straight forward. It contains some fields for the user to fill inn, that I will split up in “Personal Details”, “Address” and “Contact Details”:

public class SimpleWizardFormModel : IValidatableObject
{
    [Required]
    [Display(Name = "First Name")]
    public string FirstName { get; set; }

    [Required]
    [Display(Name = "Last Name")]
    public string LastName { get; set; }

    [Display(Name = "Street Address")]
    public string Address { get; set; }

    [Required]
    [Display(Name = "Postal Code")]
    public string PostalCode { get; set; }

    [Required]
    [Display(Name = "City")]
    public string City { get; set; }

    [Display(Name = "Home Phone")]
    public string Phone { get; set; }

    [Display(Name = "Mobile Phone")]
    public string Mobile { get; set; }

    [Display(Name = "I'm at least 18 years old?")]
    public bool HasTurned18 { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (!HasTurned18)
            yield return new ValidationResult("You must be 18 or older.", new[] { "HasTurned18" });
    }
}

The view isn’t very complicated either:

@model SimpleWizardFormModel
@section head
{
    <style type="text/css">
        .wizard-step { display: none; }
        .wizard-confirmation { display: none; }
        .wizard-nav {  }
        .wizard-nav input[type="button"] { width: 100px; }
    </style>
}
@section script
{
    <script type="text/javascript">
        //*SNIP*
    </script>
}
<h2>Simple Wizard Form</h2>
@using (Html.BeginForm())
{
    <fieldset>
        <legend></legend>
        <div class="wizard-step">
            <h4>Personal Details</h4>
            <ol>
                <li>
                    @Html.LabelFor(m => m.FirstName)
                    @Html.TextBoxFor(m => m.FirstName)
                    @Html.ValidationMessageFor(m => m.FirstName)
                </li>
                <li>
                    @Html.LabelFor(m => m.LastName)
                    @Html.TextBoxFor(m => m.LastName)
                    @Html.ValidationMessageFor(m => m.LastName)
                </li>
                <li>
                    @Html.LabelFor(m => m.HasTurned18)
                    @Html.CheckBoxFor(m => m.HasTurned18)
                    @Html.ValidationMessageFor(m => m.HasTurned18)
                </li>
            </ol>
        </div>
        <div class="wizard-step">
            @**SNIP**@
        </div>
        <div class="wizard-step wizard-confirmation">
            <h4>Confirm</h4>
            <div id="field-summary"></div>
            <div id="validation-summary">
                <span class="message-error">Please correct the following errors;</span>
                @Html.ValidationSummary(true)
            </div>
        </div>
        <div class="wizard-nav">
            <input type="button" id="wizard-prev" value="<< Previous" />
            <input type="button" id="wizard-next" value="Next >>" />
            <input type="button" id="wizard-submit" value="Submit" />
        </div>
    </fieldset>
}

I’ve cut out the javascript as I will get back to that later, as well as a couple of the wizard steps since they are look just like step 1 (just with other input fields). Inside my Layout.cshtml-file I’m importing jquery, jquery.validate, jquery.validate.unobtrusive, and rendering the “head”-section (in the head-tag) and “script”-section (just before body-close-tag) seen above.

The most important “feature” of the view are the divs which have been given the “wizard-step”-class. These contains the various input fields and will become the (as the class name suggests) steps in the wizard that is presented to the user. Initially all these divs are hidden from the user (note the display –> none in the css styles), and the javascript will take care of showing the div that represents the current wizard step to the user.

And now the stuff which actually performs some work, the javascript:

function DisplayStep() {
    var selectedStep = null;
    var firstInputError = $("input.input-validation-error:first"); // check for any invalid input fields
    if (firstInputError.length) {
        selectedStep = $(".wizard-confirmation");
        if (selectedStep && selectedStep.length) { // the confirmation step should be initialized and selected if it exists present
            UpdateConfirmation();
        }
        else {
            selectedStep = firstInputError.closest(".wizard-step"); // the first step with invalid fields should be displayed
        }
    }
    if (!selectedStep || !selectedStep.length) {
        selectedStep = $(".wizard-step:first"); // display first step if no step has invalid fields
    }

    $(".wizard-step:visible").hide(); // hide the step that currently is visible
    selectedStep.fadeIn(); // fade in the step that should become visible

    // enable/disable the prev/next/submit buttons
    if (selectedStep.prev().hasClass("wizard-step")) {
        $("#wizard-prev").show();
    }
    else {
        $("#wizard-prev").hide();
    }
    if (selectedStep.next().hasClass("wizard-step")) {
        $("#wizard-submit").hide();
        $("#wizard-next").show();
    }
    else {
        $("#wizard-next").hide();
        $("#wizard-submit").show();
    }
}

The first method in my javascript, called “DisplayStep”, takes care of displaying the correct wizard step (typically this means the first step) when the view is loaded. if the view is loaded after submitting it to the server and server validation errors are found however, it will show the confirmation step if there is one, and if not it will show the first step which contains erroneous input. Once the correct step to show is found, it will decide where this step is located in relation to the other steps and show or hide the “previous”, “next” and “submit” buttons.

function PrevStep() {
    var currentStep = $(".wizard-step:visible"); // get current step

    if (currentStep.prev().hasClass("wizard-step")) { // is there a previous
step?


        currentStep.hide().prev().fadeIn();  // hide current step and display previous step

        $("#wizard-submit").hide(); // disable wizard-submit button
        $("#wizard-next").show(); // enable wizard-next button

        if (!currentStep.prev().prev().hasClass("wizard-step")) { // disable wizard-prev button?
            $("#wizard-prev").hide();
        }
    }
}

The “PrevStep” method is pretty straight forward. It just finds the current step, hides it, shows the previous one, and shows/hides the buttons. No validation is performed before navigation to the previous step, but if desired, this could be done just like in the “NextStep” shown below.

function NextStep() {
    var currentStep = $(".wizard-step:visible"); // get current step

    var validator = $("form").validate(); // get validator
    var valid = true;
    currentStep.find("input:not(:blank)").each(function () { // ignore empty fields, i.e. allow the user to step through without filling in required fields
        if (!validator.element(this)) { // validate every input element inside this step
            valid = false;
        }
    });
    if (!valid)
        return; // exit if invalid

    if (currentStep.next().hasClass("wizard-step")) { // is there a next step?

        if (currentStep.next().hasClass("wizard-confirmation")) { // is the next step the confirmation?
            UpdateConfirmation();
        }

        currentStep.hide().next().fadeIn();  // hide current step and display next step

        $("#wizard-prev").show(); // enable wizard-prev button
        if (!currentStep.next().next().hasClass("wizard-step")) { // disable wizard-next button and enable wizard-submit?
            $("#wizard-next").hide();
            $("#wizard-submit").show();
        }
    }
}

The “NextStep” is a little more complicated. In addition to performing pretty much the same tasks as the “PrevStep” (only the opposite), it validates all input fields in the current step, and if there are any errors, you won’t be allowed to go to the next step. It only validates none empty fields however, i.e. the required rule if applicable for a given field isn’t evaluated. This is done because I wanted the user to be able to step through the entire form to see how much needs to be filled in (you can easily change this by changing the part of the script where the input fields are found). If the next step has been given the “wizard-confirmation”-class a call is also made to setup/update the confirmation (the specifics of this function will be explained further down).

function Submit() {
    if ($("form").valid()) { // validate all fields, including blank required
fields

        $("form").submit();
    }
    else {
        DisplayStep(); // validation failed, redisplay correct step
    }
}

The last function related to navigation is “Submit”. This function validates the entire form (including required fields), and submits the form if all is good, or calls “DisplayStep” to show the confirmation step (if there is one), or the first step with errors on it (in cases where there are no confirmation step).

function UpdateConfirmation() {
    UpdateValidationSummary();
    var fieldList = $("<ol/>");
    $(".wizard-step:not(.wizard-confirmation)").find("input").each(function () {
        var input = this;
        var value;
        switch (input.type) {
        case "hidden":
            return;
        case "checkbox":
            value = input.checked;
            break;
        default:
            value = input.value;
        }
        var name = $('label[for="' + input.name + '"]').text();
        fieldList.append("<li><label>" + name + "</label><span>" + value + "&nbsp;</span></li>");
    });
    $("#field-summary").children().remove();
    $("#field-summary").append(fieldList);
}

function UpdateValidationSummary() {
    var validationSummary = $("#validation-summary");
    if (!validationSummary.find(".validation-summary-errors").length) { // check if validation errors container already exists, and if not create it
        $('<div class="validation-summary-errors"><ul></ul></div>').appendTo(validationSummary);
    }
    var errorList = $(".validation-summary-errors ul");
    errorList.find("li.field-error").remove(); // remove any field errors that might have been added earlier, leaving any server errors intact
    $('.field-validation-error').each(function () {
        var element = this;
        $('<li class="field-error">' + element.innerText + '</li>').appendTo(errorList); // add the current field errors
    });
    if (errorList.find("li").length) {
        $("#validation-summary span").show();
    }
    else {
        $("#validation-summary span").hide();
    }
}

The “UpdateConfirmation” function (and the “UpdateValidationSummary”-function called by this function) takes care of setting up / displaying the confirmation step. The “UpdateValidationSummary” function finds all input errors (if any) and adds them to the server validation error list (creating this list if it doesn’t already exist). The “UpdateConfirmation” function, in addition to calling “UpdateValidationSummary”, finds all input fields and associated labels and created a list with them that is displayed to the user.

$(function () {
    // attach click handlers to the nav buttons
    $("#wizard-prev").click(function () { PrevStep(); });
    $("#wizard-next").click(function () { NextStep(); });
    $("#wizard-submit").click(function () { Submit(); });

    // display the first step (or the confirmation if returned from server with errors)
    DisplayStep();
});

Last part of the javascript is where we hook up handlers for the navigation buttons and calls the function to display the first (or correct) step when the view is first loaded.

That was all the code needed, not to bad if I say so myself.

A couple of screens to show how it looks in action (first picture shows one of the steps, while the second picture shows the confirmation step):


As I said in the beginning, this wizard is pretty basic, but it works pretty good.

 



European ASP.NET MVC 4 Hosting - Amsterdam :: Optimization Performance MVC 4 with Bundling and Minification

clock February 12, 2013 04:37 by author Scott

MVC4 and .Net Framework 4.5 offer bundling and minification techniques that reduce the number of request to the server and size of requested CSS and JavaScript library, which improve page loading time.

What is Bundle?

A bundle is a logical group of files that is loaded with a single HTTP request. You can create style and script bundle for css and javascripts respectively by calling BundleCollection class Add() method with in BundleConfig.cs file.

Creating Style Bundle

bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.min.css",
"~/Content/mystyle.min.css"));

Creating Script Bundle

bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
 "~/Scripts/jquery-1.7.1.min.js",
 "~/Scripts/jquery.validate.min.js",
 "~/Scripts/jquery.validate.unobtrusive.min.js"));

Above both the bundles are defined with in BundleConfig class as shown below:

public class BundleConfig
{
 public static void RegisterBundles(BundleCollection bundles)
 {
 bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.min.css",
 "~/Content/mystyle.min.css"));

bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
 "~/Scripts/jquery-1.7.1.min.js",
 "~/Scripts/jquery.validate.min.js",
 "~/Scripts/jquery.validate.unobtrusive.min.js"));
 }
}

Creating Bundle using the "*" Wildcard Character

"*" wildcard character is used to combines the files that are in the same directory and have same prefix or suffix with its name. Suppose you want to add all the scripts files that exist with in "~/Script" directory and have "jquery" as prefix then you can create bundle like below:

bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include("~/Scripts/jquery*.js"));

You can also add all the css that exist with in "~/Content" directory and have ".css" extension(as suffix) like below:

bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/*.css"));

Registering Bundle

All bundles are registered with in Application_Start event of Global.asax file of you web application.

protected void Application_Start()
{
 BundleConfig.RegisterBundles(BundleTable.Bundles);
 // Other Code is removed for clarity
}

Minification

Minification is technique for removing unnecessary characters (like white space, newline, tab) and comments from the JavaScript and CSS files to reduce the size which cause improved load times of a webpage. There are so many tools for minifying the js and css files. JSMin and YUI Compressor are two most popular tools for minifying the js and css files.

You can also add WebEssentials2012.vsix extension to your VS2012 for minifying the js and css files. This is a great extension for VS2012 for playing with js and css.

Minification with VS2012 and WebEssentials 2012 extension

I would like to share how can you make minify version of you css file using WebEssentials extension and VS2012. This minify version will updated automatically if you will make change in original css file.

Performance Optimization with Bundling and Minification

I have done a performance test on a MVC4 application with & without bundling and minification. I have noticed the below result.

Without Bundling and Minification

I have the below css and js files on the layout page and run the application in chrome browser and test no of request and loding time using chrome developer tools as shown below.

<link href="~/Content/Site.css" rel="stylesheet"/>
<link href="~/Content/MyStyle.css" rel="stylesheet"/>
<script src="~/Scripts/jquery-1.7.1.js"></script>
<script src="~/Scripts/jquery-ui-1.8.20.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>

In this test, I have seen, There are 7 request, total data size is 3.96KB and loading time is approximate 296ms.

With Bundling and Minification

I have run the above application with Bundling and Minification of css and js files and test no of request and loding time using chrome developer tools as shown below.

@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/jquery")

In this test, I have seen, There are only 3 request, total data size is 2.67KB and loading time is approximate 80ms. In this way by using bundling and minification you have reduced the total no of request, size and loading time.

Enabling Bundling and Minification in debug mode

Bundling and minification doesn't work in debug mode. So to enable this featues you need to add below line of code with in Application_Start event of Global.asax.

protected void Application_Start()
{
 BundleConfig.RegisterBundles(BundleTable.Bundles);
 //Enabling Bundling and Minification
 BundleTable.EnableOptimizations = true;
 // Other Code is removed for clarity
}

Busting Browser's Cache by Bundling

As you know browsers cache resources based on URLs. When a web page requests a resource, the browser first checks its cache to see if there is a resource with the matched URL. If yes, then it simply uses the cached copy instead of fetching a new one from server. Hence whenever you change the content of css and js files will not reflect on the browser. For this you need to force the browser for refreshing/reloading.

But bundles automatically takes care of this problem by adding a hashcode to each bundle as a query parameter to the URL as shown below. Whenever you change the content of css and js files then a new has code will be generated and rendered to the page automatically. In this way, the browser will see a different url and will fetch the new copy of css and js.

I hope you will enjoy the tips while performance optimization of your MVC4 application.

 



European ASP.NET MVC 4 Hosting - Amsterdam :: Bundling and Minification of JavaScript and CSS ASP.NET MVC 4

clock February 8, 2013 05:32 by author Scott

ASP.NET MVC 4 beta has built in minification, which reduces the number of requests and general payload size, resulting in faster and better performing applications.

This feature allows you can create custom bundles where you specify the resource name and order of your stylesheets and JavaScript files.

Introducing ASP.NET MVC 4 BundleTables

Upon creating a new project in ASP.NET MVC 4, you'll notice that your default _Layout.cshtml file will reference System.Web.Optimization and BundleTable.Bundles in its head.

According to Microsoft, these references are for the beta and will be accessed via a helper in the RTM release, expected sometime next quarter.

<link href="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Content/css")" rel="stylesheet" type="text/css" />
<link href="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Content/themes/base/css")" rel="stylesheet"    type="text/css" />
<script src="@System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/Scripts/js")"></script>

If you look at the actual source code in the browser, you will see these get rendered as:

<link href="/Content/css?v=x" rel="stylesheet" type="text/css" />
<link href="/Content/themes/base/css?v=y" rel="stylesheet" type="text/css" />
<script src="/Scripts/js?v=z"></script>

The CSS and JavaScript files in this project are minified and compressed and the querystring parameter, v, is a hash of the current files being served. This will change when you alter your .js and .css files.



About HostForLIFE

HostForLIFE is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2019 Hosting, ASP.NET 5 Hosting, ASP.NET MVC 6 Hosting and SQL 2019 Hosting.


Month List

Tag cloud

Sign in