Hi Guys!! I never thought building offline MVC
3 app could be this much simple.
I had a question in my mind for a long time: Why this offline application? How
it works? Etc..
As per my knowledge, in Silverlight there is a smart client concept. So that,
even we can see and work when there is no network available (flight mode or in
remote area). Whenever device/app detects network, then either the user can
invoke saving operation into server or the application can automatically
triggers event to save data.
Silverlight did a great job in this aspect. But, in the case of an ASP.NET/HTML
application, how can it be done?.
For the same purpose, HTML 5 introduces a MIME type manifest and local storage.
It mainly adds one manifest file to load all required recourses.
This walkthrough is to demonstrate how we can create/develop offline/online
application using MVC 3.
I will first create an ASP.NET MVC 3 empty app using VS 2010 and I will add
offline htm page to the project.
The HTML page will look like:
The first line uses the HTML5 doctype and the header links to jQuery. We use two
buttons, one to create the profiles in the browser local storage and another the
send the profiles to the server.
To create red boxes around our input boxes when jQuery detects some validation
we need to add these few lines of css to stylesheet:
input.error
{
border:
2px solid red;
}
Now it's time to implement our UI logic with javascript. By creating a separate
file for our javascript we keep the HTML page clean.
Add a "offline.js" to the script folder:
var
root = '/Offline;//Controller
name.
var
subscriptionsUploaded = 0;
//jQuery on document ready handler
$(function
() {
//Show the busy indicator during ajax
calls
$("#busy").hide();
$("#busy").ajaxStart(function
() { $("#busy").show();
})
$("#busy").ajaxStop(function
() { $("#busy").hide();
})
var x =
$("#createSubscription");
//When the createSubscription button is
clicked create a subscription
$("#create_subscription").click(createSubscriptionClick);
//When the sendData button is clicked
retrieve the subscriptions stored in the local storage and send the data to the
server
$("#send_data").click(sendDataClick);
//Define jQuery validation rules and
execute the validation when the form is validated
$("#sub_form").validate({
rules: {
firstname: {
required: true,
minlength: 2
},
lastname: {
required: true,
minlength: 2
},
email: {
required: true,
email: true
},
phone: {
required: true,
number: true,
minlength: 9,
maxlength: 9
}
},
messages: {
firstname: "",
lastname: "",
email: "",
phone: ""
}
});
});
function
sendDataClick() {
//Iterate over the subscriptions stored in
the local storage
for
(var i = 0; i
< window.localStorage.length; i++) {
//Retrieve the serialized
subscription
var
json = window.localStorage.getItem(window.localStorage.key(i));
try {
//Send the subscription to the
server
sendData(
json,
//On success remove the
subscription from the local storage
function
(data) {
window.localStorage.removeItem(window.localStorage.key(data.Message));
subscriptionsUploaded++;
$("#resultmessage").html(subscriptionsUploaded
+ " subscriptions uploaded!");
},
//On error
function (xhr) {
alert(xhr.responseText);
});
}
catch (e) { alert(e);
}
};
}
//Stores a subscription into the local storage
function createSubscriptionClick()
{
//check the jQuery validation rules
if ($("#sub_form").valid())
{
var person = getSubscription();
//seialize the subscription
var jsData = JSON.stringify(person);
//store the subscription
window.localStorage.setItem($("#email").val(), jsData);
//update the resultMessage
$("#resultmessage").html($("#email").val() + " stored in local storage");
clearAll();
}
}
//Create a subscription object and bind to the input boxes values
function getSubscription()
{
var firstname = $("#firstname").val();
var lastname = $("#lastname").val();
var email = $("#email").val();
Lastname: lastname, Email: email, Phone: phone };
}
//Clear the input boxes values
function clearAll()
{
$("#firstname").attr("value", "");
$("#lastname").attr("value", "");
$("#email").attr("value", "");
$("#phone").attr("value", "");
}
//Ajax: post the json serilized subscriptions
function sendData(json, success, error)
{
$.ajax(
{
url: root + '/save',
type: 'POST',
dataType: 'json',
data: json,
contentType: 'application/json; charset=utf-8',
success: success,
error: error
});
To get data from the controller side we can use a JSON format as given bellow.
In js file we can use
$.getJSON(
//controller name.
root + '/GetDataFromServer',
"",
function (data) {
});
When the user click on the create button the createSubscription function is called, this function is responsible for serializing the data into a Json object and
to store it in the isolated storage. Isolated storage is a feature defined in the Html5 spec. For each domain the browser provide access to private key/value
pair collection where data can be stored and retrieved. The sendData button is attached with an anonymous function that iterate over the key/value pair
collection that contains the JSON serialized subscriptions and post the JSON serialized subscription object.
MVC 3 includes built-in JSON binding support that enables action methods to receive JSON-encoded data and model-bind it to action-method
parameters.
We will now create our Model to bind to, add a OfflineModel class to the models of the MVC app:
public class OfflineModel
{
[Required]
[Display(Name = "Firstname")]
public string Firstname { get; set; }
[Required]
[Display(Name = "Lastname")]
public string Lastname
{ get; set; }
[Display(Name = "Phone")]
public string Phone { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email address")]
public string Email { get; set; }
public void Save()
{
//store the object in db
//...
}
}
In the controller, I have written sample code for returning some data.
public ActionResult GetDataFromServer()
{
List<Scoreboard> lstscores = new List<Scoreboard>();
try
{
//Return format to the client side.
return Json(
new { message = lstscores },
JsonRequestBehavior.AllowGet);
}
catch
{
throw;
}
}
In case, we need to bind these data to any controller like table/list etc, then
we can create item list dynamically.
Here "data" is the JSON array of data. Here I am creating rows and adding it
into existing table.
for
(var i = 0; i < data.message.length; i++) {
$("table#lst_info").find('tbody')
//Column Agency
.append($('<tr>')
.append($('<td style="width:300">')
.append($('<label >')
.text(data.message[i].Agency)
)
)
//Column Actual
.append($('<td style="width:300">')
.append($('<label >')
.text(data.message[i].Actual)
)
)
//Column Target
.append($('<td style="width:300">')
.append($('<label >')
.text(data.message[i].Target)
)
)
//Column Score
.append($('<td style="width:300">')
.append($('<label >')
.text(data.message[i].Score)
)
)
);
}
Now, we can test the application.
To be able to load the application when we are offline we need to use a new
feature available in the latest browser like IE9, the Html5:"offline
application.
Add the Offline.manifest file to the root of the application.
CACHE MANIFEST
/Offline.htm
/Content/Site.css
/Scripts/Offline.js
/Scripts/jquery-1.5.1.min.js
/Scripts/jquery.validate.min.js
/Content/wait.gif
Change the Doctype of the Offline.htm
//<html
manifest="Offline.manifest">//
So, now even when network is not available, the client can display the page.
Let's have a fun!!!!!
Storing data over local storage:
As of you all know, there are two types of web storage.
-
Localstorage.
-
Session storage.
But, In this article, we will discuss about
localstorage.
In simple, we can add data to local storage as like this.
window.localStorage.setItem("data","Hi
this is Aravind");
Retrieving data from localstorage…
var
datadt = window.localStorage.getItem("data");
Suppose, if I want to save list or array, then what can be done?.
Then, we have to convert list/array into JSON format.
window.localStorage.setItem("data", JSON.stringify(data));
Retrieving it as
var frequentdatadt =
window.localStorage.getItem("data");
var data = JSON.parse(frequentdatadt);